Skip to content

Commit

Permalink
split ValidatedBlock and AssembledBlock interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
cce committed Mar 27, 2024
1 parent 9c8211c commit c054b3c
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 62 deletions.
29 changes: 18 additions & 11 deletions agreement/abstractions.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,6 @@ type BlockValidator interface {
// and can now be recorded in the ledger. This is an optimized version of
// calling EnsureBlock() on the Ledger.
type ValidatedBlock interface {
// WithProposer creates a copy of this ValidatedBlock with its
// cryptographically random seed and proposer set. The block's
// ProposerPayout is zero'd if !eligible. Abstractly, it is how the
// agreement code "finishes" a block and makes it a proposal for a specific
// account.
//
// Calls to Seed() or to Digest() on the copy's Block must
// reflect the value of the new seed.
WithProposer(seed committee.Seed, proposer basics.Address, eligible bool) ValidatedBlock

// Block returns the underlying block that has been validated.
Block() bookkeeping.Block
}
Expand All @@ -87,7 +77,24 @@ type BlockFactory interface {
// produce a ValidatedBlock for the given round. If an insufficient number of
// nodes on the network can assemble entries, the agreement protocol may
// lose liveness.
AssembleBlock(basics.Round) (ValidatedBlock, error)
AssembleBlock(basics.Round) (AssembledBlock, error)
}

// An AssembledBlock represents a Block produced by a BlockFactory
// to be included in a proposal by agreement.
type AssembledBlock interface {
// WithProposer creates a copy of this AssembledBlock with its
// cryptographically random seed and proposer set. The block's
// ProposerPayout is zero'd if !eligible. Abstractly, it is how the
// agreement code "finishes" a block and makes it a proposal for a specific
// account.
//
// Calls to Seed() or to Digest() on the copy's Block must
// reflect the value of the new seed.
WithProposer(seed committee.Seed, proposer basics.Address, eligible bool) AssembledBlock

// Block returns the underlying block that has been assembled.
Block() bookkeeping.Block
}

// A Ledger represents the sequence of Entries agreed upon by the protocol.
Expand Down
4 changes: 2 additions & 2 deletions agreement/agreementtest/simulate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (b testValidatedBlock) Block() bookkeeping.Block {
return b.Inside
}

func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.ValidatedBlock {
func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.AssembledBlock {
b.Inside.BlockHeader.Seed = s
b.Inside.BlockHeader.Proposer = proposer
if !eligible {
Expand All @@ -98,7 +98,7 @@ type testBlockFactory struct {
Owner int
}

func (f testBlockFactory) AssembleBlock(r basics.Round) (agreement.ValidatedBlock, error) {
func (f testBlockFactory) AssembleBlock(r basics.Round) (agreement.AssembledBlock, error) {
return testValidatedBlock{Inside: bookkeeping.Block{BlockHeader: bookkeeping.BlockHeader{Round: r}}}, nil
}

Expand Down
4 changes: 2 additions & 2 deletions agreement/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (b testValidatedBlock) Block() bookkeeping.Block {
return b.Inside
}

func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) ValidatedBlock {
func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) AssembledBlock {
b.Inside.BlockHeader.Seed = s
b.Inside.BlockHeader.Proposer = proposer
if !eligible {
Expand All @@ -184,7 +184,7 @@ type testBlockFactory struct {
Owner int
}

func (f testBlockFactory) AssembleBlock(r basics.Round) (ValidatedBlock, error) {
func (f testBlockFactory) AssembleBlock(r basics.Round) (AssembledBlock, error) {
return testValidatedBlock{Inside: bookkeeping.Block{BlockHeader: bookkeeping.BlockHeader{Round: r}}}, nil
}

Expand Down
4 changes: 2 additions & 2 deletions agreement/fuzzer/ledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (b testValidatedBlock) Block() bookkeeping.Block {
return b.Inside
}

func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.ValidatedBlock {
func (b testValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.AssembledBlock {
b.Inside.BlockHeader.Seed = s
b.Inside.BlockHeader.Proposer = proposer
if !eligible {
Expand All @@ -112,7 +112,7 @@ type testBlockFactory struct {
Owner int
}

func (f testBlockFactory) AssembleBlock(r basics.Round) (agreement.ValidatedBlock, error) {
func (f testBlockFactory) AssembleBlock(r basics.Round) (agreement.AssembledBlock, error) {
return testValidatedBlock{Inside: bookkeeping.Block{BlockHeader: bookkeeping.BlockHeader{Round: r}}}, nil
}

Expand Down
30 changes: 20 additions & 10 deletions agreement/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,24 @@ type proposal struct {
validatedAt time.Duration
}

func makeProposal(ve ValidatedBlock, pf crypto.VrfProof, origPer period, origProp basics.Address) proposal {
func makeProposalFromAssembledBlock(blk AssembledBlock, pf crypto.VrfProof, origPer period, origProp basics.Address) proposal {
e := blk.Block()
var payload unauthenticatedProposal
payload.Block = e
payload.SeedProof = pf
payload.OriginalPeriod = origPer
payload.OriginalProposer = origProp
return proposal{unauthenticatedProposal: payload}
}

func makeProposalFromValidatedBlock(ve ValidatedBlock, pf crypto.VrfProof, origPer period, origProp basics.Address) proposal {
e := ve.Block()
var payload unauthenticatedProposal
payload.Block = e
payload.SeedProof = pf
payload.OriginalPeriod = origPer
payload.OriginalProposer = origProp
return proposal{unauthenticatedProposal: payload, ve: ve}
return proposal{unauthenticatedProposal: payload, ve: ve} // store ve to use when calling Ledger.EnsureValidatedBlock
}

func (p proposal) u() unauthenticatedProposal {
Expand Down Expand Up @@ -285,8 +295,8 @@ func payoutEligible(rnd basics.Round, proposer basics.Address, ledger LedgerRead
return eligible, balanceRecord, nil
}

func proposalForBlock(address basics.Address, vrf *crypto.VRFSecrets, ve ValidatedBlock, period period, ledger LedgerReader) (proposal, proposalValue, error) {
rnd := ve.Block().Round()
func proposalForBlock(address basics.Address, vrf *crypto.VRFSecrets, blk AssembledBlock, period period, ledger LedgerReader) (proposal, proposalValue, error) {
rnd := blk.Block().Round()

cparams, err := ledger.ConsensusParams(ParamsRound(rnd))
if err != nil {
Expand All @@ -303,15 +313,15 @@ func proposalForBlock(address basics.Address, vrf *crypto.VRFSecrets, ve Validat
return proposal{}, proposalValue{}, fmt.Errorf("proposalForBlock: could determine eligibility: %w", err)
}

ve = ve.WithProposer(newSeed, address, eligible)
proposal := makeProposal(ve, seedProof, period, address)
blk = blk.WithProposer(newSeed, address, eligible)
prop := makeProposalFromAssembledBlock(blk, seedProof, period, address)
value := proposalValue{
OriginalPeriod: period,
OriginalProposer: address,
BlockDigest: proposal.Block.Digest(),
EncodingDigest: crypto.HashObj(proposal),
BlockDigest: prop.Block.Digest(),
EncodingDigest: crypto.HashObj(prop),
}
return proposal, value, nil
return prop, value, nil
}

// validate returns true if the proposal is valid.
Expand All @@ -334,5 +344,5 @@ func (p unauthenticatedProposal) validate(ctx context.Context, current round, le
return invalid, fmt.Errorf("EntryValidator rejected entry: %w", err)
}

return makeProposal(ve, p.SeedProof, p.OriginalPeriod, p.OriginalProposer), nil
return makeProposalFromValidatedBlock(ve, p.SeedProof, p.OriginalPeriod, p.OriginalProposer), nil
}
18 changes: 18 additions & 0 deletions data/bookkeeping/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,24 @@ func (block Block) ProposerPayout() basics.MicroAlgos {
return block.BlockHeader.ProposerPayout
}

// WithProposer returns a copy of the Block with a modified seed and associated proposer
func (block Block) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) Block {
newblock := block
newblock.BlockHeader.Seed = s
// agreement is telling us who the proposer is and if they're eligible, but
// agreement does not consider the current config params, so here we decide
// what really goes into the BlockHeader.
proto := config.Consensus[block.CurrentProtocol]
if proto.Payouts.Enabled {
newblock.BlockHeader.Proposer = proposer
}
if !proto.Payouts.Enabled || !eligible {
newblock.BlockHeader.ProposerPayout = basics.MicroAlgos{}
}

return newblock
}

// NextRewardsState computes the RewardsState of the subsequent round
// given the subsequent consensus parameters, along with the incentive pool
// balance and the total reward units in the system as of the current round.
Expand Down
6 changes: 3 additions & 3 deletions data/datatest/impls.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type entryFactoryImpl struct {
}

// AssembleBlock implements Ledger.AssembleBlock.
func (i entryFactoryImpl) AssembleBlock(round basics.Round) (agreement.ValidatedBlock, error) {
func (i entryFactoryImpl) AssembleBlock(round basics.Round) (agreement.AssembledBlock, error) {
prev, err := i.l.BlockHdr(round - 1)
if err != nil {
return nil, fmt.Errorf("could not make proposals: could not read block from ledger at round %v: %v", round, err)
Expand All @@ -64,8 +64,8 @@ func (i entryFactoryImpl) AssembleBlock(round basics.Round) (agreement.Validated
return validatedBlock{blk: &b}, nil
}

// WithProposer implements the agreement.ValidatedBlock interface.
func (ve validatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.ValidatedBlock {
// WithProposer implements the agreement.AssembledBlock interface.
func (ve validatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.AssembledBlock {
newblock := *ve.blk
newblock.BlockHeader.Seed = s
newblock.BlockHeader.Proposer = proposer
Expand Down
24 changes: 0 additions & 24 deletions ledger/ledgercore/validatedBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
package ledgercore

import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/committee"
)

// ValidatedBlock represents the result of a block validation. It can
Expand All @@ -41,27 +38,6 @@ func (vb ValidatedBlock) Delta() StateDelta {
return vb.delta
}

// WithProposer returns a copy of the ValidatedBlock with a modified seed and associated proposer
func (vb ValidatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) ValidatedBlock {
newblock := vb.blk
newblock.BlockHeader.Seed = s
// agreement is telling us who the proposer is and if they're eligible, but
// agreement does not consider the current config params, so here we decide
// what really goes into the BlockHeader.
proto := config.Consensus[vb.blk.CurrentProtocol]
if proto.Payouts.Enabled {
newblock.BlockHeader.Proposer = proposer
}
if !proto.Payouts.Enabled || !eligible {
newblock.BlockHeader.ProposerPayout = basics.MicroAlgos{}
}

return ValidatedBlock{
blk: newblock,
delta: vb.delta,
}
}

// MakeValidatedBlock creates a validated block.
func MakeValidatedBlock(blk bookkeeping.Block, delta StateDelta) ValidatedBlock {
return ValidatedBlock{
Expand Down
26 changes: 18 additions & 8 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1290,20 +1290,30 @@ type validatedBlock struct {
vb *ledgercore.ValidatedBlock
}

// WithProposer satisfies the agreement.ValidatedBlock interface.
func (vb validatedBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.ValidatedBlock {
lvb := vb.vb.WithProposer(s, proposer, eligible)
return validatedBlock{vb: &lvb}
}

// Block satisfies the agreement.ValidatedBlock interface.
func (vb validatedBlock) Block() bookkeeping.Block {
blk := vb.vb.Block()
return blk
}

// assembledBlock satisfies agreement.AssembledBlock
type assembledBlock struct {
blk bookkeeping.Block
}

// WithProposer satisfies the agreement.ValidatedBlock interface.
func (ab assembledBlock) WithProposer(s committee.Seed, proposer basics.Address, eligible bool) agreement.AssembledBlock {
nb := ab.blk.WithProposer(s, proposer, eligible)
return assembledBlock{blk: nb}
}

// Block satisfies the agreement.AssembledBlock interface.
func (ab assembledBlock) Block() bookkeeping.Block {
return ab.blk
}

// AssembleBlock implements Ledger.AssembleBlock.
func (node *AlgorandFullNode) AssembleBlock(round basics.Round) (agreement.ValidatedBlock, error) {
func (node *AlgorandFullNode) AssembleBlock(round basics.Round) (agreement.AssembledBlock, error) {
deadline := time.Now().Add(node.config.ProposalAssemblyTime)
lvb, err := node.transactionPool.AssembleBlock(round, deadline)
if err != nil {
Expand All @@ -1324,7 +1334,7 @@ func (node *AlgorandFullNode) AssembleBlock(round basics.Round) (agreement.Valid
}
return nil, err
}
return validatedBlock{vb: lvb}, nil
return assembledBlock{blk: lvb.Block()}, nil
}

// getOfflineClosedStatus will return an int with the appropriate bit(s) set if it is offline and/or online
Expand Down

0 comments on commit c054b3c

Please sign in to comment.