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

[chain] Remove Parent Block Dependency during Verify #427

Merged
merged 28 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
23c48df
add TODO
patrick-ogrady Aug 28, 2023
511772a
remove parent fetch
patrick-ogrady Aug 28, 2023
80eaa66
remove parent block from innerVerify
patrick-ogrady Aug 28, 2023
3fdae14
add verify context
patrick-ogrady Aug 28, 2023
512c42b
cleanup VerifyContext call
patrick-ogrady Aug 28, 2023
c6f4d7e
working on clarifying GetVerifyContext/View
patrick-ogrady Aug 28, 2023
ba736d5
keep cleaning up
patrick-ogrady Aug 28, 2023
261f2a4
add specific conditional for height
patrick-ogrady Aug 28, 2023
77a07d3
update verification context handling
patrick-ogrady Aug 28, 2023
7b86e5a
update wording in view to explain why we need accepted handling
patrick-ogrady Aug 28, 2023
cae4094
add more comments to main path
patrick-ogrady Aug 28, 2023
2b0d235
update interface
patrick-ogrady Aug 28, 2023
521aaa3
use preferred block directly
patrick-ogrady Aug 28, 2023
290020b
drop verify
patrick-ogrady Aug 28, 2023
ffb7b65
fix lint
patrick-ogrady Aug 28, 2023
6f8d542
update state manager
patrick-ogrady Aug 28, 2023
cb69e19
add note about GetBlockIDByHeight
patrick-ogrady Aug 28, 2023
482473e
finish comment about handling blocks
patrick-ogrady Aug 28, 2023
6886b35
make sure keys in set
patrick-ogrady Aug 28, 2023
c96da30
add todo for genesis handling
patrick-ogrady Aug 30, 2023
642b282
update genesis block handling
patrick-ogrady Aug 30, 2023
f6b0c47
add more logs
patrick-ogrady Aug 30, 2023
475b712
e2e passing
patrick-ogrady Aug 30, 2023
84665c6
address chain nits
patrick-ogrady Aug 31, 2023
25689a0
better comment genesis
patrick-ogrady Aug 31, 2023
7f5fc24
extra VM comments
patrick-ogrady Aug 31, 2023
54a8917
add TODO
patrick-ogrady Aug 31, 2023
fbd1541
clarify note about verification status
patrick-ogrady Aug 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 149 additions & 103 deletions chain/block.go

Large diffs are not rendered by default.

38 changes: 20 additions & 18 deletions chain/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"time"

