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

Stateful block to vm #1744

Merged
merged 51 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0a3f3b8
Separate verifyExpiryReplayProtection to separate function
aaronbuchwald Oct 28, 2024
3aaa513
Move GetVerifyContext into innerVerify
aaronbuchwald Oct 31, 2024
a43dfcc
Move execution from block to executor
aaronbuchwald Oct 31, 2024
1c3626c
remove unused receiver
aaronbuchwald Oct 31, 2024
fd58510
Start moving stateful block to VM
aaronbuchwald Nov 5, 2024
03018a4
add locking to isRepeat
aaronbuchwald Nov 5, 2024
62a096d
unexport executeTxs
aaronbuchwald Nov 5, 2024
0e7b9bd
remove unneeded fields from stateful block
aaronbuchwald Nov 5, 2024
b6ce2d0
Remove initializeBuilt from stateful block
aaronbuchwald Nov 5, 2024
376351d
Finish TODOs
aaronbuchwald Nov 5, 2024
522fdcd
Add cleared mempool metric back
aaronbuchwald Nov 5, 2024
d6bc275
remove txRemoved events
aaronbuchwald Nov 5, 2024
1005ca2
Init genesis executedBlock
aaronbuchwald Nov 5, 2024
ff87bdc
Fix integration tests
aaronbuchwald Nov 6, 2024
228a0c9
Merge branch 'main' into stateful-block-to-vm
aaronbuchwald Nov 6, 2024
f0cf9a8
Fix merge and clean up block types
aaronbuchwald Nov 6, 2024
88a191b
Remove unneeded param
aaronbuchwald Nov 6, 2024
51d81b3
Move config to separate file
aaronbuchwald Nov 6, 2024
1c46a8d
Add comment to where ExecutionBlock extra fields are populated
aaronbuchwald Nov 6, 2024
0c6dbef
Remove unneeded argument
aaronbuchwald Nov 6, 2024
256624e
Clean up last accepted block getters
aaronbuchwald Nov 6, 2024
0005130
rearrange stateful block fields
aaronbuchwald Nov 6, 2024
e38d52c
Move verify/accept/reject metrics handling from vm into chain
aaronbuchwald Nov 6, 2024
896a167
Remove unused tx metrics from vm
aaronbuchwald Nov 6, 2024
d0698b3
Rename ExecutionConfig to Config
aaronbuchwald Nov 7, 2024
0c91606
Merge branch 'main' into stateful-block-to-vm
aaronbuchwald Nov 7, 2024
adb7b04
fix lint
aaronbuchwald Nov 7, 2024
46fec0e
add nolint spancheck for sigVerifySpan
aaronbuchwald Nov 7, 2024
fa0afa2
Move sync backfill into chain package
aaronbuchwald Nov 7, 2024
965219c
move validity window to separate struct
aaronbuchwald Nov 7, 2024
39e8b3a
fix lint and skip low quality vm unit test
aaronbuchwald Nov 8, 2024
5964d8b
fix syncer
aaronbuchwald Nov 8, 2024
f70b383
Remove buildBlock type
aaronbuchwald Nov 8, 2024
a60d9e9
move mempool back from builder to dependencies
aaronbuchwald Nov 8, 2024
02dece0
Update assemble block
aaronbuchwald Nov 8, 2024
955ef6c
use field instead of function for vm last accepted block where possible
aaronbuchwald Nov 8, 2024
bd2dce6
Fix span naming in chain
aaronbuchwald Nov 8, 2024
73a25df
remove buildBlock type
aaronbuchwald Nov 8, 2024
4639776
clean up spans
aaronbuchwald Nov 8, 2024
20cdfe9
Fix spans
aaronbuchwald Nov 8, 2024
a4c8606
Revert "Remove buildBlock type"
aaronbuchwald Nov 8, 2024
254ec9c
Remove buildBlock type
aaronbuchwald Nov 8, 2024
44fdf31
Separate chain into components and update chain constructor
aaronbuchwald Nov 8, 2024
2bf28b7
Remove chain backend interface
aaronbuchwald Nov 8, 2024
71b4d04
Merge branch 'main' into stateful-block-to-vm
aaronbuchwald Nov 8, 2024
047f180
remove unused interface
aaronbuchwald Nov 8, 2024
b13875f
Pass log/tracer params explicitly to time validity window
aaronbuchwald Nov 12, 2024
4238909
Address comments
aaronbuchwald Nov 12, 2024
e893118
fix lint
aaronbuchwald Nov 12, 2024
24e89d0
fix metric naming
aaronbuchwald Nov 12, 2024
040b19d
Merge branch 'main' into stateful-block-to-vm
aaronbuchwald Nov 12, 2024
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
4 changes: 1 addition & 3 deletions api/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ type VM interface {
verifySig bool,
txs []*chain.Transaction,
) (errs []error)
// LastAcceptedBlock provides the most recent block that the VM has accepted.
// The value returned is guaranteed to be non-nil.
LastAcceptedBlock() *chain.StatefulBlock
LastAcceptedBlockResult() *chain.ExecutedBlock
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
UnitPrices(context.Context) (fees.Dimensions, error)
CurrentValidators(
context.Context,
Expand Down
4 changes: 2 additions & 2 deletions api/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (i *Indexer) initBlocks() error {
return err
}

i.blockIDToHeight.Put(blk.BlockID, blk.Block.Hght)
i.blockIDToHeight.Put(blk.Block.ID(), blk.Block.Hght)
i.blockHeightToBlock.Put(blk.Block.Hght, blk)
lastHeight = blk.Block.Hght
}
Expand Down Expand Up @@ -133,7 +133,7 @@ func (i *Indexer) storeBlock(blk *chain.ExecutedBlock) error {
return err
}

