Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

agreement: split ValidatedBlock and AssembledBlock interfaces #5967

Closed
wants to merge 10 commits into from
Closed
29 changes: 18 additions & 11 deletions agreement/abstractions.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +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 {
// WithSeed creates a copy of this ValidatedBlock with its
// cryptographically random seed set to the given value.
//
// Calls to Seed() or to Digest() on the copy's Block must
// reflect the value of the new seed.
WithSeed(committee.Seed) ValidatedBlock

// Block returns the underlying block that has been validated.
Block() bookkeeping.Block
}
Expand All @@ -72,19 +65,33 @@ var ErrAssembleBlockRoundStale = errors.New("requested round for AssembleBlock i
// An BlockFactory produces an Block which is suitable for proposal for a given
// Round.
type BlockFactory interface {
// AssembleBlock produces a new ValidatedBlock which is suitable for proposal
// AssembleBlock produces a new AssembledBlock which is suitable for proposal
cce marked this conversation as resolved.
Show resolved Hide resolved
// at a given Round.
//
// AssembleBlock should produce a ValidatedBlock for which the corresponding
// AssembleBlock should produce a block for which the corresponding
// BlockValidator validates (i.e. for which BlockValidator.Validate
// returns true). If an insufficient number of nodes can assemble valid
// entries, the agreement protocol may lose liveness.
//
// AssembleBlock may return an error if the BlockFactory is unable to
// produce a ValidatedBlock for the given round. If an insufficient number of
// produce a AssembledBlock 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
// and can now be proposed by agreement.
type AssembledBlock interface {
// WithSeed creates a copy of this AssembledBlock with its
// cryptographically random seed set to the given value.
//
// Calls to Seed() or to Digest() on the copy's Block must
// reflect the value of the new seed.
WithSeed(committee.Seed) 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) WithSeed(s committee.Seed) agreement.ValidatedBlock {
func (b testValidatedBlock) WithSeed(s committee.Seed) agreement.AssembledBlock {
b.Inside.BlockHeader.Seed = s
return b
}
Expand All @@ -94,7 +94,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) WithSeed(s committee.Seed) ValidatedBlock {
func (b testValidatedBlock) WithSeed(s committee.Seed) AssembledBlock {
b.Inside.BlockHeader.Seed = s
return b
}
Expand All @@ -180,7 +180,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) WithSeed(s committee.Seed) agreement.ValidatedBlock {
func (b testValidatedBlock) WithSeed(s committee.Seed) agreement.AssembledBlock {
b.Inside.BlockHeader.Seed = s
return b
}
Expand All @@ -108,7 +108,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
34 changes: 24 additions & 10 deletions agreement/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,28 @@ type proposal struct {
validatedAt time.Duration
}

func makeProposal(ve ValidatedBlock, pf crypto.VrfProof, origPer period, origProp basics.Address) proposal {
// makeProposalFromAssembledBlock is called when making a new proposal message,
// using the output of AssembleBlock (from makeProposals -> proposalForBlock)
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}
}

// makeProposalFromValidatedBlock is called after successfully validating a proposal message,
// using the output of BlockValidator.Validate (from unauthenticatedProposal.validate)
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 @@ -244,22 +258,22 @@ func verifyNewSeed(p unauthenticatedProposal, ledger LedgerReader) error {
return 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()
newSeed, seedProof, err := deriveNewSeed(address, vrf, rnd, period, ledger)
if err != nil {
return proposal{}, proposalValue{}, fmt.Errorf("proposalForBlock: could not derive new seed: %v", err)
}

ve = ve.WithSeed(newSeed)
proposal := makeProposal(ve, seedProof, period, address)
blk = blk.WithSeed(newSeed)
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 @@ -282,5 +296,5 @@ func (p unauthenticatedProposal) validate(ctx context.Context, current round, le
return invalid, fmt.Errorf("EntryValidator rejected entry: %v", err)
}

return makeProposal(ve, p.SeedProof, p.OriginalPeriod, p.OriginalProposer), nil
return makeProposalFromValidatedBlock(ve, p.SeedProof, p.OriginalPeriod, p.OriginalProposer), nil
}
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) {
cce marked this conversation as resolved.
Show resolved Hide resolved
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
}

// WithSeed implements the agreement.ValidatedBlock interface.
func (ve validatedBlock) WithSeed(s committee.Seed) agreement.ValidatedBlock {
// WithSeed implements the agreement.AssembledBlock interface.
func (ve validatedBlock) WithSeed(s committee.Seed) agreement.AssembledBlock {
cce marked this conversation as resolved.
Show resolved Hide resolved
newblock := ve.blk.WithSeed(s)
return validatedBlock{blk: &newblock}
cce marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down
19 changes: 13 additions & 6 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1295,20 +1295,27 @@
vb *ledgercore.ValidatedBlock
}

// WithSeed satisfies the agreement.ValidatedBlock interface.
func (vb validatedBlock) WithSeed(s committee.Seed) agreement.ValidatedBlock {
lvb := vb.vb.WithSeed(s)
return validatedBlock{vb: &lvb}
type assembledBlock struct {
blk bookkeeping.Block
}

// WithSeed satisfies the agreement.AssembledBlock interface.
func (ab assembledBlock) WithSeed(s committee.Seed) agreement.AssembledBlock {
blk := ab.blk.WithSeed(s)
return assembledBlock{blk: blk}

Check warning on line 1305 in node/node.go

View check run for this annotation

Codecov / codecov/patch

node/node.go#L1303-L1305

Added lines #L1303 - L1305 were not covered by tests
}

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

Check warning on line 1309 in node/node.go

View check run for this annotation

Codecov / codecov/patch

node/node.go#L1309

Added line #L1309 was not covered by tests

// Block satisfies the agreement.ValidatedBlock interface.
func (vb validatedBlock) Block() bookkeeping.Block {
blk := vb.vb.Block()
return 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) {

Check warning on line 1318 in node/node.go

View check run for this annotation

Codecov / codecov/patch

node/node.go#L1318

Added line #L1318 was not covered by tests
deadline := time.Now().Add(node.config.ProposalAssemblyTime)
lvb, err := node.transactionPool.AssembleBlock(round, deadline)
if err != nil {
Expand All @@ -1329,7 +1336,7 @@
}
return nil, err
}
return validatedBlock{vb: lvb}, nil
return assembledBlock{blk: lvb.Block()}, nil

Check warning on line 1339 in node/node.go

View check run for this annotation

Codecov / codecov/patch

node/node.go#L1339

Added line #L1339 was not covered by tests
}

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