"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/ids"
smblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/math"
Expand Down Expand Up @@ -61,19 +60,17 @@ func HandlePreExecute(log logging.Logger, err error) bool {
func BuildBlock(
ctx context.Context,
vm VM,
preferred ids.ID,
parent *StatelessBlock,
blockContext *smblock.Context,
) (*StatelessBlock, error) {
ctx, span := vm.Tracer().Start(ctx, "chain.BuildBlock")
defer span.End()
log := vm.Logger()

// Setup new block
parent, err := vm.GetStatelessBlock(ctx, preferred)
if err != nil {
log.Warn("block building failed: couldn't get parent", zap.Error(err))
return nil, err
}
// We don't need to fetch the [VerifyContext] because
// we will always have a block to build on.

// Select next timestamp
nextTime := time.Now().UnixMilli()
r := vm.Rules(nextTime)
if nextTime < parent.Tmstmp+r.GetMinBlockGap() {
Expand All @@ -82,10 +79,13 @@ func BuildBlock(
}
b := NewBlock(vm, parent, nextTime)

// Fetch state to build on
// Fetch view where we will apply block state transitions
//
// If the parent block is not yet verified, we will attempt to
// execute it.
mempoolSize := vm.Mempool().Len(ctx)
changesEstimate := math.Min(mempoolSize, maxViewPreallocation)
parentView, err := parent.View(ctx, nil)
parentView, err := parent.View(ctx, nil, true)
if err != nil {
log.Warn("block building failed: couldn't get parent db", zap.Error(err))
return nil, err
Expand Down Expand Up @@ -454,21 +454,23 @@ func BuildBlock(
vm.RecordEmptyBlockBuilt()
}

// Set scope for [tstate] changes
// Update chain metadata
heightKey := HeightKey(sm.HeightKey())
heightKeyStr := string(heightKey)
timestampKey := TimestampKey(b.vm.StateManager().TimestampKey())
patrick-ogrady marked this conversation as resolved.
Show resolved Hide resolved
timestampKeyStr := string(timestampKey)
feeKeyStr := string(feeKey)
ts.SetScope(ctx, set.Of(heightKeyStr, feeKeyStr), map[string][]byte{
heightKeyStr: binary.BigEndian.AppendUint64(nil, parent.Hght),
feeKeyStr: parentFeeManager.Bytes(),
ts.SetScope(ctx, set.Of(heightKeyStr, timestampKeyStr, feeKeyStr), map[string][]byte{
heightKeyStr: binary.BigEndian.AppendUint64(nil, parent.Hght),
timestampKeyStr: binary.BigEndian.AppendUint64(nil, uint64(parent.Tmstmp)),
feeKeyStr: parentFeeManager.Bytes(),
})

// Store height in state to prevent duplicate roots
if err := ts.Insert(ctx, heightKey, binary.BigEndian.AppendUint64(nil, b.Hght)); err != nil {
return nil, fmt.Errorf("%w: unable to insert height", err)
}

// Store fee parameters
if err := ts.Insert(ctx, timestampKey, binary.BigEndian.AppendUint64(nil, uint64(b.Tmstmp))); err != nil {
return nil, fmt.Errorf("%w: unable to insert timestamp", err)
}
if err := ts.Insert(ctx, feeKey, feeManager.Bytes()); err != nil {
return nil, fmt.Errorf("%w: unable to insert fees", err)
}
Expand Down
5 changes: 5 additions & 0 deletions chain/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ const (
// ranges (so, we can't expose a way to modify this over time).
MaxOutgoingWarpChunks = 4
HeightKeyChunks = 1
TimestampKeyChunks = 1
FeeKeyChunks = 8 // 96 (per dimension) * 5 (num dimensions)
)

func HeightKey(prefix []byte) []byte {
return keys.EncodeChunks(prefix, HeightKeyChunks)
}

func TimestampKey(prefix []byte) []byte {
return keys.EncodeChunks(prefix, TimestampKeyChunks)
}

func FeeKey(prefix []byte) []byte {
return keys.EncodeChunks(prefix, FeeKeyChunks)
}
8 changes: 8 additions & 0 deletions chain/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type VM interface {
SetLastAccepted(*StatelessBlock) error
GetStatelessBlock(context.Context, ids.ID) (*StatelessBlock, error)

GetVerifyContext(ctx context.Context, blockHeight uint64, parent ids.ID) (VerifyContext, error)

State() (merkledb.MerkleDB, error)
StateManager() StateManager
ValidatorState() validators.State
Expand Down Expand Up @@ -82,6 +84,11 @@ type VM interface {
RecordClearedMempool()
}

type VerifyContext interface {
View(ctx context.Context, blockRoot *ids.ID, verify bool) (state.View, error)
IsRepeat(ctx context.Context, oldestAllowed int64, txs []*Transaction, marker set.Bits, stop bool) (set.Bits, error)
}

type Mempool interface {
Len(context.Context) int // items
Size(context.Context) int // bytes
Expand Down Expand Up @@ -156,6 +163,7 @@ type Rules interface {
// use. This will be handled by the hypersdk.
type StateManager interface {
HeightKey() []byte
TimestampKey() []byte
FeeKey() []byte

IncomingWarpKeyPrefix(sourceChainID ids.ID, msgID ids.ID) []byte
Expand Down
1 change: 1 addition & 0 deletions chain/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var (
ErrInvalidSurplus = errors.New("invalid surplus fee")
ErrStateRootMismatch = errors.New("state root mismatch")
ErrInvalidResult = errors.New("invalid result")
ErrInvalidBlockHeight = errors.New("invalid block height")

// Tx Correctness
ErrInvalidSignature = errors.New("invalid signature")
Expand Down
4 changes: 4 additions & 0 deletions examples/morpheusvm/storage/state_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ func (*StateManager) HeightKey() []byte {
return HeightKey()
}

func (*StateManager) TimestampKey() []byte {
return TimestampKey()
}

func (*StateManager) FeeKey() []byte {
return FeeKey()
}
Expand Down
27 changes: 17 additions & 10 deletions examples/morpheusvm/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ type ReadState func(context.Context, [][]byte) ([][]byte, []error)
// 0x0/ (balance)
// -> [owner] => balance
// 0x1/ (hypersdk-height)
// 0x2/ (hypersdk-fee)
// 0x3/ (hypersdk-incoming warp)
// 0x4/ (hypersdk-outgoing warp)
// 0x2/ (hypersdk-timestamp)
// 0x3/ (hypersdk-fee)
// 0x4/ (hypersdk-incoming warp)
// 0x5/ (hypersdk-outgoing warp)

const (
// metaDB
Expand All @@ -44,18 +45,20 @@ const (
// stateDB
balancePrefix = 0x0
heightPrefix = 0x1
feePrefix = 0x2
incomingWarpPrefix = 0x3
outgoingWarpPrefix = 0x4
timestampPrefix = 0x2
feePrefix = 0x3
incomingWarpPrefix = 0x4
outgoingWarpPrefix = 0x5
)

const BalanceChunks uint16 = 1

var (
failureByte = byte(0x0)
successByte = byte(0x1)
heightKey = []byte{heightPrefix}
feeKey = []byte{feePrefix}
failureByte = byte(0x0)
successByte = byte(0x1)
heightKey = []byte{heightPrefix}
timestampKey = []byte{timestampPrefix}
feeKey = []byte{feePrefix}

balanceKeyPool = sync.Pool{
New: func() any {
Expand Down Expand Up @@ -256,6 +259,10 @@ func HeightKey() (k []byte) {
return heightKey
}

func TimestampKey() (k []byte) {
return timestampKey
}

func FeeKey() (k []byte) {
return feeKey
}
Expand Down
4 changes: 4 additions & 0 deletions examples/tokenvm/controller/state_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ func (*StateManager) HeightKey() []byte {
return storage.HeightKey()
}

func (*StateManager) TimestampKey() []byte {
return storage.TimestampKey()
}

func (*StateManager) FeeKey() []byte {
return storage.HeightKey()
}
Expand Down
27 changes: 17 additions & 10 deletions examples/tokenvm/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ type ReadState func(context.Context, [][]byte) ([][]byte, []error)
// 0x3/ (loans)
// -> [assetID|destination] => amount
// 0x4/ (hypersdk-height)
// 0x5/ (hypersdk-fee)
// 0x6/ (hypersdk-incoming warp)
// 0x7/ (hypersdk-outgoing warp)
// 0x5/ (hypersdk-timestamp)
// 0x6/ (hypersdk-fee)
// 0x7/ (hypersdk-incoming warp)
// 0x8/ (hypersdk-outgoing warp)

const (
// metaDB
Expand All @@ -51,9 +52,10 @@ const (
orderPrefix = 0x2
loanPrefix = 0x3
heightPrefix = 0x4
feePrefix = 0x5
incomingWarpPrefix = 0x6
outgoingWarpPrefix = 0x7
timestampPrefix = 0x5
feePrefix = 0x6
incomingWarpPrefix = 0x7
outgoingWarpPrefix = 0x8
)

const (
Expand All @@ -64,10 +66,11 @@ const (
)

var (
failureByte = byte(0x0)
successByte = byte(0x1)
heightKey = []byte{heightPrefix}
feeKey = []byte{feePrefix}
failureByte = byte(0x0)
successByte = byte(0x1)
heightKey = []byte{heightPrefix}
timestampKey = []byte{timestampPrefix}
feeKey = []byte{feePrefix}

balanceKeyPool = sync.Pool{
New: func() any {
Expand Down Expand Up @@ -538,6 +541,10 @@ func HeightKey() (k []byte) {
return heightKey
}

func TimestampKey() (k []byte) {
return timestampKey
}

func FeeKey() (k []byte) {
return feeKey
}
Expand Down
11 changes: 6 additions & 5 deletions vm/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
)

var (
ErrNotAdded = errors.New("not added")
ErrDropped = errors.New("dropped")
ErrNotReady = errors.New("not ready")
ErrStateMissing = errors.New("state missing")
ErrStateSyncing = errors.New("state still syncing")
ErrNotAdded = errors.New("not added")
ErrDropped = errors.New("dropped")
ErrNotReady = errors.New("not ready")
ErrStateMissing = errors.New("state missing")
ErrStateSyncing = errors.New("state still syncing")
ErrUnexpectedStateRoot = errors.New("unexpected state root")
)
3 changes: 3 additions & 0 deletions vm/resolutions.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func (vm *VM) Verified(ctx context.Context, b *chain.StatelessBlock) {
zap.Stringer("blkID", b.ID()),
zap.Uint64("height", b.Hght),
zap.Int("txs", len(b.Txs)),
zap.Stringer("parent root", b.StateRoot),
zap.Bool("state ready", vm.StateReady()),
zap.Any("unit prices", fm.UnitPrices()),
zap.Any("units consumed", fm.UnitsConsumed()),
Expand All @@ -128,6 +129,7 @@ func (vm *VM) Verified(ctx context.Context, b *chain.StatelessBlock) {
zap.Stringer("blkID", b.ID()),
zap.Uint64("height", b.Hght),
zap.Int("txs", len(b.Txs)),
zap.Stringer("parent root", b.StateRoot),
zap.Bool("state ready", vm.StateReady()),
)
}
Expand Down Expand Up @@ -301,6 +303,7 @@ func (vm *VM) Accepted(ctx context.Context, b *chain.StatelessBlock) {
zap.Stringer("blkID", b.ID()),
zap.Uint64("height", b.Hght),
zap.Int("txs", len(b.Txs)),
zap.Stringer("parent root", b.StateRoot),
zap.Int("size", len(b.Bytes())),
zap.Int("dropped mempool txs", len(removed)),
zap.Bool("state ready", vm.StateReady()),
Expand Down
Loading