Skip to content

Commit

Permalink
Increase ProposalVM maximum Block Size (ava-labs#1651)
Browse files Browse the repository at this point in the history
Co-authored-by: Chloe <[email protected]>
Co-authored-by: Stephen <[email protected]>
  • Loading branch information
3 people authored Sep 2, 2022
1 parent df2877d commit 4760336
Show file tree
Hide file tree
Showing 23 changed files with 279 additions and 120 deletions.
15 changes: 10 additions & 5 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ var (

// Manager manages the chains running on this node.
// It can:
// * Create a chain
// * Add a registrant. When a chain is created, each registrant calls
// - Create a chain
// - Add a registrant. When a chain is created, each registrant calls
// RegisterChain with the new chain as the argument.
// * Manage the aliases of chains
// - Manage the aliases of chains
type Manager interface {
ids.Aliaser

Expand Down Expand Up @@ -187,6 +187,7 @@ type ManagerConfig struct {

ApricotPhase4Time time.Time
ApricotPhase4MinPChainHeight uint64
BlueberryTime time.Time

// Tracks CPU/disk usage caused by each peer.
ResourceTracker timetracker.ResourceTracker
Expand Down Expand Up @@ -795,8 +796,12 @@ func (m *manager) createSnowmanChain(
return nil, fmt.Errorf("error while fetching chain config: %w", err)
}

// enable ProposerVM on this VM
vm = proposervm.New(vm, m.ApricotPhase4Time, m.ApricotPhase4MinPChainHeight)
vm = proposervm.New(
vm,
m.ApricotPhase4Time,
m.ApricotPhase4MinPChainHeight,
m.BlueberryTime,
)

if m.MeterVMEnabled {
vm = metervm.NewBlockVM(vm)
Expand Down
13 changes: 9 additions & 4 deletions codec/reflectcodec/type_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const (
)

var (
ErrMaxMarshalSliceLimitExceeded = errors.New("maximum marshal slice limit exceeded")

errMarshalNil = errors.New("can't marshal nil pointer or interface")
errUnmarshalNil = errors.New("can't unmarshal nil")
errNeedPointer = errors.New("argument to unmarshal must be a pointer")
Expand Down Expand Up @@ -138,7 +140,8 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice
case reflect.Slice:
numElts := value.Len() // # elements in the slice/array. 0 if this slice is nil.
if uint32(numElts) > maxSliceLen {
return fmt.Errorf("slice length, %d, exceeds maximum length, %d",
return fmt.Errorf("%w; slice length, %d, exceeds maximum length, %d",
ErrMaxMarshalSliceLimitExceeded,
numElts,
maxSliceLen)
}
Expand Down Expand Up @@ -166,7 +169,7 @@ func (c *genericCodec) marshal(value reflect.Value, p *wrappers.Packer, maxSlice
return p.Err
}
if uint32(numElts) > c.maxSliceLen {
return fmt.Errorf("array length, %d, exceeds maximum length, %d", numElts, c.maxSliceLen)
return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d", ErrMaxMarshalSliceLimitExceeded, numElts, c.maxSliceLen)
}
for i := 0; i < numElts; i++ { // Process each element in the array
if err := c.marshal(value.Index(i), p, c.maxSliceLen); err != nil {
Expand Down Expand Up @@ -277,12 +280,14 @@ func (c *genericCodec) unmarshal(p *wrappers.Packer, value reflect.Value, maxSli
return fmt.Errorf("couldn't unmarshal slice: %w", p.Err)
}
if numElts32 > maxSliceLen {
return fmt.Errorf("array length, %d, exceeds maximum length, %d",
return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d",
ErrMaxMarshalSliceLimitExceeded,
numElts32,
maxSliceLen)
}
if numElts32 > math.MaxInt32 {
return fmt.Errorf("array length, %d, exceeds maximum length, %d",
return fmt.Errorf("%w; array length, %d, exceeds maximum length, %d",
ErrMaxMarshalSliceLimitExceeded,
numElts32,
math.MaxInt32)
}
Expand Down
1 change: 1 addition & 0 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ func (n *Node) initChainManager(avaxAssetID ids.ID) error {
BootstrapAncestorsMaxContainersReceived: n.Config.BootstrapAncestorsMaxContainersReceived,
ApricotPhase4Time: version.GetApricotPhase4Time(n.Config.NetworkID),
ApricotPhase4MinPChainHeight: version.GetApricotPhase4MinPChainHeight(n.Config.NetworkID),
BlueberryTime: version.GetBlueberryTime(n.Config.NetworkID),
ResourceTracker: n.resourceTracker,
StateSyncBeacons: n.Config.StateSyncIDs,
})
Expand Down
7 changes: 6 additions & 1 deletion vms/proposervm/batched_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,19 @@ func (vm *VM) BatchedParseBlock(blks [][]byte) ([]snowman.Block, error) {
innerBlocksIndex int
statelessBlockDescs = make([]partialData, 0, len(blks))
innerBlockBytes = make([][]byte, 0, len(blks))
blueberryActivated = vm.Clock.Time().After(vm.activationTimeBlueberry)
)
for ; blocksIndex < len(blks); blocksIndex++ {
blkBytes := blks[blocksIndex]
statelessBlock, err := statelessblock.Parse(blkBytes)
statelessBlock, requireBlueberry, err := statelessblock.Parse(blkBytes)
if err != nil {
break
}

if requireBlueberry && !blueberryActivated {
break
}

blkID := statelessBlock.ID()
block, exists := vm.verifiedBlocks[blkID]
if exists {
Expand Down
2 changes: 1 addition & 1 deletion vms/proposervm/batched_vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ func initTestRemoteProposerVM(
}
}

proVM := New(coreVM, proBlkStartTime, 0)
proVM := New(coreVM, proBlkStartTime, 0, time.Time{})

valState := &validators.TestState{
T: t,
Expand Down
53 changes: 38 additions & 15 deletions vms/proposervm/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,28 +211,51 @@ func (p *postForkCommonComponents) buildChild(
return nil, err
}

blueberryActivated := newTimestamp.After(p.vm.activationTimeBlueberry)

// Build the child
var statelessChild block.SignedBlock
if delay >= proposer.MaxDelay {
statelessChild, err = block.BuildUnsigned(
parentID,
newTimestamp,
pChainHeight,
innerBlock.Bytes(),
)
if blueberryActivated {
statelessChild, err = block.BuildUnsignedBlueberry(
parentID,
newTimestamp,
pChainHeight,
innerBlock.Bytes(),
)
} else {
statelessChild, err = block.BuildUnsignedApricot(
parentID,
newTimestamp,
pChainHeight,
innerBlock.Bytes(),
)
}
if err != nil {
return nil, err
}
} else {
statelessChild, err = block.Build(
parentID,
newTimestamp,
pChainHeight,
p.vm.ctx.StakingCertLeaf,
innerBlock.Bytes(),
p.vm.ctx.ChainID,
p.vm.ctx.StakingLeafSigner,
)
if blueberryActivated {
statelessChild, err = block.BuildBlueberry(
parentID,
newTimestamp,
pChainHeight,
p.vm.ctx.StakingCertLeaf,
innerBlock.Bytes(),
p.vm.ctx.ChainID,
p.vm.ctx.StakingLeafSigner,
)
} else {
statelessChild, err = block.BuildApricot(
parentID,
newTimestamp,
pChainHeight,
p.vm.ctx.StakingCertLeaf,
innerBlock.Bytes(),
p.vm.ctx.ChainID,
p.vm.ctx.StakingLeafSigner,
)
}
if err != nil {
return nil, err
}
Expand Down
22 changes: 21 additions & 1 deletion vms/proposervm/block/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
package block

import (
"bytes"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/codec/reflectcodec"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/units"
)

func equal(require *require.Assertions, chainID ids.ID, want, have SignedBlock) {
Expand All @@ -32,7 +35,7 @@ func TestVerifyNoCertWithSignature(t *testing.T) {

require := require.New(t)

builtBlockIntf, err := BuildUnsigned(parentID, timestamp, pChainHeight, innerBlockBytes)
builtBlockIntf, err := BuildUnsignedApricot(parentID, timestamp, pChainHeight, innerBlockBytes)
require.NoError(err)

builtBlock := builtBlockIntf.(*statelessBlock)
Expand All @@ -44,3 +47,20 @@ func TestVerifyNoCertWithSignature(t *testing.T) {
err = builtBlock.Verify(true, ids.Empty)
require.Error(err)
}

func TestBlockSizeLimitExceeded(t *testing.T) {
require := require.New(t)

parentID := ids.ID{1}
timestamp := time.Unix(123, 0)
pChainHeight := uint64(2)
innerBlockBytes := bytes.Repeat([]byte{0}, 270*units.KiB)

// linear codec should fail to marshal, due to exceeded maximum length
_, err := BuildUnsignedApricot(parentID, timestamp, pChainHeight, innerBlockBytes)
require.ErrorIs(err, reflectcodec.ErrMaxMarshalSliceLimitExceeded)

// with the new max limit, it should be able to build blocks
_, err = BuildUnsignedBlueberry(parentID, timestamp, pChainHeight, innerBlockBytes)
require.NoError(err)
}
59 changes: 52 additions & 7 deletions vms/proposervm/block/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,32 @@ import (
"crypto/x509"
"time"

"github.com/ava-labs/avalanchego/codec"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/ava-labs/avalanchego/utils/wrappers"
)

func BuildUnsigned(
func BuildUnsignedApricot(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
blockBytes []byte,
) (SignedBlock, error) {
return buildUnsigned(apricotCodec, parentID, timestamp, pChainHeight, blockBytes)
}

func BuildUnsignedBlueberry(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
blockBytes []byte,
) (SignedBlock, error) {
return buildUnsigned(blueberryCodec, parentID, timestamp, pChainHeight, blockBytes)
}

func buildUnsigned(
cm codec.Manager,
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
Expand All @@ -31,14 +51,39 @@ func BuildUnsigned(
timestamp: timestamp,
}

bytes, err := c.Marshal(version, &block)
bytes, err := cm.Marshal(codecVersion, &block)
if err != nil {
return nil, err
}
return block, block.initialize(bytes)
}

func Build(
func BuildApricot(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
cert *x509.Certificate,
blockBytes []byte,
chainID ids.ID,
key crypto.Signer,
) (SignedBlock, error) {
return build(apricotCodec, parentID, timestamp, pChainHeight, cert, blockBytes, chainID, key)
}

func BuildBlueberry(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
cert *x509.Certificate,
blockBytes []byte,
chainID ids.ID,
key crypto.Signer,
) (SignedBlock, error) {
return build(blueberryCodec, parentID, timestamp, pChainHeight, cert, blockBytes, chainID, key)
}

func build(
cm codec.Manager,
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
Expand All @@ -61,7 +106,7 @@ func Build(
}
var blockIntf SignedBlock = block

unsignedBytesWithEmptySignature, err := c.Marshal(version, &blockIntf)
unsignedBytesWithEmptySignature, err := cm.Marshal(codecVersion, &blockIntf)
if err != nil {
return nil, err
}
Expand All @@ -85,7 +130,7 @@ func Build(
return nil, err
}

block.bytes, err = c.Marshal(version, &blockIntf)
block.bytes, err = cm.Marshal(codecVersion, &blockIntf)
return block, err
}

Expand All @@ -100,7 +145,7 @@ func BuildHeader(
Body: bodyID,
}

bytes, err := c.Marshal(version, &header)
bytes, err := blueberryCodec.Marshal(codecVersion, &header)
header.bytes = bytes
return &header, err
}
Expand All @@ -117,7 +162,7 @@ func BuildOption(
InnerBytes: innerBytes,
}

bytes, err := c.Marshal(version, &block)
bytes, err := blueberryCodec.Marshal(codecVersion, &block)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions vms/proposervm/block/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestBuild(t *testing.T) {
cert := tlsCert.Leaf
key := tlsCert.PrivateKey.(crypto.Signer)

builtBlock, err := Build(
builtBlock, err := BuildApricot(
parentID,
timestamp,
pChainHeight,
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestBuildUnsigned(t *testing.T) {

require := require.New(t)

builtBlock, err := BuildUnsigned(parentID, timestamp, pChainHeight, innerBlockBytes)
builtBlock, err := BuildUnsignedApricot(parentID, timestamp, pChainHeight, innerBlockBytes)
require.NoError(err)

require.Equal(parentID, builtBlock.ParentID())
Expand Down
Loading

0 comments on commit 4760336

Please sign in to comment.