i.blockIDToHeight.Put(blk.BlockID, blk.Block.Hght)
i.blockIDToHeight.Put(blk.Block.ID(), blk.Block.Hght)
i.blockHeightToBlock.Put(blk.Block.Hght, blk)
i.lastHeight.Store(blk.Block.Hght)

Expand Down
8 changes: 4 additions & 4 deletions api/indexer/indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ func checkBlocks(
expectedLatestBlk := expectedBlocks[len(expectedBlocks)-1]
latestBlk, err := indexer.GetLatestBlock()
require.NoError(err)
require.Equal(expectedLatestBlk.BlockID, latestBlk.BlockID)
require.Equal(expectedLatestBlk.Block.ID(), latestBlk.Block.ID())

// Confirm all blocks in the window are retrievable
for i := 0; i < blockWindow; i++ {
expectedBlk := expectedBlocks[len(expectedBlocks)-1-i]
height := expectedBlk.Block.Hght
blkByHeight, err := indexer.GetBlockByHeight(height)
require.NoError(err)
require.Equal(expectedBlk.BlockID, blkByHeight.BlockID)
require.Equal(expectedBlk.Block.ID(), blkByHeight.Block.ID())

blkByID, err := indexer.GetBlock(expectedBlk.BlockID)
blkByID, err := indexer.GetBlock(expectedBlk.Block.ID())
require.NoError(err)
require.Equal(expectedBlk.BlockID, blkByID.BlockID)
require.Equal(expectedBlk.Block.ID(), blkByID.Block.ID())
}

// Confirm blocks outside the window are not retrievable
Expand Down
8 changes: 4 additions & 4 deletions api/jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ type LastAcceptedReply struct {
}

func (j *JSONRPCServer) LastAccepted(_ *http.Request, _ *struct{}, reply *LastAcceptedReply) error {
blk := j.vm.LastAcceptedBlock()
reply.Height = blk.Hght
reply.BlockID = blk.ID()
reply.Timestamp = blk.Tmstmp
blk := j.vm.LastAcceptedBlockResult()
reply.Height = blk.Block.Hght
reply.BlockID = blk.Block.ID()
reply.Timestamp = blk.Block.Tmstmp
return nil
}

Expand Down
14 changes: 0 additions & 14 deletions api/ws/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ func OptionFunc(v api.VM, config Config) (vm.Opt, error) {
)

webSocketFactory := NewWebSocketServerFactory(handler)
txRemovedSubscription := event.SubscriptionFuncFactory[vm.TxRemovedEvent]{
AcceptF: func(event vm.TxRemovedEvent) error {
return server.RemoveTx(event.TxID, event.Err)
},
}
Comment on lines -69 to -73
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be factored out to a separate PR if needed. Removed this as part of this change so that PreExecute can move into the chain/ package and would prefer not to force that function to differentiate between an error that can notify the caller the tx will never go through vs. may go through in the future. This is not currently providing any new information to the caller since it only sends this notification for an invalid signature, which the caller could always check itself.


blockSubscription := event.SubscriptionFuncFactory[*chain.ExecutedBlock]{
AcceptF: func(event *chain.ExecutedBlock) error {
Expand All @@ -80,7 +75,6 @@ func OptionFunc(v api.VM, config Config) (vm.Opt, error) {

return vm.NewOpt(
vm.WithBlockSubscriptions(blockSubscription),
vm.WithTxRemovedSubscriptions(txRemovedSubscription),
vm.WithVMAPIs(webSocketFactory),
), nil
}
Expand Down Expand Up @@ -159,14 +153,6 @@ func (w *WebSocketServer) AddTxListener(tx *chain.Transaction, c *pubsub.Connect
w.expiringTxs.Add([]*chain.Transaction{tx})
}

// If never possible for a tx to enter mempool, call this
func (w *WebSocketServer) RemoveTx(txID ids.ID, err error) error {
w.txL.Lock()
defer w.txL.Unlock()

return w.removeTx(txID, err)
}

func (w *WebSocketServer) removeTx(txID ids.ID, err error) error {
listeners, ok := w.txListeners[txID]
if !ok {
Expand Down
38 changes: 38 additions & 0 deletions chain/accepter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package chain

import (
"context"

"github.com/ava-labs/avalanchego/trace"
)

type Accepter struct {
tracer trace.Tracer
validityWindow *TimeValidityWindow
metrics *chainMetrics
}

func NewAccepter(
tracer trace.Tracer,
validityWindow *TimeValidityWindow,
metrics *chainMetrics,
) *Accepter {
return &Accepter{
tracer: tracer,
validityWindow: validityWindow,
metrics: metrics,
}
}

func (a *Accepter) AcceptBlock(ctx context.Context, blk *ExecutionBlock) error {
_, span := a.tracer.Start(ctx, "Chain.AcceptBlock")
defer span.End()

a.metrics.txsAccepted.Add(float64(len(blk.Txs)))
a.validityWindow.Accept(blk)

return nil
}
74 changes: 27 additions & 47 deletions chain/assembler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,70 +5,50 @@ package chain

import (
"context"
"time"

"github.com/ava-labs/hypersdk/utils"
"github.com/ava-labs/avalanchego/trace"

"github.com/ava-labs/hypersdk/state"
)

type Assembler struct {
vm VM
tracer trace.Tracer
processor *Processor
}

func NewAssembler(tracer trace.Tracer, processor *Processor) *Assembler {
return &Assembler{
tracer: tracer,
processor: processor,
}
}

func (a *Assembler) AssembleBlock(
ctx context.Context,
parent *StatefulBlock,
parentView state.View,
parent *ExecutionBlock,
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
timestamp int64,
blockHeight uint64,
txs []*Transaction,
) (*StatefulBlock, error) {
ctx, span := a.vm.Tracer().Start(ctx, "chain.AssembleBlock")
) (*ExecutedBlock, state.View, error) {
ctx, span := a.tracer.Start(ctx, "Chain.AssembleBlock")
defer span.End()

parentView, err := parent.View(ctx, true)
if err != nil {
return nil, err
}
parentStateRoot, err := parentView.GetMerkleRoot(ctx)
if err != nil {
return nil, err
}

blk := &StatelessBlock{
Prnt: parent.ID(),
Tmstmp: timestamp,
Hght: blockHeight,
Txs: txs,
StateRoot: parentStateRoot,
}
for _, tx := range txs {
blk.authCounts[tx.Auth.GetTypeID()]++
return nil, nil, err
}

blkBytes, err := blk.Marshal()
sb, err := NewStatelessBlock(
parent.ID(),
timestamp,
blockHeight,
txs,
parentStateRoot,
)
if err != nil {
return nil, err
return nil, nil, err
}
b := &StatefulBlock{
StatelessBlock: blk,
t: time.UnixMilli(blk.Tmstmp),
bytes: blkBytes,
accepted: false,
vm: a.vm,
id: utils.ToID(blkBytes),
}
return b, b.populateTxs(ctx) // TODO: simplify since txs are guaranteed to already be de-duplicated here
}

func (a *Assembler) ExecuteBlock(
ctx context.Context,
b *StatefulBlock,
) (*ExecutedBlock, error) {
ctx, span := a.vm.Tracer().Start(ctx, "chain.ExecuteBlock")
defer span.End()

if err := b.Verify(ctx); err != nil {
return nil, err
}

return NewExecutedBlockFromStateful(b), nil
executionBlock := NewExecutionBlock(sb)
return a.processor.Execute(ctx, parentView, executionBlock)
}
Loading
Loading