Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph committed Nov 21, 2023
1 parent bd5be37 commit dfa3889
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 80 deletions.
10 changes: 8 additions & 2 deletions vms/proposervm/batched_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ func (vm *VM) BatchedParseBlock(ctx context.Context, blks [][]byte) ([]snowman.B
}

blkID := statelessBlock.ID()
block, exists := vm.verifiedBlocks[blkID]
if exists {
if block, exists := vm.verifiedProposerBlocks[blkID]; exists {
blocks[blocksIndex] = block
continue
}
if block, exists := vm.verifiedBlocks[blkID]; exists {
blocks[blocksIndex] = block
continue
}
Expand Down Expand Up @@ -168,6 +171,9 @@ func (vm *VM) BatchedParseBlock(ctx context.Context, blks [][]byte) ([]snowman.B
}

func (vm *VM) getStatelessBlk(blkID ids.ID) (statelessblock.Block, error) {
if currentBlk, exists := vm.verifiedProposerBlocks[blkID]; exists {
return currentBlk.getStatelessBlk(), nil
}
if currentBlk, exists := vm.verifiedBlocks[blkID]; exists {
return currentBlk.getStatelessBlk(), nil
}
Expand Down
87 changes: 40 additions & 47 deletions vms/proposervm/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ type Block interface {
acceptOuterBlk() error
acceptInnerBlk(context.Context) error

verifyProposerPreForkChild(ctx context.Context, child *preForkBlock) error
verifyPreForkChild(ctx context.Context, child *preForkBlock) error

verifyProposerPostForkChild(ctx context.Context, child *postForkBlock) error
Expand Down Expand Up @@ -94,7 +93,6 @@ func (p *postForkCommonComponents) Height() uint64 {
// 6) [childPChainHeight] <= the current P-Chain height
// 7) [child]'s timestamp is within its proposer's window
// 8) [child] has a valid signature from its proposer
// 9) [child]'s inner block is valid
func (p *postForkCommonComponents) Verify(
ctx context.Context,
parentTimestamp time.Time,
Expand Down Expand Up @@ -128,58 +126,53 @@ func (p *postForkCommonComponents) Verify(

// If the node is currently syncing - we don't assume that the P-chain has
// been synced up to this point yet.
if p.vm.consensusState == snow.NormalOp {
childID := child.ID()
currentPChainHeight, err := p.vm.ctx.ValidatorState.GetCurrentHeight(ctx)
if err != nil {
p.vm.ctx.Log.Error("block verification failed",
zap.String("reason", "failed to get current P-Chain height"),
zap.Stringer("blkID", childID),
zap.Error(err),
)
return err
}
if childPChainHeight > currentPChainHeight {
return fmt.Errorf("%w: %d > %d",
errPChainHeightNotReached,
childPChainHeight,
currentPChainHeight,
)
}
if p.vm.consensusState != snow.NormalOp {
return nil
}

childHeight := child.Height()
proposerID := child.Proposer()
minDelay, err := p.vm.Windower.Delay(ctx, childHeight, parentPChainHeight, proposerID)
if err != nil {
return err
}
childID := child.ID()
currentPChainHeight, err := p.vm.ctx.ValidatorState.GetCurrentHeight(ctx)
if err != nil {
p.vm.ctx.Log.Error("block verification failed",
zap.String("reason", "failed to get current P-Chain height"),
zap.Stringer("blkID", childID),
zap.Error(err),
)
return err
}
if childPChainHeight > currentPChainHeight {
return fmt.Errorf("%w: %d > %d",
errPChainHeightNotReached,
childPChainHeight,
currentPChainHeight,
)
}

delay := childTimestamp.Sub(parentTimestamp)
if delay < minDelay {
return errProposerWindowNotStarted
}
childHeight := child.Height()
proposerID := child.Proposer()
minDelay, err := p.vm.Windower.Delay(ctx, childHeight, parentPChainHeight, proposerID)
if err != nil {
return err
}

// Verify the signature of the node
shouldHaveProposer := delay < proposer.MaxDelay
if err := child.SignedBlock.Verify(shouldHaveProposer, p.vm.ctx.ChainID); err != nil {
return err
}
delay := childTimestamp.Sub(parentTimestamp)
if delay < minDelay {
return errProposerWindowNotStarted
}

p.vm.ctx.Log.Debug("verified post-fork block",
zap.Stringer("blkID", childID),
zap.Time("parentTimestamp", parentTimestamp),
zap.Duration("minDelay", minDelay),
zap.Time("blockTimestamp", childTimestamp),
)
// Verify the signature of the node
shouldHaveProposer := delay < proposer.MaxDelay
if err := child.SignedBlock.Verify(shouldHaveProposer, p.vm.ctx.ChainID); err != nil {
return err
}

return p.vm.verifyAndRecordInnerBlk(
ctx,
&smblock.Context{
PChainHeight: parentPChainHeight,
},
child,
p.vm.ctx.Log.Debug("verified post-fork block",
zap.Stringer("blkID", childID),
zap.Time("parentTimestamp", parentTimestamp),
zap.Duration("minDelay", minDelay),
zap.Time("blockTimestamp", childTimestamp),
)
return nil
}

// Return the child (a *postForkBlock) of this block
Expand Down
47 changes: 39 additions & 8 deletions vms/proposervm/post_fork_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow/choices"
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
smblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/vms/proposervm/block"
)

Expand Down Expand Up @@ -46,7 +47,9 @@ func (b *postForkBlock) acceptInnerBlk(ctx context.Context) error {

func (b *postForkBlock) Reject(context.Context) error {
// We do not reject the inner block here because it may be accepted later
delete(b.vm.verifiedBlocks, b.ID())
blkID := b.ID()
delete(b.vm.verifiedProposerBlocks, blkID)
delete(b.vm.verifiedBlocks, blkID)
b.status = choices.Rejected
return nil
}
Expand All @@ -64,6 +67,14 @@ func (b *postForkBlock) Parent() ids.ID {
return b.ParentID()
}

func (b *postForkBlock) VerifyProposer(ctx context.Context) error {
parent, err := b.vm.getBlock(ctx, b.ParentID())
if err != nil {
return err
}
return parent.verifyProposerPostForkChild(ctx, b)
}

// If Verify() returns nil, Accept() or Reject() will eventually be called on
// [b] and [b.innerBlk]
func (b *postForkBlock) Verify(ctx context.Context) error {
Expand Down Expand Up @@ -113,26 +124,40 @@ func (b *postForkBlock) Options(ctx context.Context) ([2]snowman.Block, error) {
}

// A post-fork block can never have a pre-fork child
func (*postForkBlock) verifyProposerPreForkChild(context.Context, *preForkBlock) error {
return errUnsignedChild
}

func (*postForkBlock) verifyPreForkChild(context.Context, *preForkBlock) error {
return errUnsignedChild
}

func (b *postForkBlock) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
func (b *postForkBlock) verifyProposerPostForkChild(ctx context.Context, child *postForkBlock) error {
parentTimestamp := b.Timestamp()
parentPChainHeight := b.PChainHeight()
return b.postForkCommonComponents.Verify(
err := b.postForkCommonComponents.Verify(
ctx,
parentTimestamp,
parentPChainHeight,
child,
)
if err != nil {
return err
}

childID := child.ID()
child.vm.verifiedProposerBlocks[childID] = child
return nil
}

func (b *postForkBlock) verifyPostForkOption(ctx context.Context, child *postForkOption) error {
func (b *postForkBlock) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
parentPChainHeight := b.PChainHeight()
return child.vm.verifyAndRecordInnerBlk(
ctx,
&smblock.Context{
PChainHeight: parentPChainHeight,
},
child,
)
}

func (b *postForkBlock) verifyProposerPostForkOption(ctx context.Context, child *postForkOption) error {
if err := verifyIsOracleBlock(ctx, b.innerBlk); err != nil {
return err
}
Expand All @@ -144,6 +169,12 @@ func (b *postForkBlock) verifyPostForkOption(ctx context.Context, child *postFor
return errInnerParentMismatch
}

childID := child.ID()
child.vm.verifiedProposerBlocks[childID] = child
return nil
}

func (b *postForkBlock) verifyPostForkOption(ctx context.Context, child *postForkOption) error {
return child.vm.verifyAndRecordInnerBlk(ctx, nil, child)
}

Expand Down
44 changes: 35 additions & 9 deletions vms/proposervm/post_fork_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow/choices"
smblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/vms/proposervm/block"
)

Expand Down Expand Up @@ -54,8 +55,9 @@ func (b *postForkOption) acceptInnerBlk(ctx context.Context) error {
func (b *postForkOption) Reject(context.Context) error {
// we do not reject the inner block here because that block may be contained
// in the proposer block that causing this block to be rejected.

delete(b.vm.verifiedBlocks, b.ID())
blkID := b.ID()
delete(b.vm.verifiedProposerBlocks, blkID)
delete(b.vm.verifiedBlocks, blkID)
b.status = choices.Rejected
return nil
}
Expand All @@ -71,6 +73,14 @@ func (b *postForkOption) Parent() ids.ID {
return b.ParentID()
}

func (b *postForkOption) VerifyProposer(ctx context.Context) error {
parent, err := b.vm.getBlock(ctx, b.ParentID())
if err != nil {
return err
}
return parent.verifyProposerPostForkOption(ctx, b)
}

// If Verify returns nil, Accept or Reject is eventually called on [b] and
// [b.innerBlk].
func (b *postForkOption) Verify(ctx context.Context) error {
Expand All @@ -82,27 +92,43 @@ func (b *postForkOption) Verify(ctx context.Context) error {
return parent.verifyPostForkOption(ctx, b)
}

// A *preForkBlock's parent must be a *preForkBlock
func (*postForkOption) verifyProposerPreForkChild(context.Context, *preForkBlock) error {
return errUnsignedChild
}

func (*postForkOption) verifyPreForkChild(context.Context, *preForkBlock) error {
return errUnsignedChild
}

func (b *postForkOption) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
func (b *postForkOption) verifyProposerPostForkChild(ctx context.Context, child *postForkBlock) error {
parentTimestamp := b.Timestamp()
parentPChainHeight, err := b.pChainHeight(ctx)
if err != nil {
return err
}
return b.postForkCommonComponents.Verify(
err = b.postForkCommonComponents.Verify(
ctx,
parentTimestamp,
parentPChainHeight,
child,
)
if err != nil {
return err
}

childID := child.ID()
child.vm.verifiedProposerBlocks[childID] = child
return nil
}

func (b *postForkOption) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
parentPChainHeight, err := b.pChainHeight(ctx)
if err != nil {
return err
}
return child.vm.verifyAndRecordInnerBlk(
ctx,
&smblock.Context{
PChainHeight: parentPChainHeight,
},
child,
)
}

// A *postForkOption's parent can't be a *postForkOption
Expand Down
25 changes: 14 additions & 11 deletions vms/proposervm/pre_fork_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,18 @@ func (b *preForkBlock) Status() choices.Status {
return b.Block.Status()
}

func (b *preForkBlock) Verify(ctx context.Context) error {
func (b *preForkBlock) VerifyProposer(ctx context.Context) error {
parent, err := b.vm.getPreForkBlock(ctx, b.Block.Parent())
if err != nil {
return err
}
return parent.verifyPreForkChild(ctx, b)
}

func (b *preForkBlock) Verify(ctx context.Context) error {
return nil // Block verification is fully handled by VerifyProposer
}

func (b *preForkBlock) Options(ctx context.Context) ([2]snowman.Block, error) {
oracleBlk, ok := b.Block.(snowman.OracleBlock)
if !ok {
Expand Down Expand Up @@ -95,7 +99,7 @@ func (b *preForkBlock) getInnerBlk() snowman.Block {
return b.Block
}

func (b *preForkBlock) verifyProposerPreForkChild(ctx context.Context, child *preForkBlock) error {
func (b *preForkBlock) verifyPreForkChild(ctx context.Context, child *preForkBlock) error {
parentTimestamp := b.Timestamp()
if parentTimestamp.Before(b.vm.activationTime) {
return nil
Expand All @@ -109,15 +113,13 @@ func (b *preForkBlock) verifyProposerPreForkChild(ctx context.Context, child *pr
zap.String("reason", "parent is an oracle block"),
zap.Stringer("blkID", b.ID()),
)
return child.Block.VerifyProposer(ctx)
}

func (b *preForkBlock) verifyPreForkChild(ctx context.Context, child *preForkBlock) error {
if err := child.Block.VerifyProposer(ctx); err != nil {
return err
}
return child.Block.Verify(ctx)
}

// This method only returns nil once (during the transition)
func (b *preForkBlock) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
func (b *preForkBlock) verifyProposerPostForkChild(ctx context.Context, child *postForkBlock) error {
if err := verifyIsNotOracleBlock(ctx, b.Block); err != nil {
return err
}
Expand Down Expand Up @@ -172,10 +174,11 @@ func (b *preForkBlock) verifyPostForkChild(ctx context.Context, child *postForkB
}

// Verify the lack of signature on the node
if err := child.SignedBlock.Verify(false, b.vm.ctx.ChainID); err != nil {
return err
}
return child.SignedBlock.Verify(false, b.vm.ctx.ChainID)
}

// This method only returns nil once (during the transition)
func (b *preForkBlock) verifyPostForkChild(ctx context.Context, child *postForkBlock) error {
// Verify the inner block and track it as verified
return b.vm.verifyAndRecordInnerBlk(ctx, nil, child)
}
Expand Down
Loading

0 comments on commit dfa3889

Please sign in to comment.