From a6a6e9e0e959ea815e159b4646adec251c20304c Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Wed, 14 Aug 2024 22:01:59 +0900 Subject: [PATCH 01/18] prevent dup L2 block & skip partition check for ToB block --- chain/chunk.go | 50 +++++++++++++++++++++++++++++++++++++++++++++- chain/processor.go | 42 ++++++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/chain/chunk.go b/chain/chunk.go index 6fa8132f68..c413a11f6f 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -18,7 +18,19 @@ import ( const chunkPrealloc = 16_384 +const ( + AnchorToB = iota + AnchorRoB +) + +type Anchor struct { + BlockType int `json:"blockType"` // use to determine if it is TOB or ROB + Namespace string `json:"namespace"` +} + type Chunk struct { + Anchor *Anchor `json:"anchor"` // if null then the chunk is generated from txs in mempool + Slot int64 `json:"slot"` // rounded to nearest 100ms Txs []*Transaction `json:"txs"` @@ -202,6 +214,11 @@ func (c *Chunk) Digest() ([]byte, error) { size := consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + bls.PublicKeyLen p := codec.NewWriter(size, consts.NetworkSizeLimit) + // p.PackBool(c.Anchor != nil) + // if c.Anchor != nil { + // p.PackInt(c.Anchor.BlockType) + // p.PackString(c.Anchor.Namespace) + // } // Marshal transactions p.PackInt64(c.Slot) p.PackInt(len(c.Txs)) @@ -224,7 +241,14 @@ func (c *Chunk) ID() ids.ID { } func (c *Chunk) Size() int { - return consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + codec.AddressLen + bls.PublicKeyLen + bls.SignatureLen + size := consts.BoolLen + consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + codec.AddressLen + bls.PublicKeyLen + bls.SignatureLen + + isAnchor := c.Anchor != nil + if isAnchor { + size += consts.IntLen + size += codec.StringLen(c.Anchor.Namespace) + } + return size } func (c *Chunk) Units(sm StateManager, r Rules) (Dimensions, error) { @@ -268,7 +292,17 @@ func (c *Chunk) Marshal() ([]byte, error) { p.PackAddress(c.Beneficiary) p.PackFixedBytes(bls.PublicKeyToCompressedBytes(c.Signer)) p.PackFixedBytes(bls.SignatureToBytes(c.Signature)) + + isAnchorChunk := c.Anchor != nil + p.PackBool(isAnchorChunk) + fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) + if isAnchorChunk { + p.PackInt(c.Anchor.BlockType) + p.PackString(c.Anchor.Namespace) + } + bytes, err := p.Bytes(), p.Err() + fmt.Printf("chunk bytes: %s\n", hex.EncodeToString(bytes)) if err != nil { return nil, err } @@ -300,6 +334,8 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { c Chunk authCounts = make(map[uint8]int) ) + fmt.Printf("chunk bytes: %s\n", hex.EncodeToString(raw)) + c.id = utils.ToID(raw) // Parse transactions @@ -334,6 +370,18 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { } c.Signature = signature + isAnchorChunk := p.UnpackBool() + fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) + if isAnchorChunk { + blockType := p.UnpackInt(false) + namespace := p.UnpackString(false) + anchor := Anchor{ + BlockType: blockType, + Namespace: namespace, + } + c.Anchor = &anchor + } + // Ensure no leftover bytes if !p.Empty() { return nil, fmt.Errorf("%w: remaining=%d", ErrInvalidObject, len(raw)-p.Offset()) diff --git a/chain/processor.go b/chain/processor.go index 6be26d1f0b..7944420f55 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -23,6 +23,7 @@ type Processor struct { latestPHeight *uint64 epochHeights []*uint64 + acceptedNS map[string]struct{} // to record accepted L2 block, we only allow one L2 block per SEQ block timestamp int64 epoch uint64 @@ -216,6 +217,24 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { return } + // constraint on only allowing one L2 block per SEQ block + if chunk.Anchor != nil { + switch chunk.Anchor.BlockType { + case AnchorToB: + if _, exists := p.acceptedNS["TOB"]; exists { + p.markChunkTxsInvalid(chunkIndex, chunkTxs) + return + } + p.acceptedNS["TOB"] = struct{}{} + case AnchorRoB: + if _, exists := p.acceptedNS[chunk.Anchor.Namespace]; exists { + p.markChunkTxsInvalid(chunkIndex, chunkTxs) + return + } + p.acceptedNS[chunk.Anchor.Namespace] = struct{}{} + } + } + // TODO: consider doing some of these checks in parallel queueStart := time.Now() for rtxIndex, rtx := range chunk.Txs { @@ -286,16 +305,19 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { // If this passes, we know that latest pHeight must be non-nil // Check that transaction is in right partition - parition, err := p.vm.AddressPartition(ctx, txEpoch, *epochHeight, tx.Action.NMTNamespace(), tx.Partition()) - if err != nil { - p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) - p.results[chunkIndex][txIndex] = &Result{Valid: false} - return nil, nil - } - if parition != chunk.Producer { - p.vm.Logger().Warn("tx in wrong partition", zap.Stringer("txID", tx.ID())) - p.results[chunkIndex][txIndex] = &Result{Valid: false} - return nil, nil + if chunk.Anchor == nil || chunk.Anchor != nil && chunk.Anchor.BlockType == AnchorRoB { // RoB block and chunk from mempool + parition, err := p.vm.AddressPartition(ctx, txEpoch, *epochHeight, tx.Action.NMTNamespace(), tx.Partition()) + if err != nil { + p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) + p.results[chunkIndex][txIndex] = &Result{Valid: false} + return nil, nil + } + if parition != chunk.Producer { + p.vm.Logger().Warn("tx in wrong partition", zap.Stringer("txID", tx.ID())) + p.results[chunkIndex][txIndex] = &Result{Valid: false} + return nil, nil + } + } else { // TODO: handle ToB, probably don't need this branch } // Check that transaction isn't frozen (can avoid state lookups) From fcd0c6c6f7177989c96abe1e93a9bd6043a5094e Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Wed, 14 Aug 2024 23:51:31 +0900 Subject: [PATCH 02/18] two paths of partitioning --- chain/dependencies.go | 3 ++- chain/processor.go | 19 ++++++++++++++++--- vm/chunk_manager.go | 4 ++-- vm/proposer_monitor.go | 35 ++++++++++++++++++++++++++++++++--- vm/resolutions.go | 9 +++++++-- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/chain/dependencies.go b/chain/dependencies.go index 1bd34e4b45..74f5935983 100644 --- a/chain/dependencies.go +++ b/chain/dependencies.go @@ -133,7 +133,8 @@ type VM interface { CacheValidators(ctx context.Context, height uint64) IsValidator(ctx context.Context, height uint64, nodeID ids.NodeID) (bool, error) // TODO: filter based on being part of whole epoch GetAggregatePublicKey(ctx context.Context, height uint64, signers set.Bits, num, denom uint64) (*bls.PublicKey, error) // cached - AddressPartition(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) + AddressPartition(ctx context.Context, epoch uint64, height uint64, addr codec.Address, partition uint8) (ids.NodeID, error) + AddressPartitionByNamespace(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) } type Mempool interface { diff --git a/chain/processor.go b/chain/processor.go index 7944420f55..0ccc8b3e09 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -305,8 +305,8 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { // If this passes, we know that latest pHeight must be non-nil // Check that transaction is in right partition - if chunk.Anchor == nil || chunk.Anchor != nil && chunk.Anchor.BlockType == AnchorRoB { // RoB block and chunk from mempool - parition, err := p.vm.AddressPartition(ctx, txEpoch, *epochHeight, tx.Action.NMTNamespace(), tx.Partition()) + if chunk.Anchor == nil { // from mempool + parition, err := p.vm.AddressPartition(ctx, txEpoch, *epochHeight, tx.Sponsor(), tx.Partition()) if err != nil { p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) p.results[chunkIndex][txIndex] = &Result{Valid: false} @@ -317,7 +317,20 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { p.results[chunkIndex][txIndex] = &Result{Valid: false} return nil, nil } - } else { // TODO: handle ToB, probably don't need this branch + } else { // from Anchor, which we allow + if chunk.Anchor.BlockType == AnchorRoB { + parition, err := p.vm.AddressPartitionByNamespace(ctx, txEpoch, *epochHeight, tx.Action.NMTNamespace(), tx.Partition()) + if err != nil { + p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) + p.results[chunkIndex][txIndex] = &Result{Valid: false} + return nil, nil + } + if parition != chunk.Producer { + p.vm.Logger().Warn("tx in wrong partition", zap.Stringer("txID", tx.ID())) + p.results[chunkIndex][txIndex] = &Result{Valid: false} + return nil, nil + } + } } // Check that transaction isn't frozen (can avoid state lookups) diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index bbe93d1bc7..cde67c66b0 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -969,7 +969,7 @@ func (c *ChunkManager) Run(appSender common.AppSender) { invalid = true break } - partition, err := c.vm.proposerMonitor.AddressPartition(ctx, epoch, epochHeight, tx.Action.NMTNamespace(), tx.Partition()) + partition, err := c.vm.proposerMonitor.AddressPartition(ctx, epoch, epochHeight, tx.Sponsor(), tx.Partition()) if err != nil { c.vm.Logger().Debug("unable to compute address partition", zap.Error(err)) invalid = true @@ -1398,7 +1398,7 @@ func (c *ChunkManager) HandleTx(ctx context.Context, tx *chain.Transaction) { c.vm.Logger().Warn("cannot lookup epoch", zap.Error(err)) return } - partition, err := c.vm.proposerMonitor.AddressPartition(ctx, epoch, epochHeight, tx.Action.NMTNamespace(), tx.Partition()) + partition, err := c.vm.proposerMonitor.AddressPartition(ctx, epoch, epochHeight, tx.Sponsor(), tx.Partition()) if err != nil { c.vm.Logger().Warn("unable to compute address partition", zap.Error(err)) return diff --git a/vm/proposer_monitor.go b/vm/proposer_monitor.go index 3f79d00fae..955df6c2d0 100644 --- a/vm/proposer_monitor.go +++ b/vm/proposer_monitor.go @@ -237,9 +237,38 @@ func (p *ProposerMonitor) RandomValidator(ctx context.Context, height uint64) (i return ids.NodeID{}, fmt.Errorf("no validators") } -// @todo instead of codec.Address, we can do tx.NamespaceID(). -// this makes, sure all general transactions are sampled by a validator, whereas rollup transactions in individual chunks per validator. -func (p *ProposerMonitor) AddressPartition(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) { +func (p *ProposerMonitor) AddressPartition(ctx context.Context, epoch uint64, height uint64, addr codec.Address, partition uint8) (ids.NodeID, error) { + // Get determinisitc ordering of validators + info, ok := p.proposers.Get(height) + if !ok { + info = p.Fetch(ctx, height) + } + if info == nil { + return ids.NodeID{}, errors.New("could not get validator set for height") + } + if len(info.partitionSet) == 0 { + return ids.NodeID{}, errors.New("no validators") + } + + // Compute seed + seedBytes := make([]byte, consts.Uint64Len*2+codec.AddressLen) + binary.BigEndian.PutUint64(seedBytes, epoch) // ensures partitions rotate even if P-Chain height is static + binary.BigEndian.PutUint64(seedBytes[consts.Uint64Len:], height) + copy(seedBytes[consts.Uint64Len*2:], addr[:]) + seed := utils.ToID(seedBytes) + + // Select validator + // + // It is important to ensure each partition is actually a unique validator, otherwise + // the censorship resistance that partitions are supposed to provide is lost (all partitions + // could be allocated to a single validator if we aren't careful). + seedInt := new(big.Int).SetBytes(seed[:]) + partitionInt := new(big.Int).Add(seedInt, big.NewInt(int64(partition))) + partitionIdx := new(big.Int).Mod(partitionInt, big.NewInt(int64(len(info.partitionSet)))).Int64() + return info.partitionSet[int(partitionIdx)], nil +} + +func (p *ProposerMonitor) AddressPartitionByNamespace(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) { // Get determinisitc ordering of validators info, ok := p.proposers.Get(height) if !ok { diff --git a/vm/resolutions.go b/vm/resolutions.go index d59fe526a5..df30b5fba0 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -414,8 +414,13 @@ func (vm *VM) CacheValidators(ctx context.Context, height uint64) { vm.proposerMonitor.Fetch(ctx, height) } -func (vm *VM) AddressPartition(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) { - return vm.proposerMonitor.AddressPartition(ctx, epoch, height, ns, partition) +func (vm *VM) AddressPartition(ctx context.Context, epoch uint64, height uint64, addr codec.Address, partition uint8) (ids.NodeID, error) { + return vm.proposerMonitor.AddressPartition(ctx, epoch, height, addr, partition) +} + +// used for txs from Anchor +func (vm *VM) AddressPartitionByNamespace(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) { + return vm.proposerMonitor.AddressPartitionByNamespace(ctx, epoch, height, ns, partition) } func (vm *VM) IsValidator(ctx context.Context, height uint64, nid ids.NodeID) (bool, error) { From b23f7e6c9fd7e92f25a581ab0666cbe6cdaa759c Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 15 Aug 2024 03:05:32 +0900 Subject: [PATCH 03/18] prototype of anchor chunk handling --- chain/chunk.go | 158 ++++++++++++++++++++++++++++++++++++++++-- rpc/dependencies.go | 3 + rpc/jsonrpc_server.go | 31 +++++++++ vm/chunk_manager.go | 31 +++++++++ vm/resolutions.go | 4 ++ 5 files changed, 220 insertions(+), 7 deletions(-) diff --git a/chain/chunk.go b/chain/chunk.go index c413a11f6f..cf11c1ae70 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -34,8 +34,9 @@ type Chunk struct { Slot int64 `json:"slot"` // rounded to nearest 100ms Txs []*Transaction `json:"txs"` - Producer ids.NodeID `json:"producer"` - Beneficiary codec.Address `json:"beneficiary"` // used for fees + PriorityFeeReceiverAddr codec.Address `json:"priorityFeeReceiver"` + Producer ids.NodeID `json:"producer"` + Beneficiary codec.Address `json:"beneficiary"` // used for fees Signer *bls.PublicKey `json:"signer"` Signature *bls.Signature `json:"signature"` @@ -46,6 +47,148 @@ type Chunk struct { authCounts map[uint8]int } +func BuildChunkFromAnchor(ctx context.Context, vm VM, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { + start := time.Now() + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + sm := vm.StateManager() + r := vm.Rules(now) + c := &Chunk{ + Slot: slot, + Txs: txs, + } + epoch := utils.Epoch(now, r.GetEpochDuration()) + + // Don't build chunk if no P-Chain height for epoch + timestamp, heights, err := vm.Engine().GetEpochHeights(ctx, []uint64{epoch}) + if err != nil { + return nil, err + } + executedEpoch := utils.Epoch(timestamp, r.GetEpochDuration()) // epoch duration set to 10 seconds. + if executedEpoch+2 < epoch { // only require + 2 because we don't care about epoch + 1 like in verification. + return nil, fmt.Errorf("executed epoch (%d) is too far behind (%d) to verify chunk", executedEpoch, epoch) + } + if heights[0] == nil { + return nil, fmt.Errorf("no P-Chain height for epoch %d", epoch) + } + + // Check if validator + // + // If not a validator in this epoch height, don't build. + amValidator, err := vm.IsValidator(ctx, *heights[0], vm.NodeID()) + if err != nil { + return nil, err + } + if !amValidator { + return nil, ErrNotAValidator + } + + // Pack chunk for build duration + // + // TODO: sort mempool by priority and fit (only fetch items that can be included) + var ( + maxChunkUnits = r.GetMaxChunkUnits() + chunkUnits = Dimensions{} + full bool + authCounts = make(map[uint8]int) + ) + for _, tx := range txs { + // Ensure we haven't included this transaction in a chunk yet + // + // Should protect us from issuing repeat txs (if others get duplicates, + // there will be duplicate inclusion but this is fixed with partitions) + if vm.IsIssuedTx(ctx, tx) { + return nil, fmt.Errorf("tx already issued") + } + + // TODO: count outstanding for an account and ensure less than epoch bond + // if too many, just put back into mempool and try again later + + // TODO: ensure tx can still be processed (bond not frozen) + + // TODO: skip if transaction will pay < max fee over validity window (this fee period or a future one based on limit + // of activity). + + // TODO: check if chunk units greater than limit + + // TODO: verify transactions + if tx.Base.Timestamp > c.Slot { + vm.RecordChunkBuildTxDropped() + return nil, fmt.Errorf("tx timestamp greater than the slot") + } + + // Check if tx can fit in chunk + txUnits, err := tx.Units(sm, r) + if err != nil { + vm.RecordChunkBuildTxDropped() + vm.Logger().Warn("failed to get units for transaction", zap.Error(err)) + continue + } + nextUnits, err := Add(chunkUnits, txUnits) + if err != nil || !maxChunkUnits.Greater(nextUnits) { + return nil, fmt.Errorf("too many units consumed in a chunk") + } + chunkUnits = nextUnits + + // Add transaction to chunk + vm.IssueTx(ctx, tx) // prevents duplicate from being re-added to mempool + c.Txs = append(c.Txs, tx) + authCounts[tx.Auth.GetTypeID()]++ + } + + // Discard chunk if nothing produced + if len(c.Txs) == 0 { + return nil, ErrNoTxs + } + + // Setup chunk + c.PriorityFeeReceiverAddr = priorityFeeReceiver + c.Producer = vm.NodeID() + c.Beneficiary = vm.Beneficiary() + c.Signer = vm.Signer() + c.units = &chunkUnits + c.authCounts = authCounts + + // Sign chunk + digest, err := c.Digest() + if err != nil { + return nil, err + } + wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + if err != nil { + return nil, err + } + sig, err := vm.Sign(wm) + if err != nil { + return nil, err + } + c.Signature, err = bls.SignatureFromBytes(sig) + if err != nil { + return nil, err + } + bytes, err := c.Marshal() + if err != nil { + return nil, err + } + c.id = utils.ToID(bytes) + + vm.Logger().Info( + "built chunk with signature from anchor msg", + zap.Stringer("nodeID", vm.NodeID()), + zap.Uint32("networkID", r.NetworkID()), + zap.Stringer("chainID", r.ChainID()), + zap.Int64("slot", c.Slot), + zap.Uint64("epoch", epoch), + zap.Bool("full", full), + zap.Int("txs", len(c.Txs)), + zap.Any("units", chunkUnits), + zap.String("signer", hex.EncodeToString(bls.PublicKeyToCompressedBytes(c.Signer))), + zap.String("signature", hex.EncodeToString(bls.SignatureToBytes(c.Signature))), + zap.Duration("t", time.Since(start)), + ) + return c, nil + +} + func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance @@ -164,6 +307,7 @@ func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { } // Setup chunk + c.PriorityFeeReceiverAddr = codec.EmptyAddress c.Producer = vm.NodeID() c.Beneficiary = vm.Beneficiary() c.Signer = vm.Signer() @@ -214,11 +358,11 @@ func (c *Chunk) Digest() ([]byte, error) { size := consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + bls.PublicKeyLen p := codec.NewWriter(size, consts.NetworkSizeLimit) - // p.PackBool(c.Anchor != nil) - // if c.Anchor != nil { - // p.PackInt(c.Anchor.BlockType) - // p.PackString(c.Anchor.Namespace) - // } + p.PackBool(c.Anchor != nil) + if c.Anchor != nil { + p.PackInt(c.Anchor.BlockType) + p.PackString(c.Anchor.Namespace) + } // Marshal transactions p.PackInt64(c.Slot) p.PackInt(len(c.Txs)) diff --git a/rpc/dependencies.go b/rpc/dependencies.go index edfce342a2..7f4531a042 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/chain" + "github.com/ava-labs/hypersdk/codec" ) type VM interface { @@ -42,4 +43,6 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() + + HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error } diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index 97a556a4a8..5f689d8be5 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -89,6 +89,37 @@ func (j *JSONRPCServer) SubmitTx( return j.vm.Submit(ctx, false, []*chain.Transaction{tx})[0] } +// TODO: make it permissioned +type SubmitAnchorChunkArgs struct { + Slot int64 `json:"slot"` + Txs []byte `json:"txs"` // raw tx + PriorityFeeReceiverAddr codec.Address `json:"priorityFeeReceiverAddr"` +} + +type SubmitAnchorChunkReply struct { + Success bool `json:"success"` +} + +func (j *JSONRPCServer) SubmitAnchorChunk( + req *http.Request, + args *SubmitAnchorChunkArgs, + reply *SubmitAnchorChunkReply, +) error { + actionRegistry, authRegistery := j.vm.Registry() + _, txs, err := chain.UnmarshalTxs(args.Txs, len(args.Txs), actionRegistry, authRegistery) + if err != nil { + return err + } + + err = j.vm.HandleAnchorChunk(context.TODO(), args.Slot, txs, args.PriorityFeeReceiverAddr) + if err == nil { + reply.Success = true + return nil + } + + return err +} + type LastAcceptedReply struct { Height uint64 `json:"height"` BlockID ids.ID `json:"blockId"` diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index cde67c66b0..f60c06ab10 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -1449,6 +1449,37 @@ func (c *ChunkManager) HandleTx(ctx context.Context, tx *chain.Transaction) { c.sendTxGossip(ctx, gossipable) } +func (c *ChunkManager) SignAnchorChunkHeader(ctx context.Context, header *chain.Chunk) ([]byte, error) { + digest, err := header.Digest() + if err != nil { + return nil, err + } + + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := c.vm.Rules(now) + wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + if err != nil { + return nil, err + } + + return c.vm.Sign(wm) +} + +// fields that are guaranteed populated: +// Slot, Txs, PriorityFeeReceiverAddr +func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { + chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, slot, txs, priorityFeeReceiverAddr) + if err != nil { + return err + } + + // for gossipping & sig collecting + c.auth.Add(chunk) + c.PushChunk(ctx, chunk) + + return nil +} + func (c *ChunkManager) sendTxGossip(ctx context.Context, gossip *txGossip) { txs := maps.Values(gossip.txs) txBytes, err := chain.MarshalTxs(txs) diff --git a/vm/resolutions.go b/vm/resolutions.go index df30b5fba0..c99860a667 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -588,6 +588,10 @@ func (vm *VM) Engine() *chain.Engine { return vm.engine } +func (vm *VM) HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { + return vm.cm.HandleAnchorChunk(ctx, slot, txs, priorityFeeReceiverAddr) +} + func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { return vm.issuedTxs.Has(tx) } From 2beca4fea5c6e0cb7098ad9ffc6c207db5d6ef89 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 15 Aug 2024 03:14:31 +0900 Subject: [PATCH 04/18] attach anchor meta to rpc.SubmitAnchorChunk --- chain/chunk.go | 2 +- rpc/dependencies.go | 2 +- rpc/jsonrpc_server.go | 3 ++- vm/chunk_manager.go | 4 ++-- vm/resolutions.go | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/chain/chunk.go b/chain/chunk.go index cf11c1ae70..30ffd450e2 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -47,7 +47,7 @@ type Chunk struct { authCounts map[uint8]int } -func BuildChunkFromAnchor(ctx context.Context, vm VM, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { +func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *Anchor, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance sm := vm.StateManager() diff --git a/rpc/dependencies.go b/rpc/dependencies.go index 7f4531a042..a957a13a52 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -44,5 +44,5 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() - HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error + HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error } diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index 5f689d8be5..a712d8cf13 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -91,6 +91,7 @@ func (j *JSONRPCServer) SubmitTx( // TODO: make it permissioned type SubmitAnchorChunkArgs struct { + Anchor chain.Anchor `json:"anchor"` Slot int64 `json:"slot"` Txs []byte `json:"txs"` // raw tx PriorityFeeReceiverAddr codec.Address `json:"priorityFeeReceiverAddr"` @@ -111,7 +112,7 @@ func (j *JSONRPCServer) SubmitAnchorChunk( return err } - err = j.vm.HandleAnchorChunk(context.TODO(), args.Slot, txs, args.PriorityFeeReceiverAddr) + err = j.vm.HandleAnchorChunk(context.TODO(), &args.Anchor, args.Slot, txs, args.PriorityFeeReceiverAddr) if err == nil { reply.Success = true return nil diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index f60c06ab10..6008a5a8fa 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -1467,8 +1467,8 @@ func (c *ChunkManager) SignAnchorChunkHeader(ctx context.Context, header *chain. // fields that are guaranteed populated: // Slot, Txs, PriorityFeeReceiverAddr -func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { - chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, slot, txs, priorityFeeReceiverAddr) +func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { + chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, anchor, slot, txs, priorityFeeReceiverAddr) if err != nil { return err } diff --git a/vm/resolutions.go b/vm/resolutions.go index c99860a667..8e0a8a2760 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -588,8 +588,8 @@ func (vm *VM) Engine() *chain.Engine { return vm.engine } -func (vm *VM) HandleAnchorChunk(ctx context.Context, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { - return vm.cm.HandleAnchorChunk(ctx, slot, txs, priorityFeeReceiverAddr) +func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { + return vm.cm.HandleAnchorChunk(ctx, anchor, slot, txs, priorityFeeReceiverAddr) } func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { From 4e45140f0a96147e3306558060c16246458e9d23 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 15 Aug 2024 16:56:29 +0900 Subject: [PATCH 05/18] basic arch --- anchor/anchor.go | 21 ++++++++++++++++++ anchor/dependencies.go | 13 +++++++++++ config/config.go | 1 + examples/morpheusvm/config/config.go | 7 ++++++ rpc/dependencies.go | 3 --- rpc/jsonrpc_server.go | 32 ---------------------------- vm/chunk_manager.go | 7 +----- vm/dependencies.go | 1 + vm/resolutions.go | 4 ++++ vm/vm.go | 5 +++++ 10 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 anchor/anchor.go create mode 100644 anchor/dependencies.go diff --git a/anchor/anchor.go b/anchor/anchor.go new file mode 100644 index 0000000000..c65869b43a --- /dev/null +++ b/anchor/anchor.go @@ -0,0 +1,21 @@ +package anchor + +type Anchor struct { + vm VM + Url string `json:"url"` +} + +func NewAnchor(url string, vm VM) *Anchor { + return &Anchor{ + Url: url, + vm: vm, + } +} + +func (a *Anchor) RequestAnchorDigest() { + +} + +func (a *Anchor) RequestAnchorChunk() { + +} diff --git a/anchor/dependencies.go b/anchor/dependencies.go new file mode 100644 index 0000000000..3185fc8521 --- /dev/null +++ b/anchor/dependencies.go @@ -0,0 +1,13 @@ +package anchor + +import ( + "context" + + "github.com/ava-labs/hypersdk/chain" + "github.com/ava-labs/hypersdk/codec" +) + +type VM interface { + HandleAnchorChunk(ctx context.Context, meta *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error + SignAnchorDigest(ctx context.Context, digest []byte) ([]byte, error) +} diff --git a/config/config.go b/config/config.go index 0372d420cd..17b50a4a04 100644 --- a/config/config.go +++ b/config/config.go @@ -47,3 +47,4 @@ func (c *Config) GetBlockBuildFrequency() time.Duration { return time. func (c *Config) GetProcessingBuildSkip() int { return 16 } func (c *Config) GetMinimumCertificateBroadcastNumerator() uint64 { return 85 } // out of 100 (more weight == more fees) // @todo func (c *Config) GetBeneficiary() codec.Address { return codec.EmptyAddress } +func (c *Config) GetAnchorURL() string { return "" } diff --git a/examples/morpheusvm/config/config.go b/examples/morpheusvm/config/config.go index 53e9e38bc9..a3b743f59d 100644 --- a/examples/morpheusvm/config/config.go +++ b/examples/morpheusvm/config/config.go @@ -31,6 +31,9 @@ const ( type Config struct { *config.Config + // Anchor + AnchorURL string `json:"anchorUrl"` + // Building ChunkBuildFrequency int64 `json:"chunkBuildFrequency"` // in milliseconds TargetChunkBuildDuration int64 `json:"targetChunkBuildDuration"` // in milliseconds @@ -115,6 +118,7 @@ func (c *Config) setDefault() { c.AuthGossipBacklog = c.Config.GetAuthGossipBacklog() c.ChunkStorageCores = c.Config.GetChunkStorageCores() c.ChunkStorageBacklog = c.Config.GetChunkStorageBacklog() + c.AnchorURL = c.Config.GetAnchorURL() } func (c *Config) GetLogLevel() logging.Level { return c.LogLevel } @@ -197,3 +201,6 @@ func (c *Config) GetChunkStorageCores() int { func (c *Config) GetChunkStorageBacklog() int { return c.ChunkStorageBacklog } +func (c *Config) GetAnchorURL() string { + return "" +} diff --git a/rpc/dependencies.go b/rpc/dependencies.go index a957a13a52..edfce342a2 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -12,7 +12,6 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/chain" - "github.com/ava-labs/hypersdk/codec" ) type VM interface { @@ -43,6 +42,4 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() - - HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error } diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index a712d8cf13..97a556a4a8 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -89,38 +89,6 @@ func (j *JSONRPCServer) SubmitTx( return j.vm.Submit(ctx, false, []*chain.Transaction{tx})[0] } -// TODO: make it permissioned -type SubmitAnchorChunkArgs struct { - Anchor chain.Anchor `json:"anchor"` - Slot int64 `json:"slot"` - Txs []byte `json:"txs"` // raw tx - PriorityFeeReceiverAddr codec.Address `json:"priorityFeeReceiverAddr"` -} - -type SubmitAnchorChunkReply struct { - Success bool `json:"success"` -} - -func (j *JSONRPCServer) SubmitAnchorChunk( - req *http.Request, - args *SubmitAnchorChunkArgs, - reply *SubmitAnchorChunkReply, -) error { - actionRegistry, authRegistery := j.vm.Registry() - _, txs, err := chain.UnmarshalTxs(args.Txs, len(args.Txs), actionRegistry, authRegistery) - if err != nil { - return err - } - - err = j.vm.HandleAnchorChunk(context.TODO(), &args.Anchor, args.Slot, txs, args.PriorityFeeReceiverAddr) - if err == nil { - reply.Success = true - return nil - } - - return err -} - type LastAcceptedReply struct { Height uint64 `json:"height"` BlockID ids.ID `json:"blockId"` diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index 6008a5a8fa..2fbd9f255b 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -1449,12 +1449,7 @@ func (c *ChunkManager) HandleTx(ctx context.Context, tx *chain.Transaction) { c.sendTxGossip(ctx, gossipable) } -func (c *ChunkManager) SignAnchorChunkHeader(ctx context.Context, header *chain.Chunk) ([]byte, error) { - digest, err := header.Digest() - if err != nil { - return nil, err - } - +func (c *ChunkManager) SignAnchorDigest(ctx context.Context, digest []byte) ([]byte, error) { now := time.Now().UnixMilli() - consts.ClockSkewAllowance r := c.vm.Rules(now) wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) diff --git a/vm/dependencies.go b/vm/dependencies.go index 246e55eb90..e8f624b65c 100644 --- a/vm/dependencies.go +++ b/vm/dependencies.go @@ -50,6 +50,7 @@ type Config interface { GetBlockBuildFrequency() time.Duration GetProcessingBuildSkip() int GetMinimumCertificateBroadcastNumerator() uint64 + GetAnchorURL() string } type Genesis interface { diff --git a/vm/resolutions.go b/vm/resolutions.go index 8e0a8a2760..d870c89064 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -588,6 +588,10 @@ func (vm *VM) Engine() *chain.Engine { return vm.engine } +func (vm *VM) SignAnchorDigest(ctx context.Context, digest []byte) ([]byte, error) { + return vm.cm.SignAnchorDigest(ctx, digest) +} + func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { return vm.cm.HandleAnchorChunk(ctx, anchor, slot, txs, priorityFeeReceiverAddr) } diff --git a/vm/vm.go b/vm/vm.go index b3dffd6322..ba2a1a4ff2 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -28,6 +28,7 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/avalanchego/version" + "github.com/ava-labs/hypersdk/anchor" hcache "github.com/ava-labs/hypersdk/cache" "github.com/ava-labs/hypersdk/filedb" "github.com/ava-labs/hypersdk/pebble" @@ -79,6 +80,7 @@ type VM struct { // Handle chunks cm *ChunkManager + anchor *anchor.Anchor engine *chain.Engine // track all issuedTxs (to prevent wasting bandwidth) @@ -211,6 +213,9 @@ func (vm *VM) Initialize( vm.networkManager.SetHandler(chunkHandler, vm.cm) go vm.cm.Run(chunkSender) + anchorUrl := vm.config.GetAnchorURL() + vm.anchor = anchor.NewAnchor(anchorUrl, vm) + // Setup tracer vm.tracer, err = htrace.New(vm.config.GetTraceConfig()) if err != nil { From a778926cad1ab9034d694ed5a89d503acc1680ac Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 15 Aug 2024 17:04:06 +0900 Subject: [PATCH 06/18] remove checks for anchor chunk --- chain/processor.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/chain/processor.go b/chain/processor.go index 0ccc8b3e09..cd461716a9 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -317,21 +317,8 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { p.results[chunkIndex][txIndex] = &Result{Valid: false} return nil, nil } - } else { // from Anchor, which we allow - if chunk.Anchor.BlockType == AnchorRoB { - parition, err := p.vm.AddressPartitionByNamespace(ctx, txEpoch, *epochHeight, tx.Action.NMTNamespace(), tx.Partition()) - if err != nil { - p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) - p.results[chunkIndex][txIndex] = &Result{Valid: false} - return nil, nil - } - if parition != chunk.Producer { - p.vm.Logger().Warn("tx in wrong partition", zap.Stringer("txID", tx.ID())) - p.results[chunkIndex][txIndex] = &Result{Valid: false} - return nil, nil - } - } } + // TODO: some checks are needed to ensure that the Anchor chunk is issued by a correct validator // Check that transaction isn't frozen (can avoid state lookups) // From 5533082c67eca9b22778153e3859e1ab9b842ece Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Thu, 15 Aug 2024 21:44:46 +0900 Subject: [PATCH 07/18] anchor chunk flow --- anchor/anchor.go | 26 +++++++++++++++--- rpc/dependencies.go | 3 +++ rpc/jsonrpc_client.go | 15 +++++++++++ rpc/jsonrpc_server.go | 30 +++++++++++++++++++++ vm/chunk_manager.go | 61 +++++++++++++++++++++++++++++++++++++++++++ vm/resolutions.go | 5 ++++ 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/anchor/anchor.go b/anchor/anchor.go index c65869b43a..2de665b37b 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,8 +1,17 @@ package anchor +import ( + "sync" + + "github.com/ava-labs/hypersdk/chain" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/bls" +) + type Anchor struct { - vm VM - Url string `json:"url"` + vm VM + Url string `json:"url"` + UrlL sync.Mutex } func NewAnchor(url string, vm VM) *Anchor { @@ -12,10 +21,19 @@ func NewAnchor(url string, vm VM) *Anchor { } } -func (a *Anchor) RequestAnchorDigest() { +// only the Anchor provide the signature signed by the same key the validator has will be accepted +func (a *Anchor) Replace(url string) { + a.UrlL.Lock() + defer a.UrlL.Unlock() + a.Url = url } -func (a *Anchor) RequestAnchorChunk() { +func (a *Anchor) RequestAnchorDigest() ([]byte, error) { + return nil, nil +} +// returns Slot, Txs, FeeReceiver, error +func (a *Anchor) RequestAnchorChunk(sig *bls.Signature) (*chain.Anchor, int64, []*chain.Transaction, codec.Address, error) { + return nil, 0, nil, codec.EmptyAddress, nil } diff --git a/rpc/dependencies.go b/rpc/dependencies.go index edfce342a2..1540d9d661 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/trace" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/chain" ) @@ -42,4 +43,6 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() + + Anchor() *anchor.Anchor } diff --git a/rpc/jsonrpc_client.go b/rpc/jsonrpc_client.go index f3990ebf2d..e3536a9f61 100644 --- a/rpc/jsonrpc_client.go +++ b/rpc/jsonrpc_client.go @@ -354,3 +354,18 @@ func (cli *JSONRPCClient) GenerateAggregateWarpSignature( } return message, weight, signatureWeight, nil } + +func (cli *JSONRPCClient) ReplaceAnchor(ctx context.Context, url string, pubkey *bls.PublicKey, sig *bls.Signature) (bool, error) { + resp := new(ReplaceAnchorReply) + err := cli.requester.SendRequest( + ctx, + "replaceAnchor", + &ReplaceAnchorArgs{ + Url: url, + Pubkey: pubkey, + Signature: sig, + }, + resp, + ) + return resp.Success, err +} diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index 97a556a4a8..8c98953c3e 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -204,3 +204,33 @@ func (j *JSONRPCServer) GetWarpSignatures( reply.Signatures = validSignatures return nil } + +type ReplaceAnchorArgs struct { + Url string `json:"url"` + Signature *bls.Signature `json:"signature"` + Pubkey *bls.PublicKey `json:"pubkey"` +} + +type ReplaceAnchorReply struct { + Success bool `json:"success"` +} + +func (j *JSONRPCServer) ReplaceAnchor( + req *http.Request, + args *ReplaceAnchorArgs, + reply *ReplaceAnchorReply, +) error { + msg := []byte(args.Url) + verified := bls.Verify(args.Pubkey, args.Signature, msg) + if !verified { + j.vm.Logger().Error("unable to veirfy anchor replacement sig") + return fmt.Errorf("unable to verify the signature against the pubkey and msg") + } + + bindAnchor := j.vm.Anchor() + bindAnchor.Replace(args.Url) + + reply.Success = true + + return nil +} diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index 2fbd9f255b..0e25cabf81 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -845,6 +845,67 @@ func (c *ChunkManager) Run(appSender common.AppSender) { c.auth.Run() return nil }) + g.Go(func() error { + t := time.NewTicker(c.vm.config.GetChunkBuildFrequency()) + defer t.Stop() + for { + select { + case <-t.C: + if !c.vm.isReady() { + c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") + continue + } + if skipChunks { + continue + } + + // Attempt to build a chunk + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := c.vm.Rules(now) + anchorCli := c.vm.Anchor() + digest, err := anchorCli.RequestAnchorDigest() + if err != nil { + c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) + continue + } + wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + if err != nil { + c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) + continue + } + sigBytes, err := c.vm.Sign(wm) + if err != nil { + c.vm.Logger().Error("unable to sign message", zap.Error(err)) + continue + } + sig, err := bls.SignatureFromBytes(sigBytes) + if err != nil { + c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) + continue + } + + meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) + if err != nil { + c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) + continue + } + + chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) + if err != nil { + c.vm.Logger().Error("unable to build chunk", zap.Error(err)) + continue + } + c.auth.Add(chunk) // this will be a no-op because we are the producer + c.PushChunk(context.TODO(), chunk) + case <-c.vm.stop: + // If engine taking too long to process message, Shutdown will not + // be called. + c.vm.Logger().Info("stopping chunk manager") + return nil + } + } + }) + g.Go(func() error { t := time.NewTicker(c.vm.config.GetChunkBuildFrequency()) defer t.Stop() diff --git a/vm/resolutions.go b/vm/resolutions.go index d870c89064..4c26651867 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -20,6 +20,7 @@ import ( "go.uber.org/zap" + "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/executor" @@ -596,6 +597,10 @@ func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot return vm.cm.HandleAnchorChunk(ctx, anchor, slot, txs, priorityFeeReceiverAddr) } +func (vm *VM) Anchor() *anchor.Anchor { + return vm.anchor +} + func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { return vm.issuedTxs.Has(tx) } From 4487c7cff58cde589e32375e7c972aec47f0f468 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Fri, 16 Aug 2024 03:26:16 +0900 Subject: [PATCH 08/18] anchor register msg & utility methods --- anchor/anchor.go | 117 +++++++++++++++++++++++++++++++++++++++++- anchor/anchor_test.go | 94 +++++++++++++++++++++++++++++++++ vm/chunk_manager.go | 16 ++++++ 3 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 anchor/anchor_test.go diff --git a/anchor/anchor.go b/anchor/anchor.go index 2de665b37b..e621f57896 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,13 +1,128 @@ package anchor import ( + "fmt" "sync" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" - "github.com/ava-labs/hypersdk/crypto/bls" + "github.com/ava-labs/hypersdk/consts" ) +type AnchorRegisterMsg struct { + Slot int64 // used to calcualte height and aggregate key + + Url string + + Issuer *bls.PublicKey `json:"issuer"` + IssuerSig *bls.Signature `json:"issuerSig"` + + Signers set.Bits `json:"signers"` + Signature *bls.Signature `json:"signature"` +} + +func (a *AnchorRegisterMsg) ID() ids.ID { + return ids.ID([]byte(a.Url)) +} + +func (a *AnchorRegisterMsg) Expiry() int64 { + return a.Slot +} + +func (a *AnchorRegisterMsg) Size() int { + signers := a.Signers.Bytes() + return consts.Int64Len + codec.BytesLen([]byte(a.Url)) + bls.PublicKeyLen + bls.SignatureLen + codec.BytesLen(signers) + bls.SignatureLen +} + +func (a *AnchorRegisterMsg) Digest() ([]byte, error) { + size := consts.Int64Len + codec.BytesLen([]byte(a.Url)) + bls.PublicKeyLen + p := codec.NewWriter(size, consts.NetworkSizeLimit) + p.PackInt64(a.Slot) + p.PackBytes([]byte(a.Url)) + p.PackFixedBytes(bls.PublicKeyToCompressedBytes(a.Issuer)) + + return p.Bytes(), p.Err() +} + +func (a *AnchorRegisterMsg) VerifySignature(networkID uint32, chainID ids.ID, aggrPubKey *bls.PublicKey) bool { + digest, err := a.Digest() + if err != nil { + return false + } + // TODO: don't use warp message for this (nice to have chainID protection)? + msg, err := warp.NewUnsignedMessage(networkID, chainID, digest) + if err != nil { + return false + } + return bls.Verify(aggrPubKey, a.Signature, msg.Bytes()) +} + +func (a *AnchorRegisterMsg) Marshal() ([]byte, error) { + p := codec.NewWriter(a.Size(), consts.NetworkSizeLimit) + + p.PackInt64(a.Slot) + p.PackBytes([]byte(a.Url)) + p.PackFixedBytes(bls.PublicKeyToCompressedBytes(a.Issuer)) + p.PackFixedBytes(bls.SignatureToBytes(a.IssuerSig)) + + p.PackBytes(a.Signers.Bytes()) + p.PackFixedBytes(bls.SignatureToBytes(a.Signature)) + + return p.Bytes(), p.Err() +} + +func UnmarshalAnchorRegisterMsg(raw []byte) (*AnchorRegisterMsg, error) { + var ( + p = codec.NewReader(raw, consts.NetworkSizeLimit) + a AnchorRegisterMsg + ) + + a.Slot = p.UnpackInt64(false) + var urlBytes []byte + p.UnpackBytes(-1, false, &urlBytes) + a.Url = string(urlBytes) + + issuerBytes := make([]byte, bls.PublicKeyLen) + p.UnpackFixedBytes(bls.PublicKeyLen, &issuerBytes) + issuer, err := bls.PublicKeyFromCompressedBytes(issuerBytes) + if err != nil { + return nil, err + } + a.Issuer = issuer + + issuerSigBytes := make([]byte, bls.SignatureLen) + p.UnpackFixedBytes(bls.SignatureLen, &issuerSigBytes) + issuerSig, err := bls.SignatureFromBytes(issuerSigBytes) + if err != nil { + return nil, err + } + a.IssuerSig = issuerSig + + var signersBytes []byte + p.UnpackBytes(32, true, &signersBytes) + a.Signers = set.BitsFromBytes(signersBytes) + if len(signersBytes) != len(a.Signers.Bytes()) { + return nil, fmt.Errorf("invalid anchor register msg: signers not minimal") + } + sig := make([]byte, bls.SignatureLen) + p.UnpackFixedBytes(bls.SignatureLen, &sig) + + signature, err := bls.SignatureFromBytes(sig) + if err != nil { + return nil, err + } + a.Signature = signature + + if !p.Empty() { + return nil, fmt.Errorf("invalid anchor register msg: remaining=%d", len(raw)-p.Offset()) + } + return &a, p.Err() +} + type Anchor struct { vm VM Url string `json:"url"` diff --git a/anchor/anchor_test.go b/anchor/anchor_test.go new file mode 100644 index 0000000000..1d23e2cf3c --- /dev/null +++ b/anchor/anchor_test.go @@ -0,0 +1,94 @@ +package anchor + +import ( + "testing" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/hypersdk/crypto/bls" + "github.com/stretchr/testify/require" +) + +func TestAnchorRegisterMsgCanMarshal(t *testing.T) { + key, err := bls.GeneratePrivateKey() + require.NoError(t, err) + pubkey := bls.PublicFromPrivateKey(key) + + cert := AnchorRegisterMsg{ + Slot: 1, + Url: "http://localhost:9090", + Issuer: pubkey, + } + + digest, err := cert.Digest() + require.NoError(t, err) + + sig := bls.Sign(digest, key) + cert.IssuerSig = sig + + cert.Signers = set.NewBits() + cert.Signers.Add(0) + sigs := make([]*bls.Signature, 0) + sigs = append(sigs, cert.IssuerSig) + + cert.Signature, err = bls.AggregateSignatures(sigs) + require.NoError(t, err) + + certBytes, err := cert.Marshal() + require.NoError(t, err) + + require.Equal(t, cert.Size(), len(certBytes)) + + recovered, err := UnmarshalAnchorRegisterMsg(certBytes) + require.NoError(t, err) + + _, err = recovered.Marshal() + require.NoError(t, err) + + require.Equal(t, cert.Slot, recovered.Slot) + require.Equal(t, cert.Url, recovered.Url) + require.Equal(t, cert.Issuer, recovered.Issuer) + require.Equal(t, cert.IssuerSig, recovered.IssuerSig) + require.Equal(t, cert.Signers, recovered.Signers) + require.Equal(t, cert.Signature, recovered.Signature) +} + +func TestAnchorRegisterMsgCanBeVerified(t *testing.T) { + key, err := bls.GeneratePrivateKey() + require.NoError(t, err) + pubkey := bls.PublicFromPrivateKey(key) + + cert := AnchorRegisterMsg{ + Slot: 1, + Url: "http://localhost:9090", + Issuer: pubkey, + } + + digest, err := cert.Digest() + require.NoError(t, err) + + networkID := 200 + chainID := ids.Empty + + wm, err := warp.NewUnsignedMessage(uint32(networkID), chainID, digest) + require.NoError(t, err) + + sig := bls.Sign(wm.Bytes(), key) + cert.IssuerSig = sig + + pubkeys := make([]*bls.PublicKey, 0) + pubkeys = append(pubkeys, pubkey) + aggrPubkey, err := bls.AggregatePublicKeys(pubkeys) + require.NoError(t, err) + + sigs := make([]*bls.Signature, 0) + sigs = append(sigs, sig) + aggrSig, err := bls.AggregateSignatures(sigs) + require.NoError(t, err) + + cert.Signature = aggrSig + + verified := cert.VerifySignature(uint32(networkID), chainID, aggrPubkey) + require.True(t, verified) +} diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index 0e25cabf81..cfffb830cc 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -18,6 +18,7 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/cache" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" @@ -39,6 +40,9 @@ const ( chunkCertifiedMsg uint8 = 0x3 // chunk + chunk certificate txMsg uint8 = 0x4 + // anchor registeration message, anchorInfo + sig + pubkey + anchorRegisterMsg uint8 = 0xf0 + chunkReq uint8 = 0x0 // TODO: add support for filtered chunk requests @@ -345,6 +349,18 @@ func (c *ChunkManager) Disconnected(_ context.Context, nodeID ids.NodeID) error return nil } +func (c *ChunkManager) PushAnchorRegisterMsg(ctx context.Context, nodeID ids.NodeID, cert *anchor.AnchorRegisterMsg) { + msg := make([]byte, 1+cert.Size()) + msg[0] = anchorRegisterMsg + certBytes, err := cert.Marshal() + if err != nil { + c.vm.Logger().Warn("failed to marshal anchor registeration msg", zap.Error(err)) + return + } + copy(msg[1:], certBytes) + c.appSender.SendAppGossip(ctx, common.SendConfig{NodeIDs: set.Of(nodeID)}, msg) // skips validators we aren't connected to +} + func (c *ChunkManager) PushSignature(ctx context.Context, nodeID ids.NodeID, sig *chain.ChunkSignature) { msg := make([]byte, 1+sig.Size()) msg[0] = chunkSignatureMsg From 90b76939e73a36564b218cc30dbe6cf75d040702 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Fri, 16 Aug 2024 19:57:58 +0900 Subject: [PATCH 09/18] register anchors by sending chunks --- anchor/anchor.go | 133 +++++++-------------------- anchor/anchor_test.go | 93 ------------------- chain/block.go | 5 +- chain/chunk.go | 84 +++++++++++++++++ chain/engine.go | 13 ++- chain/processor.go | 19 +++- config/config.go | 1 - examples/morpheusvm/config/config.go | 7 -- rpc/dependencies.go | 4 +- rpc/jsonrpc_client.go | 6 +- rpc/jsonrpc_server.go | 24 +++-- vm/chunk_manager.go | 104 +++++++++++---------- vm/dependencies.go | 1 - vm/resolutions.go | 12 ++- vm/vm.go | 10 +- 15 files changed, 234 insertions(+), 282 deletions(-) diff --git a/anchor/anchor.go b/anchor/anchor.go index e621f57896..48517571f4 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,132 +1,59 @@ package anchor import ( - "fmt" "sync" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" - "github.com/ava-labs/hypersdk/consts" ) -type AnchorRegisterMsg struct { - Slot int64 // used to calcualte height and aggregate key - - Url string - - Issuer *bls.PublicKey `json:"issuer"` - IssuerSig *bls.Signature `json:"issuerSig"` - - Signers set.Bits `json:"signers"` - Signature *bls.Signature `json:"signature"` -} - -func (a *AnchorRegisterMsg) ID() ids.ID { - return ids.ID([]byte(a.Url)) -} - -func (a *AnchorRegisterMsg) Expiry() int64 { - return a.Slot +type AnchorRegistry struct { + clients map[ids.ID]*Anchor + clientsL sync.Mutex + vm VM } -func (a *AnchorRegisterMsg) Size() int { - signers := a.Signers.Bytes() - return consts.Int64Len + codec.BytesLen([]byte(a.Url)) + bls.PublicKeyLen + bls.SignatureLen + codec.BytesLen(signers) + bls.SignatureLen -} - -func (a *AnchorRegisterMsg) Digest() ([]byte, error) { - size := consts.Int64Len + codec.BytesLen([]byte(a.Url)) + bls.PublicKeyLen - p := codec.NewWriter(size, consts.NetworkSizeLimit) - p.PackInt64(a.Slot) - p.PackBytes([]byte(a.Url)) - p.PackFixedBytes(bls.PublicKeyToCompressedBytes(a.Issuer)) - - return p.Bytes(), p.Err() +func NewAnchorRegistry(vm VM) *AnchorRegistry { + return &AnchorRegistry{ + vm: vm, + } } -func (a *AnchorRegisterMsg) VerifySignature(networkID uint32, chainID ids.ID, aggrPubKey *bls.PublicKey) bool { - digest, err := a.Digest() - if err != nil { - return false +func (r *AnchorRegistry) Register(url string, namespace string) error { + anchorCli := &Anchor{ + Url: url, + vm: r.vm, + Namespace: namespace, } - // TODO: don't use warp message for this (nice to have chainID protection)? - msg, err := warp.NewUnsignedMessage(networkID, chainID, digest) + clientID, err := anchorCli.ID() if err != nil { - return false + return err } - return bls.Verify(aggrPubKey, a.Signature, msg.Bytes()) -} - -func (a *AnchorRegisterMsg) Marshal() ([]byte, error) { - p := codec.NewWriter(a.Size(), consts.NetworkSizeLimit) - p.PackInt64(a.Slot) - p.PackBytes([]byte(a.Url)) - p.PackFixedBytes(bls.PublicKeyToCompressedBytes(a.Issuer)) - p.PackFixedBytes(bls.SignatureToBytes(a.IssuerSig)) - - p.PackBytes(a.Signers.Bytes()) - p.PackFixedBytes(bls.SignatureToBytes(a.Signature)) - - return p.Bytes(), p.Err() + r.clients[clientID] = anchorCli + return nil } -func UnmarshalAnchorRegisterMsg(raw []byte) (*AnchorRegisterMsg, error) { - var ( - p = codec.NewReader(raw, consts.NetworkSizeLimit) - a AnchorRegisterMsg - ) - - a.Slot = p.UnpackInt64(false) - var urlBytes []byte - p.UnpackBytes(-1, false, &urlBytes) - a.Url = string(urlBytes) - - issuerBytes := make([]byte, bls.PublicKeyLen) - p.UnpackFixedBytes(bls.PublicKeyLen, &issuerBytes) - issuer, err := bls.PublicKeyFromCompressedBytes(issuerBytes) - if err != nil { - return nil, err - } - a.Issuer = issuer - - issuerSigBytes := make([]byte, bls.SignatureLen) - p.UnpackFixedBytes(bls.SignatureLen, &issuerSigBytes) - issuerSig, err := bls.SignatureFromBytes(issuerSigBytes) - if err != nil { - return nil, err - } - a.IssuerSig = issuerSig - - var signersBytes []byte - p.UnpackBytes(32, true, &signersBytes) - a.Signers = set.BitsFromBytes(signersBytes) - if len(signersBytes) != len(a.Signers.Bytes()) { - return nil, fmt.Errorf("invalid anchor register msg: signers not minimal") - } - sig := make([]byte, bls.SignatureLen) - p.UnpackFixedBytes(bls.SignatureLen, &sig) +func (r *AnchorRegistry) Remove(url string) error { + r.clientsL.Lock() + defer r.clientsL.Unlock() - signature, err := bls.SignatureFromBytes(sig) + cilentID, err := ids.ToID([]byte(url)) if err != nil { - return nil, err + return err } - a.Signature = signature - if !p.Empty() { - return nil, fmt.Errorf("invalid anchor register msg: remaining=%d", len(raw)-p.Offset()) - } - return &a, p.Err() + delete(r.clients, cilentID) + return nil } type Anchor struct { - vm VM - Url string `json:"url"` - UrlL sync.Mutex + vm VM + Url string `json:"url"` + UrlL sync.Mutex + Namespace string `json:"namespace"` } func NewAnchor(url string, vm VM) *Anchor { @@ -136,6 +63,10 @@ func NewAnchor(url string, vm VM) *Anchor { } } +func (a *Anchor) ID() (ids.ID, error) { + return ids.ToID([]byte(a.Url)) +} + // only the Anchor provide the signature signed by the same key the validator has will be accepted func (a *Anchor) Replace(url string) { a.UrlL.Lock() diff --git a/anchor/anchor_test.go b/anchor/anchor_test.go index 1d23e2cf3c..44d3ed28f5 100644 --- a/anchor/anchor_test.go +++ b/anchor/anchor_test.go @@ -1,94 +1 @@ package anchor - -import ( - "testing" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/hypersdk/crypto/bls" - "github.com/stretchr/testify/require" -) - -func TestAnchorRegisterMsgCanMarshal(t *testing.T) { - key, err := bls.GeneratePrivateKey() - require.NoError(t, err) - pubkey := bls.PublicFromPrivateKey(key) - - cert := AnchorRegisterMsg{ - Slot: 1, - Url: "http://localhost:9090", - Issuer: pubkey, - } - - digest, err := cert.Digest() - require.NoError(t, err) - - sig := bls.Sign(digest, key) - cert.IssuerSig = sig - - cert.Signers = set.NewBits() - cert.Signers.Add(0) - sigs := make([]*bls.Signature, 0) - sigs = append(sigs, cert.IssuerSig) - - cert.Signature, err = bls.AggregateSignatures(sigs) - require.NoError(t, err) - - certBytes, err := cert.Marshal() - require.NoError(t, err) - - require.Equal(t, cert.Size(), len(certBytes)) - - recovered, err := UnmarshalAnchorRegisterMsg(certBytes) - require.NoError(t, err) - - _, err = recovered.Marshal() - require.NoError(t, err) - - require.Equal(t, cert.Slot, recovered.Slot) - require.Equal(t, cert.Url, recovered.Url) - require.Equal(t, cert.Issuer, recovered.Issuer) - require.Equal(t, cert.IssuerSig, recovered.IssuerSig) - require.Equal(t, cert.Signers, recovered.Signers) - require.Equal(t, cert.Signature, recovered.Signature) -} - -func TestAnchorRegisterMsgCanBeVerified(t *testing.T) { - key, err := bls.GeneratePrivateKey() - require.NoError(t, err) - pubkey := bls.PublicFromPrivateKey(key) - - cert := AnchorRegisterMsg{ - Slot: 1, - Url: "http://localhost:9090", - Issuer: pubkey, - } - - digest, err := cert.Digest() - require.NoError(t, err) - - networkID := 200 - chainID := ids.Empty - - wm, err := warp.NewUnsignedMessage(uint32(networkID), chainID, digest) - require.NoError(t, err) - - sig := bls.Sign(wm.Bytes(), key) - cert.IssuerSig = sig - - pubkeys := make([]*bls.PublicKey, 0) - pubkeys = append(pubkeys, pubkey) - aggrPubkey, err := bls.AggregatePublicKeys(pubkeys) - require.NoError(t, err) - - sigs := make([]*bls.Signature, 0) - sigs = append(sigs, sig) - aggrSig, err := bls.AggregateSignatures(sigs) - require.NoError(t, err) - - cert.Signature = aggrSig - - verified := cert.VerifySignature(uint32(networkID), chainID, aggrPubkey) - require.True(t, verified) -} diff --git a/chain/block.go b/chain/block.go index ee4012aa6b..8dd1063e6b 100644 --- a/chain/block.go +++ b/chain/block.go @@ -50,6 +50,8 @@ type StatefulBlock struct { ExecutedChunks []ids.ID `json:"executedChunks"` Checksum ids.ID `json:"checksum"` + AnchorRegistrations []*Anchor `json:"anchorRegistrations"` + built bool } @@ -501,11 +503,12 @@ func (b *StatelessBlock) Accept(ctx context.Context) error { // Prune async results (if any) var filteredChunks []*FilteredChunk if b.execHeight != nil { - _, fc, err := b.vm.Engine().PruneResults(ctx, *b.execHeight) + _, fc, anchors, err := b.vm.Engine().PruneResults(ctx, *b.execHeight) if err != nil { return fmt.Errorf("%w: cannot prune results", err) } filteredChunks = fc + b.AnchorRegistrations = anchors // new registered anchors is at current block height - 3 } // Notify the VM that the block has been accepted diff --git a/chain/chunk.go b/chain/chunk.go index 30ffd450e2..5cc8ba1fe4 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -21,11 +21,14 @@ const chunkPrealloc = 16_384 const ( AnchorToB = iota AnchorRoB + AnchorRegister ) type Anchor struct { BlockType int `json:"blockType"` // use to determine if it is TOB or ROB Namespace string `json:"namespace"` + Url string `json:"url"` + Creation bool `json:"string"` // with this flag, we can include zero tx in a chunk for a anchor registeration } type Chunk struct { @@ -47,6 +50,87 @@ type Chunk struct { authCounts map[uint8]int } +func BuildAnchorRegisterChunk(ctx context.Context, vm VM, anchor *Anchor) (*Chunk, error) { + if !anchor.Creation { + return nil, fmt.Errorf("not a anchor registeration chunk") + } + + start := time.Now() + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := vm.Rules(now) + c := &Chunk{ + Slot: utils.UnixRDeci(now, r.GetValidityWindow()), // chunk validity window is 9 seconds @todo + } + epoch := utils.Epoch(now, r.GetEpochDuration()) + + // Don't build chunk if no P-Chain height for epoch + timestamp, heights, err := vm.Engine().GetEpochHeights(ctx, []uint64{epoch}) + if err != nil { + return nil, err + } + executedEpoch := utils.Epoch(timestamp, r.GetEpochDuration()) // epoch duration set to 10 seconds. + if executedEpoch+2 < epoch { // only require + 2 because we don't care about epoch + 1 like in verification. + return nil, fmt.Errorf("executed epoch (%d) is too far behind (%d) to verify chunk", executedEpoch, epoch) + } + if heights[0] == nil { + return nil, fmt.Errorf("no P-Chain height for epoch %d", epoch) + } + + // Check if validator + // + // If not a validator in this epoch height, don't build. + amValidator, err := vm.IsValidator(ctx, *heights[0], vm.NodeID()) + if err != nil { + return nil, err + } + if !amValidator { + return nil, ErrNotAValidator + } + + // Setup chunk + c.PriorityFeeReceiverAddr = codec.BlackholeAddress + c.Producer = vm.NodeID() + c.Beneficiary = vm.Beneficiary() + c.Signer = vm.Signer() + + // Sign chunk + digest, err := c.Digest() + if err != nil { + return nil, err + } + wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + if err != nil { + return nil, err + } + sig, err := vm.Sign(wm) + if err != nil { + return nil, err + } + c.Signature, err = bls.SignatureFromBytes(sig) + if err != nil { + return nil, err + } + bytes, err := c.Marshal() + if err != nil { + return nil, err + } + c.id = utils.ToID(bytes) + + vm.Logger().Info( + "built registering chunk with signature from anchor msg", + zap.Stringer("nodeID", vm.NodeID()), + zap.Uint32("networkID", r.NetworkID()), + zap.Stringer("chainID", r.ChainID()), + zap.Int64("slot", c.Slot), + zap.Uint64("epoch", epoch), + zap.Int("txs", len(c.Txs)), + zap.String("signer", hex.EncodeToString(bls.PublicKeyToCompressedBytes(c.Signer))), + zap.String("signature", hex.EncodeToString(bls.SignatureToBytes(c.Signature))), + zap.Duration("t", time.Since(start)), + ) + return c, nil +} + func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *Anchor, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance diff --git a/chain/engine.go b/chain/engine.go index 65420a4635..6bdf251af2 100644 --- a/chain/engine.go +++ b/chain/engine.go @@ -13,9 +13,9 @@ import ( "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/maybe" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/hypersdk/vilmo" "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/utils" + "github.com/ava-labs/hypersdk/vilmo" "go.uber.org/zap" ) @@ -31,6 +31,8 @@ type output struct { chunks []*FilteredChunk checksum ids.ID + + anchors []*Anchor } // Engine is in charge of orchestrating the execution of @@ -120,7 +122,7 @@ func (e *Engine) processJob(batch *vilmo.Batch, job *engineJob) error { p.Add(ctx, len(chunks), chunk) chunks = append(chunks, chunk) } - txSet, ts, chunkResults, err := p.Wait() + txSet, ts, chunkResults, newAnchors, err := p.Wait() if err != nil { e.vm.Logger().Fatal("chunk processing failed", zap.Error(err)) // does not actually panic return err @@ -311,6 +313,7 @@ func (e *Engine) processJob(batch *vilmo.Batch, job *engineJob) error { chunks: filteredChunks, checksum: checksum, + anchors: newAnchors, } e.largestOutput = &job.blk.StatefulBlock.Height e.outputsLock.Unlock() @@ -406,19 +409,19 @@ func (e *Engine) Results(height uint64) ([]ids.ID /* Executed Chunks */, ids.ID return nil, ids.Empty, fmt.Errorf("%w: results not found for %d", errors.New("not found"), height) } -func (e *Engine) PruneResults(ctx context.Context, height uint64) ([][]*Result, []*FilteredChunk, error) { +func (e *Engine) PruneResults(ctx context.Context, height uint64) ([][]*Result, []*FilteredChunk, []*Anchor, error) { e.outputsLock.Lock() defer e.outputsLock.Unlock() output, ok := e.outputs[height] if !ok { - return nil, nil, fmt.Errorf("%w: %d", errors.New("not outputs found at height"), height) + return nil, nil, nil, fmt.Errorf("%w: %d", errors.New("not outputs found at height"), height) } delete(e.outputs, height) if e.largestOutput != nil && *e.largestOutput == height { e.largestOutput = nil } - return output.chunkResults, output.chunks, nil + return output.chunkResults, output.chunks, output.anchors, nil } func (e *Engine) ReadLatestState(ctx context.Context, keys []string) ([][]byte, []error) { diff --git a/chain/processor.go b/chain/processor.go index cd461716a9..af71c5547c 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -36,6 +36,7 @@ type Processor struct { txs map[ids.ID]*blockLoc results [][]*Result + anchors map[string]*Anchor // TODO: track frozen sponsors @@ -232,6 +233,11 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { return } p.acceptedNS[chunk.Anchor.Namespace] = struct{}{} + case AnchorRegister: + if _, exists := p.anchors[chunk.Anchor.Url]; !exists { + p.anchors[chunk.Anchor.Url] = chunk.Anchor + p.vm.Logger().Debug("adding new anchor to processor") + } } } @@ -335,19 +341,24 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { p.queueWait += time.Since(queueStart) } -func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, error) { +func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, []*Anchor, error) { p.vm.RecordWaitRepeat(p.repeatWait) p.vm.RecordWaitQueue(p.queueWait) p.vm.RecordWaitAuth(p.authWait) // we record once so we can see how much of a block was spend waiting (this is not the same as the total time) precheckStart := time.Now() if err := p.prechecker.Wait(); err != nil { - return nil, nil, nil, fmt.Errorf("%w: prechecker failed", err) + return nil, nil, nil, nil, fmt.Errorf("%w: prechecker failed", err) } p.vm.RecordWaitPrecheck(time.Since(precheckStart)) exectutorStart := time.Now() if err := p.executor.Wait(); err != nil { - return nil, nil, nil, fmt.Errorf("%w: processor failed", err) + return nil, nil, nil, nil, fmt.Errorf("%w: processor failed", err) + } + anchors := make([]*Anchor, 0, len(p.anchors)) + for _, anchor := range p.anchors { + anchors = append(anchors, anchor) } + p.vm.RecordWaitExec(time.Since(exectutorStart)) - return p.txs, p.ts, p.results, nil + return p.txs, p.ts, p.results, anchors, nil } diff --git a/config/config.go b/config/config.go index 17b50a4a04..0372d420cd 100644 --- a/config/config.go +++ b/config/config.go @@ -47,4 +47,3 @@ func (c *Config) GetBlockBuildFrequency() time.Duration { return time. func (c *Config) GetProcessingBuildSkip() int { return 16 } func (c *Config) GetMinimumCertificateBroadcastNumerator() uint64 { return 85 } // out of 100 (more weight == more fees) // @todo func (c *Config) GetBeneficiary() codec.Address { return codec.EmptyAddress } -func (c *Config) GetAnchorURL() string { return "" } diff --git a/examples/morpheusvm/config/config.go b/examples/morpheusvm/config/config.go index a3b743f59d..53e9e38bc9 100644 --- a/examples/morpheusvm/config/config.go +++ b/examples/morpheusvm/config/config.go @@ -31,9 +31,6 @@ const ( type Config struct { *config.Config - // Anchor - AnchorURL string `json:"anchorUrl"` - // Building ChunkBuildFrequency int64 `json:"chunkBuildFrequency"` // in milliseconds TargetChunkBuildDuration int64 `json:"targetChunkBuildDuration"` // in milliseconds @@ -118,7 +115,6 @@ func (c *Config) setDefault() { c.AuthGossipBacklog = c.Config.GetAuthGossipBacklog() c.ChunkStorageCores = c.Config.GetChunkStorageCores() c.ChunkStorageBacklog = c.Config.GetChunkStorageBacklog() - c.AnchorURL = c.Config.GetAnchorURL() } func (c *Config) GetLogLevel() logging.Level { return c.LogLevel } @@ -201,6 +197,3 @@ func (c *Config) GetChunkStorageCores() int { func (c *Config) GetChunkStorageBacklog() int { return c.ChunkStorageBacklog } -func (c *Config) GetAnchorURL() string { - return "" -} diff --git a/rpc/dependencies.go b/rpc/dependencies.go index 1540d9d661..2d7e67603d 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/trace" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/chain" ) @@ -43,6 +42,5 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() - - Anchor() *anchor.Anchor + PushAnchorRegisterMsg(ctx context.Context, anchor *chain.Anchor) } diff --git a/rpc/jsonrpc_client.go b/rpc/jsonrpc_client.go index e3536a9f61..6d852c4ef6 100644 --- a/rpc/jsonrpc_client.go +++ b/rpc/jsonrpc_client.go @@ -356,16 +356,16 @@ func (cli *JSONRPCClient) GenerateAggregateWarpSignature( } func (cli *JSONRPCClient) ReplaceAnchor(ctx context.Context, url string, pubkey *bls.PublicKey, sig *bls.Signature) (bool, error) { - resp := new(ReplaceAnchorReply) + resp := new(RegisterAnchorReply) err := cli.requester.SendRequest( ctx, "replaceAnchor", - &ReplaceAnchorArgs{ + &RegisterAnchorArgs{ Url: url, Pubkey: pubkey, Signature: sig, }, resp, ) - return resp.Success, err + return resp.Added, err } diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index 8c98953c3e..dfbb9c235b 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -205,20 +205,21 @@ func (j *JSONRPCServer) GetWarpSignatures( return nil } -type ReplaceAnchorArgs struct { +type RegisterAnchorArgs struct { Url string `json:"url"` + Namespace string `json:"namespace"` Signature *bls.Signature `json:"signature"` Pubkey *bls.PublicKey `json:"pubkey"` } -type ReplaceAnchorReply struct { - Success bool `json:"success"` +type RegisterAnchorReply struct { + Added bool `json:"success"` } -func (j *JSONRPCServer) ReplaceAnchor( +func (j *JSONRPCServer) RegisterAnchor( req *http.Request, - args *ReplaceAnchorArgs, - reply *ReplaceAnchorReply, + args *RegisterAnchorArgs, + reply *RegisterAnchorReply, ) error { msg := []byte(args.Url) verified := bls.Verify(args.Pubkey, args.Signature, msg) @@ -227,10 +228,15 @@ func (j *JSONRPCServer) ReplaceAnchor( return fmt.Errorf("unable to verify the signature against the pubkey and msg") } - bindAnchor := j.vm.Anchor() - bindAnchor.Replace(args.Url) + anchor := chain.Anchor{ + BlockType: -1, + Namespace: args.Namespace, + Url: args.Url, + Creation: true, + } - reply.Success = true + j.vm.PushAnchorRegisterMsg(context.Background(), &anchor) + reply.Added = true return nil } diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index cfffb830cc..97066aa12d 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -18,7 +18,6 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/cache" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" @@ -248,6 +247,8 @@ type ChunkManager struct { incomingChunks chan *chunkGossipWrapper incomingTxs chan *txGossipWrapper + incomingAnchorRegisterMsg chan *chain.Anchor + epochHeights *cache.FIFO[uint64, uint64] built *emap.EMap[*chunkWrapper] @@ -349,18 +350,6 @@ func (c *ChunkManager) Disconnected(_ context.Context, nodeID ids.NodeID) error return nil } -func (c *ChunkManager) PushAnchorRegisterMsg(ctx context.Context, nodeID ids.NodeID, cert *anchor.AnchorRegisterMsg) { - msg := make([]byte, 1+cert.Size()) - msg[0] = anchorRegisterMsg - certBytes, err := cert.Marshal() - if err != nil { - c.vm.Logger().Warn("failed to marshal anchor registeration msg", zap.Error(err)) - return - } - copy(msg[1:], certBytes) - c.appSender.SendAppGossip(ctx, common.SendConfig{NodeIDs: set.Of(nodeID)}, msg) // skips validators we aren't connected to -} - func (c *ChunkManager) PushSignature(ctx context.Context, nodeID ids.NodeID, sig *chain.ChunkSignature) { msg := make([]byte, 1+sig.Size()) msg[0] = chunkSignatureMsg @@ -866,53 +855,74 @@ func (c *ChunkManager) Run(appSender common.AppSender) { defer t.Stop() for { select { - case <-t.C: - if !c.vm.isReady() { - c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") - continue - } - if skipChunks { + case anchorRegisterMsg := <-c.incomingAnchorRegisterMsg: + if !anchorRegisterMsg.Creation { continue } - // Attempt to build a chunk - now := time.Now().UnixMilli() - consts.ClockSkewAllowance - r := c.vm.Rules(now) - anchorCli := c.vm.Anchor() - digest, err := anchorCli.RequestAnchorDigest() - if err != nil { - c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) - continue - } - wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) - if err != nil { - c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) - continue - } - sigBytes, err := c.vm.Sign(wm) - if err != nil { - c.vm.Logger().Error("unable to sign message", zap.Error(err)) + if !c.vm.isReady() { + c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") continue } - sig, err := bls.SignatureFromBytes(sigBytes) - if err != nil { - c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) + if skipChunks { continue } - meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) + chunk, err := chain.BuildAnchorRegisterChunk(context.TODO(), c.vm, anchorRegisterMsg) if err != nil { - c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) - continue + c.vm.Logger().Error("unable to generate anchor registeration chunk", zap.Error(err)) } - chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) - if err != nil { - c.vm.Logger().Error("unable to build chunk", zap.Error(err)) - continue - } c.auth.Add(chunk) // this will be a no-op because we are the producer c.PushChunk(context.TODO(), chunk) + + case <-t.C: + // if !c.vm.isReady() { + // c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") + // continue + // } + // if skipChunks { + // continue + // } + + // // Attempt to build a chunk + // now := time.Now().UnixMilli() - consts.ClockSkewAllowance + // r := c.vm.Rules(now) + // anchorCli := c.vm.Anchor() + // digest, err := anchorCli.RequestAnchorDigest() + // if err != nil { + // c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) + // continue + // } + // wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + // if err != nil { + // c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) + // continue + // } + // sigBytes, err := c.vm.Sign(wm) + // if err != nil { + // c.vm.Logger().Error("unable to sign message", zap.Error(err)) + // continue + // } + // sig, err := bls.SignatureFromBytes(sigBytes) + // if err != nil { + // c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) + // continue + // } + + // meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) + // if err != nil { + // c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) + // continue + // } + + // chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) + // if err != nil { + // c.vm.Logger().Error("unable to build chunk", zap.Error(err)) + // continue + // } + // c.auth.Add(chunk) // this will be a no-op because we are the producer + // c.PushChunk(context.TODO(), chunk) case <-c.vm.stop: // If engine taking too long to process message, Shutdown will not // be called. diff --git a/vm/dependencies.go b/vm/dependencies.go index e8f624b65c..246e55eb90 100644 --- a/vm/dependencies.go +++ b/vm/dependencies.go @@ -50,7 +50,6 @@ type Config interface { GetBlockBuildFrequency() time.Duration GetProcessingBuildSkip() int GetMinimumCertificateBroadcastNumerator() uint64 - GetAnchorURL() string } type Genesis interface { diff --git a/vm/resolutions.go b/vm/resolutions.go index 4c26651867..40050a4304 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -361,6 +361,10 @@ func (vm *VM) Accepted(ctx context.Context, b *chain.StatelessBlock, chunks []*c vm.Fatal("unable to update last accepted", zap.Error(err)) } + for _, anchor := range b.AnchorRegistrations { + vm.anchorRegistry.Register(anchor.Url, anchor.Namespace) + } + // Cleanup expired chunks we are tracking and chunk certificates vm.cm.SetBuildableMin(ctx, b.StatefulBlock.Timestamp) // clear unnecessary certs @@ -597,8 +601,12 @@ func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot return vm.cm.HandleAnchorChunk(ctx, anchor, slot, txs, priorityFeeReceiverAddr) } -func (vm *VM) Anchor() *anchor.Anchor { - return vm.anchor +func (vm *VM) AnchorRegistry() *anchor.AnchorRegistry { + return vm.anchorRegistry +} + +func (vm *VM) PushAnchorRegisterMsg(ctx context.Context, anchor *chain.Anchor) { + vm.cm.incomingAnchorRegisterMsg <- anchor } func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { diff --git a/vm/vm.go b/vm/vm.go index ba2a1a4ff2..ec8562ca57 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -79,9 +79,9 @@ type VM struct { tracer trace.Tracer // Handle chunks - cm *ChunkManager - anchor *anchor.Anchor - engine *chain.Engine + cm *ChunkManager + anchorRegistry *anchor.AnchorRegistry + engine *chain.Engine // track all issuedTxs (to prevent wasting bandwidth) // @@ -213,8 +213,8 @@ func (vm *VM) Initialize( vm.networkManager.SetHandler(chunkHandler, vm.cm) go vm.cm.Run(chunkSender) - anchorUrl := vm.config.GetAnchorURL() - vm.anchor = anchor.NewAnchor(anchorUrl, vm) + anchorRegistry := anchor.NewAnchorRegistry(vm) + vm.anchorRegistry = anchorRegistry // Setup tracer vm.tracer, err = htrace.New(vm.config.GetTraceConfig()) From 0b1f838e87a91935597a454da65072abdeb090fa Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Sat, 17 Aug 2024 00:33:31 +0900 Subject: [PATCH 10/18] partition --- anchor/anchor.go | 19 ++++++ vm/chunk_manager.go | 140 ++++++++++++++++++++++++++--------------- vm/proposer_monitor.go | 25 ++++++++ 3 files changed, 135 insertions(+), 49 deletions(-) diff --git a/anchor/anchor.go b/anchor/anchor.go index 48517571f4..9d5ee192a4 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,6 +1,8 @@ package anchor import ( + "slices" + "strings" "sync" "github.com/ava-labs/avalanchego/ids" @@ -49,6 +51,23 @@ func (r *AnchorRegistry) Remove(url string) error { return nil } +func (r *AnchorRegistry) Len() int { + return len(r.clients) +} + +func (r *AnchorRegistry) SortedAnchors() []*Anchor { + anchors := make([]*Anchor, 0, len(r.clients)) + for _, anchor := range r.clients { + anchors = append(anchors, anchor) + } + + slices.SortFunc(anchors, func(a, b *Anchor) int { + return strings.Compare(a.Url, b.Url) + }) + + return anchors +} + type Anchor struct { vm VM Url string `json:"url"` diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index 97066aa12d..da14b15486 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -18,6 +18,7 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/cache" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" @@ -39,9 +40,6 @@ const ( chunkCertifiedMsg uint8 = 0x3 // chunk + chunk certificate txMsg uint8 = 0x4 - // anchor registeration message, anchorInfo + sig + pubkey - anchorRegisterMsg uint8 = 0xf0 - chunkReq uint8 = 0x0 // TODO: add support for filtered chunk requests @@ -877,52 +875,96 @@ func (c *ChunkManager) Run(appSender common.AppSender) { c.PushChunk(context.TODO(), chunk) case <-t.C: - // if !c.vm.isReady() { - // c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") - // continue - // } - // if skipChunks { - // continue - // } - - // // Attempt to build a chunk - // now := time.Now().UnixMilli() - consts.ClockSkewAllowance - // r := c.vm.Rules(now) - // anchorCli := c.vm.Anchor() - // digest, err := anchorCli.RequestAnchorDigest() - // if err != nil { - // c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) - // continue - // } - // wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) - // if err != nil { - // c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) - // continue - // } - // sigBytes, err := c.vm.Sign(wm) - // if err != nil { - // c.vm.Logger().Error("unable to sign message", zap.Error(err)) - // continue - // } - // sig, err := bls.SignatureFromBytes(sigBytes) - // if err != nil { - // c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) - // continue - // } - - // meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) - // if err != nil { - // c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) - // continue - // } - - // chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) - // if err != nil { - // c.vm.Logger().Error("unable to build chunk", zap.Error(err)) - // continue - // } - // c.auth.Add(chunk) // this will be a no-op because we are the producer - // c.PushChunk(context.TODO(), chunk) + if !c.vm.isReady() { + c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") + continue + } + if skipChunks { + continue + } + ctx := context.TODO() + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := c.vm.Rules(now) + slot := utils.UnixRDeci(now, r.GetValidityWindow()) // chunk validity window is 9 seconds @todo + + _, epochHeight, err := c.getEpochInfo(ctx, slot) + if err != nil { + c.vm.metrics.gossipChunkSigInvalid.Inc() + c.vm.Logger().Warn("unable to determine chunk epoch", zap.Int64("slot", slot)) + return nil + } + + canonicalValidators, _, err := c.vm.proposerMonitor.GetWarpValidatorSet(ctx, epochHeight) + if err != nil { + c.vm.Logger().Warn("cannot get canonical validator set", zap.Error(err)) + } + + totalAnchors := c.vm.AnchorRegistry().Len() + + partition := c.vm.proposerMonitor.PartitionArray(ctx, epochHeight, epochHeight, totalAnchors, len(canonicalValidators)) + + myValidatorIdx := 0 + myPubkey := c.vm.snowCtx.PublicKey + for i, validator := range canonicalValidators { + if *validator.PublicKey == *myPubkey { + myValidatorIdx = i + break + } + } + partitionedAnchors, assigned := partition[myValidatorIdx] + if !assigned || len(partitionedAnchors) == 0 { + continue + } + + anchors := c.vm.AnchorRegistry().SortedAnchors() + anchorClis := make([]*anchor.Anchor, 0) + for _, anchorIdx := range partitionedAnchors { + anchorClis = append(anchorClis, anchors[anchorIdx]) + } + + for _, anchorCli := range anchorClis { + go func() { + // // Attempt to build a chunk + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := c.vm.Rules(now) + digest, err := anchorCli.RequestAnchorDigest() + if err != nil { + c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) + return + } + wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + if err != nil { + c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) + return + } + sigBytes, err := c.vm.Sign(wm) + if err != nil { + c.vm.Logger().Error("unable to sign message", zap.Error(err)) + return + } + sig, err := bls.SignatureFromBytes(sigBytes) + if err != nil { + c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) + return + } + + meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) + if err != nil { + c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) + return + } + + chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) + if err != nil { + c.vm.Logger().Error("unable to build chunk", zap.Error(err)) + return + } + c.auth.Add(chunk) // this will be a no-op because we are the producer + c.PushChunk(context.TODO(), chunk) + + }() + } + case <-c.vm.stop: // If engine taking too long to process message, Shutdown will not // be called. diff --git a/vm/proposer_monitor.go b/vm/proposer_monitor.go index 955df6c2d0..74547c008d 100644 --- a/vm/proposer_monitor.go +++ b/vm/proposer_monitor.go @@ -268,6 +268,31 @@ func (p *ProposerMonitor) AddressPartition(ctx context.Context, epoch uint64, he return info.partitionSet[int(partitionIdx)], nil } +// returns validatorIdx -> indexes of a set of anchors +func (p *ProposerMonitor) PartitionArray(ctx context.Context, epoch uint64, height uint64, targetLength int, validatorLength int) map[int][]int { + seedBytes := make([]byte, consts.Uint64Len) + binary.BigEndian.PutUint64(seedBytes, epoch) + binary.BigEndian.PutUint64(seedBytes[consts.Uint64Len:], height) + seed := utils.ToID(seedBytes) + shift := new(big.Int).SetBytes(seed[:]).Int64() + + ret := make(map[int][]int) + + for i := 0; i < validatorLength; i++ { + ret[i] = make([]int, 0) + } + + inc := 0 + for j := 0; j < targetLength; j++ { + validatorIdx := (int(shift) + inc) % validatorLength + l := ret[validatorIdx] + l = append(l, j) + ret[validatorIdx] = l + } + + return ret +} + func (p *ProposerMonitor) AddressPartitionByNamespace(ctx context.Context, epoch uint64, height uint64, ns []byte, partition uint8) (ids.NodeID, error) { // Get determinisitc ordering of validators info, ok := p.proposers.Get(height) From 8bb3f8208422f62ae03b92c4569213275e745ff2 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Sat, 17 Aug 2024 00:44:23 +0900 Subject: [PATCH 11/18] partition fix --- vm/proposer_monitor.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vm/proposer_monitor.go b/vm/proposer_monitor.go index 74547c008d..416f6368de 100644 --- a/vm/proposer_monitor.go +++ b/vm/proposer_monitor.go @@ -282,9 +282,8 @@ func (p *ProposerMonitor) PartitionArray(ctx context.Context, epoch uint64, heig ret[i] = make([]int, 0) } - inc := 0 for j := 0; j < targetLength; j++ { - validatorIdx := (int(shift) + inc) % validatorLength + validatorIdx := (int(shift) + j) % validatorLength l := ret[validatorIdx] l = append(l, j) ret[validatorIdx] = l From a082967faba5c2e3c7bd91eb626d7d002a81c948 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Mon, 19 Aug 2024 07:45:24 -0400 Subject: [PATCH 12/18] app level anchor registry --- examples/morpheusvm/actions/anchorreg.go | 115 +++++++++ examples/morpheusvm/actions/consts.go | 5 +- .../morpheusvm/cmd/morpheus-cli/cmd/action.go | 33 +++ .../morpheusvm/cmd/morpheus-cli/cmd/chain.go | 22 ++ .../morpheusvm/cmd/morpheus-cli/cmd/root.go | 2 + examples/morpheusvm/consts/types.go | 5 +- examples/morpheusvm/controller/resolutions.go | 6 + examples/morpheusvm/registry/registry.go | 1 + examples/morpheusvm/rpc/dependencies.go | 1 + examples/morpheusvm/rpc/jsonrpc_client.go | 11 + examples/morpheusvm/rpc/jsonrpc_server.go | 18 ++ examples/morpheusvm/storage/storage.go | 228 +++++++++++++++++- 12 files changed, 435 insertions(+), 12 deletions(-) create mode 100644 examples/morpheusvm/actions/anchorreg.go diff --git a/examples/morpheusvm/actions/anchorreg.go b/examples/morpheusvm/actions/anchorreg.go new file mode 100644 index 0000000000..0ed60e704d --- /dev/null +++ b/examples/morpheusvm/actions/anchorreg.go @@ -0,0 +1,115 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package actions + +import ( + "bytes" + "context" + "slices" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/hypersdk/chain" + "github.com/ava-labs/hypersdk/codec" + mconsts "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" + "github.com/ava-labs/hypersdk/examples/morpheusvm/storage" + "github.com/ava-labs/hypersdk/state" + "github.com/ava-labs/hypersdk/utils" +) + +var _ chain.Action = (*AnchorRegister)(nil) + +type AnchorRegister struct { + Url string `json:"url"` + Namespace []byte `json:"namespace"` + Delete bool `json:"delete"` +} + +func (*AnchorRegister) GetTypeID() uint8 { + return mconsts.AnchorRegisterID +} + +func (t *AnchorRegister) StateKeys(actor codec.Address, _ ids.ID) state.Keys { + return state.Keys{ + string(storage.AnchorKey(t.Namespace)): state.All, + string(storage.AnchorRegistryKey()): state.All, + } +} + +func (*AnchorRegister) StateKeyChunks() []uint16 { + return []uint16{} +} + +func (*AnchorRegister) OutputsWarpMessage() bool { + return false +} + +func (t *AnchorRegister) Execute( + ctx context.Context, + _ chain.Rules, + mu state.Mutable, + _ int64, + actor codec.Address, + _ ids.ID, + _ bool, +) (bool, []byte, *warp.UnsignedMessage, error) { + namespaces, _, err := storage.GetAnchors(ctx, mu) + if err != nil { + return false, utils.ErrBytes(err), nil, nil + } + + if t.Delete { + nsIdx := -1 + for i, ns := range namespaces { + if bytes.Equal(t.Namespace, ns) { + nsIdx = i + break + } + } + namespaces = slices.Delete(namespaces, nsIdx, nsIdx+1) + if err := storage.DelAnchor(ctx, mu, t.Namespace); err != nil { + return false, utils.ErrBytes(err), nil, nil + } + } else { + namespaces = append(namespaces, t.Namespace) + if err := storage.SetAnchor(ctx, mu, t.Namespace, t.Url); err != nil { + return false, utils.ErrBytes(err), nil, nil + } + } + if err := storage.SetAnchors(ctx, mu, namespaces); err != nil { + return false, utils.ErrBytes(err), nil, nil + } + return true, nil, nil, nil +} + +func (*AnchorRegister) ComputeUnits(chain.Rules) uint64 { + return AnchorRegisterComputeUnits +} + +func (t *AnchorRegister) Size() int { + return codec.BytesLen(t.Namespace) + codec.StringLen(t.Url) +} + +func (t *AnchorRegister) Marshal(p *codec.Packer) { + p.PackBytes(t.Namespace) + p.PackString(t.Url) + p.PackBool(t.Delete) +} + +func UnmarshalAnchorRegister(p *codec.Packer, _ *warp.Message) (chain.Action, error) { + var anchorReg AnchorRegister + p.UnpackBytes(-1, false, &anchorReg.Namespace) + anchorReg.Url = p.UnpackString(false) + anchorReg.Delete = p.UnpackBool() + return &anchorReg, nil +} + +func (*AnchorRegister) ValidRange(chain.Rules) (int64, int64) { + // Returning -1, -1 means that the action is always valid. + return -1, -1 +} + +func (*AnchorRegister) NMTNamespace() []byte { + return defaultNMTNamespace // TODO: mark this the same to registering namespace? +} diff --git a/examples/morpheusvm/actions/consts.go b/examples/morpheusvm/actions/consts.go index 2520572517..274ed8978f 100644 --- a/examples/morpheusvm/actions/consts.go +++ b/examples/morpheusvm/actions/consts.go @@ -4,8 +4,9 @@ package actions const ( - TransferComputeUnits = 1 - MsgComputeUnits = 2 + TransferComputeUnits = 1 + MsgComputeUnits = 2 + AnchorRegisterComputeUnits = 1 ) var defaultNMTNamespace = make([]byte, 8) diff --git a/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go b/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go index 51f6e9a1dd..8881526b37 100644 --- a/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go +++ b/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go @@ -59,3 +59,36 @@ var transferCmd = &cobra.Command{ return err }, } + +var anchorCmd = &cobra.Command{ + Use: "anchor", + RunE: func(*cobra.Command, []string) error { + ctx := context.Background() + _, _, factory, cli, bcli, ws, err := handler.DefaultActor() + if err != nil { + return err + } + + namespaceStr, err := handler.Root().PromptString("namespace", 0, 8) + if err != nil { + return err + } + namespace := []byte(namespaceStr) + url, err := handler.Root().PromptString("url", 0, 100) + if err != nil { + return err + } + delete, err := handler.Root().PromptBool("delete") + if err != nil { + return err + } + + // Generate transaction + _, _, err = sendAndWait(ctx, nil, &actions.AnchorRegister{ + Namespace: namespace, + Delete: delete, + Url: url, + }, cli, bcli, ws, factory, true) + return err + }, +} diff --git a/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go b/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go index aa72426861..d68b587c88 100644 --- a/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go +++ b/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go @@ -5,6 +5,7 @@ package cmd import ( "context" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -73,6 +74,27 @@ var watchChainCmd = &cobra.Command{ }, } +var anchorsCmd = &cobra.Command{ + Use: "anchors", + RunE: func(_ *cobra.Command, args []string) error { + ctx := context.Background() + _, _, _, _, bcli, _, err := handler.DefaultActor() + if err != nil { + return err + } + namespaces, urls, err := bcli.RegisteredAnchors(ctx) + if err != nil { + return err + } + fmt.Printf("num of anchors registered: %d\n", len(namespaces)) + for i := 0; i < len(namespaces); i++ { + fmt.Printf("%s: %s\n", string(namespaces[i]), urls[i]) + } + + return nil + }, +} + var watchPreConfsCmd = &cobra.Command{ Use: "watch-preconfs", RunE: func(_ *cobra.Command, args []string) error { diff --git a/examples/morpheusvm/cmd/morpheus-cli/cmd/root.go b/examples/morpheusvm/cmd/morpheus-cli/cmd/root.go index 40432c6bff..890cf9020d 100644 --- a/examples/morpheusvm/cmd/morpheus-cli/cmd/root.go +++ b/examples/morpheusvm/cmd/morpheus-cli/cmd/root.go @@ -155,11 +155,13 @@ func init() { watchChainCmd, watchPreConfsCmd, watchPreConfsStandCmd, + anchorsCmd, ) // actions actionCmd.AddCommand( transferCmd, + anchorCmd, ) // spam diff --git a/examples/morpheusvm/consts/types.go b/examples/morpheusvm/consts/types.go index 352fe12d4f..10fca3b941 100644 --- a/examples/morpheusvm/consts/types.go +++ b/examples/morpheusvm/consts/types.go @@ -5,8 +5,9 @@ package consts const ( // Action TypeIDs - TransferID uint8 = 0 - MsgID uint8 = 1 + TransferID uint8 = 0 + MsgID uint8 = 1 + AnchorRegisterID uint8 = 2 // Auth TypeIDs ED25519ID uint8 = 0 SECP256R1ID uint8 = 1 diff --git a/examples/morpheusvm/controller/resolutions.go b/examples/morpheusvm/controller/resolutions.go index 78c5b89690..a7b21a3268 100644 --- a/examples/morpheusvm/controller/resolutions.go +++ b/examples/morpheusvm/controller/resolutions.go @@ -40,3 +40,9 @@ func (c *Controller) GetBalanceFromState( ) (uint64, error) { return storage.GetBalanceFromState(ctx, c.inner.ReadState, acct) } + +func (c *Controller) GetRegisteredAnchorsFromState( + ctx context.Context, +) ([][]byte, []string, error) { + return storage.GetAnchorsFromState(ctx, c.inner.ReadState) +} diff --git a/examples/morpheusvm/registry/registry.go b/examples/morpheusvm/registry/registry.go index c3b20af099..61d9979f6d 100644 --- a/examples/morpheusvm/registry/registry.go +++ b/examples/morpheusvm/registry/registry.go @@ -24,6 +24,7 @@ func init() { // When registering new actions, ALWAYS make sure to append at the end. consts.ActionRegistry.Register((&actions.Transfer{}).GetTypeID(), actions.UnmarshalTransfer, false), consts.ActionRegistry.Register((&actions.SequencerMsg{}).GetTypeID(), actions.UnmarshalSequencerMsg, false), + consts.ActionRegistry.Register((&actions.AnchorRegister{}).GetTypeID(), actions.UnmarshalAnchorRegister, false), // When registering new auth, ALWAYS make sure to append at the end. consts.AuthRegistry.Register((&auth.ED25519{}).GetTypeID(), auth.UnmarshalED25519, false), diff --git a/examples/morpheusvm/rpc/dependencies.go b/examples/morpheusvm/rpc/dependencies.go index f8e475dc64..10d1120bee 100644 --- a/examples/morpheusvm/rpc/dependencies.go +++ b/examples/morpheusvm/rpc/dependencies.go @@ -18,4 +18,5 @@ type Controller interface { Tracer() trace.Tracer GetTransaction(context.Context, ids.ID) (bool, int64, bool, chain.Dimensions, uint64, error) GetBalanceFromState(context.Context, codec.Address) (uint64, error) + GetRegisteredAnchorsFromState(context.Context) ([][]byte, []string, error) } diff --git a/examples/morpheusvm/rpc/jsonrpc_client.go b/examples/morpheusvm/rpc/jsonrpc_client.go index c976888fb0..c287337fcb 100644 --- a/examples/morpheusvm/rpc/jsonrpc_client.go +++ b/examples/morpheusvm/rpc/jsonrpc_client.go @@ -86,6 +86,17 @@ func (cli *JSONRPCClient) Balance(ctx context.Context, addr string) (uint64, err return resp.Amount, err } +func (cli *JSONRPCClient) RegisteredAnchors(ctx context.Context) ([][]byte, []string, error) { + resp := new(RegisteredAnchorReply) + err := cli.requester.SendRequest( + ctx, + "registeredAnchors", + nil, + resp, + ) + return resp.Namespaces, resp.Urls, err +} + func (cli *JSONRPCClient) WaitForBalance( ctx context.Context, addr string, diff --git a/examples/morpheusvm/rpc/jsonrpc_server.go b/examples/morpheusvm/rpc/jsonrpc_server.go index 85f8c1919c..06ed8b4b3f 100644 --- a/examples/morpheusvm/rpc/jsonrpc_server.go +++ b/examples/morpheusvm/rpc/jsonrpc_server.go @@ -83,3 +83,21 @@ func (j *JSONRPCServer) Balance(req *http.Request, args *BalanceArgs, reply *Bal reply.Amount = balance return err } + +type RegisteredAnchorReply struct { + Namespaces [][]byte `json:"namespaces"` + Urls []string `json:"urls"` +} + +func (j *JSONRPCServer) RegisteredAnchors(req *http.Request, args *struct{}, reply *RegisteredAnchorReply) error { + ctx, span := j.c.Tracer().Start(req.Context(), "Server.Balance") + defer span.End() + + namespaces, urls, err := j.c.GetRegisteredAnchorsFromState(ctx) + if err != nil { + return err + } + reply.Namespaces = namespaces + reply.Urls = urls + return err +} diff --git a/examples/morpheusvm/storage/storage.go b/examples/morpheusvm/storage/storage.go index 59e9dba4e5..93cdea558b 100644 --- a/examples/morpheusvm/storage/storage.go +++ b/examples/morpheusvm/storage/storage.go @@ -44,14 +44,16 @@ const ( txPrefix = 0x0 // stateDB - balancePrefix = 0x0 - heightPrefix = 0x1 - pHeightPrefix = 0x2 - timestampPrefix = 0x3 - feePrefix = 0x4 - incomingWarpPrefix = 0x5 - outgoingWarpPrefix = 0x6 - epochPrefix = 0x7 + balancePrefix = 0x0 + heightPrefix = 0x1 + pHeightPrefix = 0x2 + timestampPrefix = 0x3 + feePrefix = 0x4 + incomingWarpPrefix = 0x5 + outgoingWarpPrefix = 0x6 + epochPrefix = 0x7 + anchorRegisteryPrefix = 0x8 + anchorPrefix = 0x9 ) const BalanceChunks uint16 = 1 @@ -282,3 +284,213 @@ func EpochKey(epoch uint64) string { binary.BigEndian.PutUint64(k[1:], epoch) return string(k) } + +func AnchorRegistryKey() string { + k := make([]byte, 1) + k[0] = anchorRegisteryPrefix + return string(k) +} + +func PackNamespaces(namespaces [][]byte) ([]byte, error) { + p := codec.NewWriter(len(namespaces)*8, consts.NetworkSizeLimit) + p.PackInt(len(namespaces)) + for _, ns := range namespaces { + p.PackBytes(ns) + } + return p.Bytes(), p.Err() +} + +func UnpackNamespaces(raw []byte) ([][]byte, error) { + p := codec.NewReader(raw, consts.NetworkSizeLimit) + nsLen := p.UnpackInt(false) + namespaces := make([][]byte, 0, nsLen) + for i := 0; i < nsLen; i++ { + ns := make([]byte, 0, 8) + p.UnpackBytes(-1, false, &ns) + namespaces = append(namespaces, ns) + } + + return namespaces, p.Err() +} + +func GetAnchors( + ctx context.Context, + im state.Immutable, +) ([][]byte, []string, error) { + _, namespaces, urls, _, err := getAnchors(ctx, im) + return namespaces, urls, err +} + +func getAnchors( + ctx context.Context, + im state.Immutable, +) (string, [][]byte, []string, bool, error) { + k := AnchorRegistryKey() + namespaces, exists, err := innerGetAnchors(im.Get(ctx, k)) + if err != nil { + return "", nil, nil, false, err + } + + urls := make([]string, 0, len(namespaces)) + for _, ns := range namespaces { + url, err := GetAnchor(ctx, im, ns) + if err != nil { + return "", nil, nil, false, err + } + urls = append(urls, url) + } + return k, namespaces, urls, exists, err +} + +// Used to serve RPC queries +func GetAnchorsFromState( + ctx context.Context, + f ReadState, +) ([][]byte, []string, error) { + k := AnchorRegistryKey() + values, errs := f(ctx, []string{k}) + namespaces, _, err := innerGetAnchors(values[0], errs[0]) + if err != nil { + return nil, nil, err + } + + urls := make([]string, 0, len(namespaces)) + for _, ns := range namespaces { + k := AnchorKey(ns) + values, errs := f(ctx, []string{k}) + url, _, err := innerGetAnchor(values[0], errs[0]) + if err != nil { + return nil, nil, err + } + urls = append(urls, url) + } + return namespaces, urls, err +} + +func innerGetAnchors( + v []byte, + err error, +) ([][]byte, bool, error) { + if errors.Is(err, database.ErrNotFound) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + namespaces, err := UnpackNamespaces(v) + if err != nil { + return nil, false, err + } + + return namespaces, true, nil +} + +func SetAnchors( + ctx context.Context, + mu state.Mutable, + namespaces [][]byte, +) error { + return setAnchors(ctx, mu, namespaces) +} + +func setAnchors( + ctx context.Context, + mu state.Mutable, + namespaces [][]byte, +) error { + k := AnchorRegistryKey() + packed, err := PackNamespaces(namespaces) + if err != nil { + return err + } + return mu.Put(ctx, k, packed) +} + +func AnchorKey(namespace []byte) string { + k := make([]byte, 1+len(namespace)) + k[0] = anchorPrefix + copy(k[1:], namespace[:]) + return string(k) +} + +// If locked is 0, then account does not exist +func GetAnchor( + ctx context.Context, + im state.Immutable, + namespace []byte, +) (string, error) { + _, anchor, _, err := getAnchor(ctx, im, namespace) + return anchor, err +} + +func getAnchor( + ctx context.Context, + im state.Immutable, + namespace []byte, +) (string, string, bool, error) { + k := AnchorKey(namespace) + anchor, exists, err := innerGetAnchor(im.Get(ctx, k)) + return k, anchor, exists, err +} + +// Used to serve RPC queries +func GetAnchorFromState( + ctx context.Context, + f ReadState, + namespace []byte, +) (string, error) { + k := AnchorKey(namespace) + values, errs := f(ctx, []string{k}) + anchor, _, err := innerGetAnchor(values[0], errs[0]) + return anchor, err +} + +func innerGetAnchor( + v []byte, + err error, +) (string, bool, error) { + if errors.Is(err, database.ErrNotFound) { + return "", false, nil + } + if err != nil { + return "", false, err + } + return string(v), true, nil +} + +func SetAnchor( + ctx context.Context, + mu state.Mutable, + namespace []byte, + url string, +) error { + k := AnchorKey(namespace) + return setAnchor(ctx, mu, k, url) +} + +func setAnchor( + ctx context.Context, + mu state.Mutable, + key string, + url string, +) error { + urlBytes := []byte(url) + return mu.Put(ctx, key, urlBytes) +} + +func DelAnchor( + ctx context.Context, + mu state.Mutable, + namespace []byte, +) error { + k := AnchorKey(namespace) + return delAnchor(ctx, mu, k) +} + +func delAnchor( + ctx context.Context, + mu state.Mutable, + key string, +) error { + return mu.Delete(ctx, key) +} From 0388bde3cecdd6c47d1e714b9ac3de792e019dc2 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Mon, 19 Aug 2024 10:16:55 -0400 Subject: [PATCH 13/18] app level anchor registry --- chain/chunk.go | 90 ++---------------------- chain/processor.go | 6 +- chain/transaction.go | 1 + examples/morpheusvm/actions/anchorreg.go | 5 +- examples/morpheusvm/storage/storage.go | 7 +- rpc/dependencies.go | 1 - rpc/jsonrpc_client.go | 17 +---- rpc/jsonrpc_server.go | 36 ---------- vm/chunk_manager.go | 27 ++----- vm/resolutions.go | 4 -- vm/vm.go | 4 ++ 11 files changed, 27 insertions(+), 171 deletions(-) diff --git a/chain/chunk.go b/chain/chunk.go index 5cc8ba1fe4..5188574af3 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -21,14 +21,12 @@ const chunkPrealloc = 16_384 const ( AnchorToB = iota AnchorRoB - AnchorRegister ) type Anchor struct { BlockType int `json:"blockType"` // use to determine if it is TOB or ROB Namespace string `json:"namespace"` Url string `json:"url"` - Creation bool `json:"string"` // with this flag, we can include zero tx in a chunk for a anchor registeration } type Chunk struct { @@ -50,87 +48,6 @@ type Chunk struct { authCounts map[uint8]int } -func BuildAnchorRegisterChunk(ctx context.Context, vm VM, anchor *Anchor) (*Chunk, error) { - if !anchor.Creation { - return nil, fmt.Errorf("not a anchor registeration chunk") - } - - start := time.Now() - now := time.Now().UnixMilli() - consts.ClockSkewAllowance - r := vm.Rules(now) - c := &Chunk{ - Slot: utils.UnixRDeci(now, r.GetValidityWindow()), // chunk validity window is 9 seconds @todo - } - epoch := utils.Epoch(now, r.GetEpochDuration()) - - // Don't build chunk if no P-Chain height for epoch - timestamp, heights, err := vm.Engine().GetEpochHeights(ctx, []uint64{epoch}) - if err != nil { - return nil, err - } - executedEpoch := utils.Epoch(timestamp, r.GetEpochDuration()) // epoch duration set to 10 seconds. - if executedEpoch+2 < epoch { // only require + 2 because we don't care about epoch + 1 like in verification. - return nil, fmt.Errorf("executed epoch (%d) is too far behind (%d) to verify chunk", executedEpoch, epoch) - } - if heights[0] == nil { - return nil, fmt.Errorf("no P-Chain height for epoch %d", epoch) - } - - // Check if validator - // - // If not a validator in this epoch height, don't build. - amValidator, err := vm.IsValidator(ctx, *heights[0], vm.NodeID()) - if err != nil { - return nil, err - } - if !amValidator { - return nil, ErrNotAValidator - } - - // Setup chunk - c.PriorityFeeReceiverAddr = codec.BlackholeAddress - c.Producer = vm.NodeID() - c.Beneficiary = vm.Beneficiary() - c.Signer = vm.Signer() - - // Sign chunk - digest, err := c.Digest() - if err != nil { - return nil, err - } - wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) - if err != nil { - return nil, err - } - sig, err := vm.Sign(wm) - if err != nil { - return nil, err - } - c.Signature, err = bls.SignatureFromBytes(sig) - if err != nil { - return nil, err - } - bytes, err := c.Marshal() - if err != nil { - return nil, err - } - c.id = utils.ToID(bytes) - - vm.Logger().Info( - "built registering chunk with signature from anchor msg", - zap.Stringer("nodeID", vm.NodeID()), - zap.Uint32("networkID", r.NetworkID()), - zap.Stringer("chainID", r.ChainID()), - zap.Int64("slot", c.Slot), - zap.Uint64("epoch", epoch), - zap.Int("txs", len(c.Txs)), - zap.String("signer", hex.EncodeToString(bls.PublicKeyToCompressedBytes(c.Signer))), - zap.String("signature", hex.EncodeToString(bls.SignatureToBytes(c.Signature))), - zap.Duration("t", time.Since(start)), - ) - return c, nil -} - func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *Anchor, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance @@ -326,12 +243,15 @@ func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { if !ok { break } + txID := tx.ID().String() + vm.Logger().Debug("picking up a tx from mempool", zap.String("txID", txID)) // Ensure we haven't included this transaction in a chunk yet // // Should protect us from issuing repeat txs (if others get duplicates, // there will be duplicate inclusion but this is fixed with partitions) if vm.IsIssuedTx(ctx, tx) { vm.RecordChunkBuildTxDropped() + vm.Logger().Debug("tx issued", zap.String("txID", txID)) continue } @@ -347,6 +267,7 @@ func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { // TODO: verify transactions if tx.Base.Timestamp > c.Slot { + vm.Logger().Debug("tx timestamp greater than chunk slot", zap.String("txID", txID)) vm.RecordChunkBuildTxDropped() continue } @@ -355,11 +276,14 @@ func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { txUnits, err := tx.Units(sm, r) if err != nil { vm.RecordChunkBuildTxDropped() + vm.Logger().Debug("failed to get units for tx", zap.String("txID", txID), zap.Error(err)) vm.Logger().Warn("failed to get units for transaction", zap.Error(err)) continue } + vm.Logger().Debug("units", zap.String("txID", txID), zap.Any("tx units", txUnits), zap.Any("max units", maxChunkUnits)) nextUnits, err := Add(chunkUnits, txUnits) if err != nil || !maxChunkUnits.Greater(nextUnits) { + vm.Logger().Debug("chunk full before tx", zap.String("txID", txID), zap.Any("tx units", txUnits), zap.Any("max units", maxChunkUnits)) full = true // TODO: update mempool to only provide txs that can fit in chunk // Want to maximize how "full" chunk is, so need to be a little complex diff --git a/chain/processor.go b/chain/processor.go index af71c5547c..3aa1e45b12 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -233,11 +233,6 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { return } p.acceptedNS[chunk.Anchor.Namespace] = struct{}{} - case AnchorRegister: - if _, exists := p.anchors[chunk.Anchor.Url]; !exists { - p.anchors[chunk.Anchor.Url] = chunk.Anchor - p.vm.Logger().Debug("adding new anchor to processor") - } } } @@ -290,6 +285,7 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { p.results[chunkIndex][txIndex] = &Result{Valid: false} return nil, nil } + p.vm.Logger().Debug("units", zap.Any("units", units), zap.Any("unitPrices", p.r.GetUnitPrices()), zap.Uint64("fee", fee), zap.Uint64("maxFee", tx.Base.MaxFee)) if tx.Base.MaxFee < fee { // This should be checked by chunk producer before inclusion. // diff --git a/chain/transaction.go b/chain/transaction.go index 2cdf3f93dd..601432b715 100644 --- a/chain/transaction.go +++ b/chain/transaction.go @@ -136,6 +136,7 @@ func (t *Transaction) StateKeys(sm StateManager) (state.Keys, error) { for _, m := range []state.Keys{actionKeys, sponsorKeys} { for k, v := range m { if !keys.Valid(k) { + fmt.Printf("action key not valid: %s\n", t.ID().String()) return nil, ErrInvalidKeyValue } stateKeys.Add(k, v) diff --git a/examples/morpheusvm/actions/anchorreg.go b/examples/morpheusvm/actions/anchorreg.go index 0ed60e704d..e03a494fed 100644 --- a/examples/morpheusvm/actions/anchorreg.go +++ b/examples/morpheusvm/actions/anchorreg.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/consts" mconsts "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" "github.com/ava-labs/hypersdk/examples/morpheusvm/storage" "github.com/ava-labs/hypersdk/state" @@ -38,7 +39,7 @@ func (t *AnchorRegister) StateKeys(actor codec.Address, _ ids.ID) state.Keys { } func (*AnchorRegister) StateKeyChunks() []uint16 { - return []uint16{} + return []uint16{storage.BalanceChunks, storage.BalanceChunks} } func (*AnchorRegister) OutputsWarpMessage() bool { @@ -88,7 +89,7 @@ func (*AnchorRegister) ComputeUnits(chain.Rules) uint64 { } func (t *AnchorRegister) Size() int { - return codec.BytesLen(t.Namespace) + codec.StringLen(t.Url) + return codec.BytesLen(t.Namespace) + codec.StringLen(t.Url) + consts.BoolLen } func (t *AnchorRegister) Marshal(p *codec.Packer) { diff --git a/examples/morpheusvm/storage/storage.go b/examples/morpheusvm/storage/storage.go index 93cdea558b..31d9ee81fe 100644 --- a/examples/morpheusvm/storage/storage.go +++ b/examples/morpheusvm/storage/storage.go @@ -286,8 +286,10 @@ func EpochKey(epoch uint64) string { } func AnchorRegistryKey() string { - k := make([]byte, 1) + // state key must >= 2 bytes + k := make([]byte, 1+consts.Uint16Len) k[0] = anchorRegisteryPrefix + binary.BigEndian.PutUint16(k[1:], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks return string(k) } @@ -407,9 +409,10 @@ func setAnchors( } func AnchorKey(namespace []byte) string { - k := make([]byte, 1+len(namespace)) + k := make([]byte, 1+len(namespace)+consts.Uint16Len) k[0] = anchorPrefix copy(k[1:], namespace[:]) + binary.BigEndian.PutUint16(k[1+len(namespace):], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks return string(k) } diff --git a/rpc/dependencies.go b/rpc/dependencies.go index 2d7e67603d..edfce342a2 100644 --- a/rpc/dependencies.go +++ b/rpc/dependencies.go @@ -42,5 +42,4 @@ type VM interface { RecordWebsocketConnection(int) RecordRPCTxInvalid() - PushAnchorRegisterMsg(ctx context.Context, anchor *chain.Anchor) } diff --git a/rpc/jsonrpc_client.go b/rpc/jsonrpc_client.go index 6d852c4ef6..cd3391373a 100644 --- a/rpc/jsonrpc_client.go +++ b/rpc/jsonrpc_client.go @@ -180,10 +180,12 @@ func (cli *JSONRPCClient) GenerateTransaction( if err != nil { return nil, nil, 0, err } + fmt.Printf("estimated max units: %+v\n", maxUnits) maxFee, err := chain.MulSum(unitPrices, maxUnits) if err != nil { return nil, nil, 0, err } + fmt.Printf("maxFee: %+v\n", maxFee) f, tx, err := cli.GenerateTransactionManual(parser, wm, action, authFactory, maxFee, modifiers...) if err != nil { return nil, nil, 0, err @@ -354,18 +356,3 @@ func (cli *JSONRPCClient) GenerateAggregateWarpSignature( } return message, weight, signatureWeight, nil } - -func (cli *JSONRPCClient) ReplaceAnchor(ctx context.Context, url string, pubkey *bls.PublicKey, sig *bls.Signature) (bool, error) { - resp := new(RegisterAnchorReply) - err := cli.requester.SendRequest( - ctx, - "replaceAnchor", - &RegisterAnchorArgs{ - Url: url, - Pubkey: pubkey, - Signature: sig, - }, - resp, - ) - return resp.Added, err -} diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go index dfbb9c235b..97a556a4a8 100644 --- a/rpc/jsonrpc_server.go +++ b/rpc/jsonrpc_server.go @@ -204,39 +204,3 @@ func (j *JSONRPCServer) GetWarpSignatures( reply.Signatures = validSignatures return nil } - -type RegisterAnchorArgs struct { - Url string `json:"url"` - Namespace string `json:"namespace"` - Signature *bls.Signature `json:"signature"` - Pubkey *bls.PublicKey `json:"pubkey"` -} - -type RegisterAnchorReply struct { - Added bool `json:"success"` -} - -func (j *JSONRPCServer) RegisterAnchor( - req *http.Request, - args *RegisterAnchorArgs, - reply *RegisterAnchorReply, -) error { - msg := []byte(args.Url) - verified := bls.Verify(args.Pubkey, args.Signature, msg) - if !verified { - j.vm.Logger().Error("unable to veirfy anchor replacement sig") - return fmt.Errorf("unable to verify the signature against the pubkey and msg") - } - - anchor := chain.Anchor{ - BlockType: -1, - Namespace: args.Namespace, - Url: args.Url, - Creation: true, - } - - j.vm.PushAnchorRegisterMsg(context.Background(), &anchor) - reply.Added = true - - return nil -} diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index da14b15486..850475ae26 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -245,8 +245,6 @@ type ChunkManager struct { incomingChunks chan *chunkGossipWrapper incomingTxs chan *txGossipWrapper - incomingAnchorRegisterMsg chan *chain.Anchor - epochHeights *cache.FIFO[uint64, uint64] built *emap.EMap[*chunkWrapper] @@ -853,27 +851,6 @@ func (c *ChunkManager) Run(appSender common.AppSender) { defer t.Stop() for { select { - case anchorRegisterMsg := <-c.incomingAnchorRegisterMsg: - if !anchorRegisterMsg.Creation { - continue - } - - if !c.vm.isReady() { - c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") - continue - } - if skipChunks { - continue - } - - chunk, err := chain.BuildAnchorRegisterChunk(context.TODO(), c.vm, anchorRegisterMsg) - if err != nil { - c.vm.Logger().Error("unable to generate anchor registeration chunk", zap.Error(err)) - } - - c.auth.Add(chunk) // this will be a no-op because we are the producer - c.PushChunk(context.TODO(), chunk) - case <-t.C: if !c.vm.isReady() { c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") @@ -999,6 +976,10 @@ func (c *ChunkManager) Run(appSender common.AppSender) { c.vm.Logger().Error("unable to build chunk", zap.Error(err)) continue default: + c.vm.Logger().Debug("chunk built", zap.Int("numTxs", len(chunk.Txs))) + for _, tx := range chunk.Txs { + c.vm.Logger().Debug("tx in chunk", zap.String("txID", tx.ID().String())) + } } c.auth.Add(chunk) // this will be a no-op because we are the producer c.PushChunk(context.TODO(), chunk) diff --git a/vm/resolutions.go b/vm/resolutions.go index 40050a4304..af092ae351 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -605,10 +605,6 @@ func (vm *VM) AnchorRegistry() *anchor.AnchorRegistry { return vm.anchorRegistry } -func (vm *VM) PushAnchorRegisterMsg(ctx context.Context, anchor *chain.Anchor) { - vm.cm.incomingAnchorRegisterMsg <- anchor -} - func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { return vm.issuedTxs.Has(tx) } diff --git a/vm/vm.go b/vm/vm.go index ec8562ca57..f12d369d7d 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -778,6 +778,7 @@ func (vm *VM) Submit( // Perform syntactic verification if _, err := tx.SyntacticVerify(ctx, vm.StateManager(), r, now); err != nil { + vm.Logger().Info("synthetic verfication failed", zap.String("txID", tx.ID().String()), zap.Error(err)) errs = append(errs, err) continue } @@ -785,6 +786,7 @@ func (vm *VM) Submit( // Ensure state keys are valid _, err := tx.StateKeys(vm.c.StateManager()) if err != nil { + vm.Logger().Info("state keys arent valid for tx", zap.String("txID", tx.ID().String()), zap.Error(err)) errs = append(errs, ErrNotAdded) continue } @@ -793,6 +795,7 @@ func (vm *VM) Submit( if verifyAuth && vm.config.GetVerifyAuth() { msg, err := tx.Digest() if err != nil { + vm.Logger().Info("unable to make digest of a tx", zap.Error(err)) // Should never fail errs = append(errs, err) continue @@ -804,6 +807,7 @@ func (vm *VM) Submit( if err := vm.webSocketServer.RemoveTx(txID, err); err != nil { vm.snowCtx.Log.Warn("unable to remove tx from webSocketServer", zap.Error(err)) } + vm.Logger().Info("verify auth of the tx", zap.String("txID", tx.ID().String()), zap.Error(err)) errs = append(errs, err) continue } From fef43fc66cffc5f4cf3e1f78ceae739388f8481e Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Mon, 19 Aug 2024 13:58:49 -0400 Subject: [PATCH 14/18] vm & hypersdk level anchor registry --- actions/consts.go | 13 ++++ actions/keys.go | 30 +++++++++ actions/utils.go | 28 ++++++++ anchor/anchor.go | 17 +++-- chain/block.go | 27 +++++++- chain/chunk.go | 86 +++++++++++++++++++++--- chain/engine.go | 12 +++- chain/processor.go | 39 +++++++++-- examples/morpheusvm/actions/anchorreg.go | 4 +- examples/morpheusvm/consts/types.go | 4 +- examples/morpheusvm/scripts/run.sh | 2 +- examples/morpheusvm/storage/storage.go | 64 ++++++++---------- vm/resolutions.go | 14 ++-- 13 files changed, 270 insertions(+), 70 deletions(-) create mode 100644 actions/consts.go create mode 100644 actions/keys.go create mode 100644 actions/utils.go diff --git a/actions/consts.go b/actions/consts.go new file mode 100644 index 0000000000..784dd01539 --- /dev/null +++ b/actions/consts.go @@ -0,0 +1,13 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package actions + +const ( + AnchorRegisterComputeUnits = 1 +) + +const ( + // pre-defined actions starts from 0xf0 + AnchorRegisterID uint8 = 0xf0 +) diff --git a/actions/keys.go b/actions/keys.go new file mode 100644 index 0000000000..d95b67b116 --- /dev/null +++ b/actions/keys.go @@ -0,0 +1,30 @@ +package actions + +import ( + "encoding/binary" + + "github.com/ava-labs/hypersdk/consts" +) + +const ( + AnchorRegisteryPrefix = 0xf0 + AnchorPrefix = 0xf1 +) + +const AnchorChunks uint16 = 1 + +func AnchorRegistryKey() string { + // state key must >= 2 bytes + k := make([]byte, 1+consts.Uint16Len) + k[0] = AnchorRegisteryPrefix + binary.BigEndian.PutUint16(k[1:], AnchorChunks) //TODO: update the BalanceChunks to AnchorChunks + return string(k) +} + +func AnchorKey(namespace []byte) string { + k := make([]byte, 1+len(namespace)+consts.Uint16Len) + k[0] = AnchorPrefix + copy(k[1:], namespace[:]) + binary.BigEndian.PutUint16(k[1+len(namespace):], AnchorChunks) //TODO: update the BalanceChunks to AnchorChunks + return string(k) +} diff --git a/actions/utils.go b/actions/utils.go new file mode 100644 index 0000000000..029d920916 --- /dev/null +++ b/actions/utils.go @@ -0,0 +1,28 @@ +package actions + +import ( + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/consts" +) + +func PackNamespaces(namespaces [][]byte) ([]byte, error) { + p := codec.NewWriter(len(namespaces)*8, consts.NetworkSizeLimit) + p.PackInt(len(namespaces)) + for _, ns := range namespaces { + p.PackBytes(ns) + } + return p.Bytes(), p.Err() +} + +func UnpackNamespaces(raw []byte) ([][]byte, error) { + p := codec.NewReader(raw, consts.NetworkSizeLimit) + nsLen := p.UnpackInt(false) + namespaces := make([][]byte, 0, nsLen) + for i := 0; i < nsLen; i++ { + ns := make([]byte, 0, 8) + p.UnpackBytes(-1, false, &ns) + namespaces = append(namespaces, ns) + } + + return namespaces, p.Err() +} diff --git a/anchor/anchor.go b/anchor/anchor.go index 9d5ee192a4..73b4c581fa 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/utils" ) type AnchorRegistry struct { @@ -23,16 +24,20 @@ func NewAnchorRegistry(vm VM) *AnchorRegistry { } } +func (r *AnchorRegistry) Reset() { + r.clientsL.Lock() + defer r.clientsL.Unlock() + + r.clients = make(map[ids.ID]*Anchor) +} + func (r *AnchorRegistry) Register(url string, namespace string) error { anchorCli := &Anchor{ Url: url, vm: r.vm, Namespace: namespace, } - clientID, err := anchorCli.ID() - if err != nil { - return err - } + clientID := anchorCli.ID() r.clients[clientID] = anchorCli return nil @@ -82,8 +87,8 @@ func NewAnchor(url string, vm VM) *Anchor { } } -func (a *Anchor) ID() (ids.ID, error) { - return ids.ToID([]byte(a.Url)) +func (a *Anchor) ID() ids.ID { + return utils.ToID([]byte(a.Namespace + a.Url)) } // only the Anchor provide the signature signed by the same key the validator has will be accepted diff --git a/chain/block.go b/chain/block.go index 8dd1063e6b..df1f090a49 100644 --- a/chain/block.go +++ b/chain/block.go @@ -43,6 +43,8 @@ type StatefulBlock struct { Height uint64 `json:"height"` Timestamp int64 `json:"timestamp"` + Anchors []*Anchor `json:"anchors"` + // AvailableChunks is a collection of valid Chunks that will be executed in // the future. AvailableChunks []*ChunkCertificate `json:"availableChunks"` @@ -50,8 +52,6 @@ type StatefulBlock struct { ExecutedChunks []ids.ID `json:"executedChunks"` Checksum ids.ID `json:"checksum"` - AnchorRegistrations []*Anchor `json:"anchorRegistrations"` - built bool } @@ -78,6 +78,13 @@ func (b *StatefulBlock) Marshal() ([]byte, error) { p.PackUint64(b.Height) p.PackInt64(b.Timestamp) + p.PackInt(len(b.Anchors)) + for _, anchor := range b.Anchors { + if err := anchor.Marshal(p); err != nil { + return nil, err + } + } + p.PackInt(len(b.AvailableChunks)) for _, cert := range b.AvailableChunks { if err := cert.MarshalPacker(p); err != nil { @@ -110,6 +117,16 @@ func UnmarshalBlock(raw []byte) (*StatefulBlock, error) { b.Height = p.UnpackUint64(false) b.Timestamp = p.UnpackInt64(false) + numAnchors := p.UnpackInt(false) + b.Anchors = make([]*Anchor, 0, 16) + for i := 0; i < numAnchors; i++ { + anchor, err := UnmarshalAnchor(p) + if err != nil { + return nil, err + } + b.Anchors = append(b.Anchors, anchor) + } + // Parse available chunks availableChunks := p.UnpackInt(false) // can produce empty blocks b.AvailableChunks = make([]*ChunkCertificate, 0, 16) // don't preallocate all to avoid DoS @@ -508,7 +525,11 @@ func (b *StatelessBlock) Accept(ctx context.Context) error { return fmt.Errorf("%w: cannot prune results", err) } filteredChunks = fc - b.AnchorRegistrations = anchors // new registered anchors is at current block height - 3 + b.Anchors = anchors + b.vm.Logger().Debug("anchors of block", zap.Uint64("blockHeight", b.Height()), zap.Int("numAnchors", len(anchors))) + for _, anchor := range anchors { + b.vm.Logger().Debug("anchor info", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + } } // Notify the VM that the block has been accepted diff --git a/chain/chunk.go b/chain/chunk.go index 5188574af3..d67fbd3a64 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -27,6 +27,74 @@ type Anchor struct { BlockType int `json:"blockType"` // use to determine if it is TOB or ROB Namespace string `json:"namespace"` Url string `json:"url"` + + bytes []byte +} + +func (a *Anchor) Size() int { + return consts.IntLen + codec.StringLen(a.Namespace) + codec.StringLen(a.Url) +} + +func (a *Anchor) Marshal(p *codec.Packer) error { + if len(a.bytes) > 0 { + p.PackFixedBytes(a.bytes) + return p.Err() + } + + p.PackInt(a.BlockType) + p.PackString(a.Namespace) + p.PackString(a.Url) + + return p.Err() +} + +func UnmarshalAnchor(p *codec.Packer) (*Anchor, error) { + ret := new(Anchor) + ret.BlockType = p.UnpackInt(false) + ret.Namespace = p.UnpackString(false) + ret.Url = p.UnpackString(false) + + if err := p.Err(); err != nil { + return nil, p.Err() + } + + return ret, nil +} + +func MarshalAnchors(anchors []*Anchor) ([]byte, error) { + size := consts.IntLen + for _, a := range anchors { + size += a.Size() + } + p := codec.NewWriter(size, consts.NetworkSizeLimit) + + p.PackInt(len(anchors)) + for _, a := range anchors { + if err := a.Marshal(p); err != nil { + return nil, err + } + } + + return p.Bytes(), p.Err() +} + +func UnmarshalAnchors(raw []byte) ([]*Anchor, error) { + p := codec.NewReader(raw, consts.NetworkSizeLimit) + numAnchors := p.UnpackInt(false) + ret := make([]*Anchor, 0, numAnchors) + for i := 0; i < numAnchors; i++ { + a, err := UnmarshalAnchor(p) + if err != nil { + return nil, err + } + ret = append(ret, a) + } + + if p.Err() != nil { + return nil, p.Err() + } + + return ret, nil } type Chunk struct { @@ -368,8 +436,7 @@ func (c *Chunk) Digest() ([]byte, error) { p.PackBool(c.Anchor != nil) if c.Anchor != nil { - p.PackInt(c.Anchor.BlockType) - p.PackString(c.Anchor.Namespace) + c.Anchor.Marshal(p) } // Marshal transactions p.PackInt64(c.Slot) @@ -449,8 +516,9 @@ func (c *Chunk) Marshal() ([]byte, error) { p.PackBool(isAnchorChunk) fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) if isAnchorChunk { - p.PackInt(c.Anchor.BlockType) - p.PackString(c.Anchor.Namespace) + if err := c.Anchor.Marshal(p); err != nil { + return nil, err + } } bytes, err := p.Bytes(), p.Err() @@ -525,13 +593,11 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { isAnchorChunk := p.UnpackBool() fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) if isAnchorChunk { - blockType := p.UnpackInt(false) - namespace := p.UnpackString(false) - anchor := Anchor{ - BlockType: blockType, - Namespace: namespace, + anchor, err := UnmarshalAnchor(p) + if err != nil { + return nil, err } - c.Anchor = &anchor + c.Anchor = anchor } // Ensure no leftover bytes diff --git a/chain/engine.go b/chain/engine.go index 6bdf251af2..284e14a78e 100644 --- a/chain/engine.go +++ b/chain/engine.go @@ -122,7 +122,7 @@ func (e *Engine) processJob(batch *vilmo.Batch, job *engineJob) error { p.Add(ctx, len(chunks), chunk) chunks = append(chunks, chunk) } - txSet, ts, chunkResults, newAnchors, err := p.Wait() + txSet, ts, chunkResults, anchors, err := p.Wait() if err != nil { e.vm.Logger().Fatal("chunk processing failed", zap.Error(err)) // does not actually panic return err @@ -313,8 +313,16 @@ func (e *Engine) processJob(batch *vilmo.Batch, job *engineJob) error { chunks: filteredChunks, checksum: checksum, - anchors: newAnchors, + anchors: anchors, } + + if len(anchors) != 0 { + log.Debug("anchor list", zap.Uint64("blkHeight", job.blk.StatefulBlock.Height), zap.Int("numAnchors", len(anchors))) + for _, anchor := range anchors { + log.Debug("anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + } + } + e.largestOutput = &job.blk.StatefulBlock.Height e.outputsLock.Unlock() diff --git a/chain/processor.go b/chain/processor.go index 3aa1e45b12..e27688413b 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -2,11 +2,14 @@ package chain import ( "context" + "encoding/hex" "fmt" "time" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/executor" "github.com/ava-labs/hypersdk/opool" "github.com/ava-labs/hypersdk/state" @@ -36,7 +39,8 @@ type Processor struct { txs map[ids.ID]*blockLoc results [][]*Result - anchors map[string]*Anchor + + anchors []*Anchor // TODO: track frozen sponsors @@ -83,6 +87,7 @@ func NewProcessor( txs: make(map[ids.ID]*blockLoc, numTxs), results: make([][]*Result, chunks), + anchors: make([]*Anchor, 0), } } @@ -350,11 +355,35 @@ func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, [ if err := p.executor.Wait(); err != nil { return nil, nil, nil, nil, fmt.Errorf("%w: processor failed", err) } - anchors := make([]*Anchor, 0, len(p.anchors)) - for _, anchor := range p.anchors { - anchors = append(anchors, anchor) + + nsRaw, err := p.im.Get(context.TODO(), actions.AnchorRegistryKey()) + switch err { + case database.ErrNotFound: + p.anchors = nil + case nil: + namespaces, err := actions.UnpackNamespaces(nsRaw) + if err != nil { + return nil, nil, nil, nil, err + } + for _, ns := range namespaces { + url, err := p.im.Get(context.TODO(), actions.AnchorKey(ns)) + if err != nil { + // should never happen since url and namespace are paired, should be created & deleted the same time + return nil, nil, nil, nil, err + } + + anchor := Anchor{ + Url: string(url), + Namespace: hex.EncodeToString(ns), + BlockType: -1, + } + p.vm.Logger().Debug("anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + p.anchors = append(p.anchors, &anchor) + } + default: + return nil, nil, nil, nil, fmt.Errorf("state: %+v", err) } p.vm.RecordWaitExec(time.Since(exectutorStart)) - return p.txs, p.ts, p.results, anchors, nil + return p.txs, p.ts, p.results, p.anchors, nil } diff --git a/examples/morpheusvm/actions/anchorreg.go b/examples/morpheusvm/actions/anchorreg.go index e03a494fed..81ccf5316d 100644 --- a/examples/morpheusvm/actions/anchorreg.go +++ b/examples/morpheusvm/actions/anchorreg.go @@ -10,10 +10,10 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/platformvm/warp" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/consts" - mconsts "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" "github.com/ava-labs/hypersdk/examples/morpheusvm/storage" "github.com/ava-labs/hypersdk/state" "github.com/ava-labs/hypersdk/utils" @@ -28,7 +28,7 @@ type AnchorRegister struct { } func (*AnchorRegister) GetTypeID() uint8 { - return mconsts.AnchorRegisterID + return hactions.AnchorRegisterID } func (t *AnchorRegister) StateKeys(actor codec.Address, _ ids.ID) state.Keys { diff --git a/examples/morpheusvm/consts/types.go b/examples/morpheusvm/consts/types.go index 10fca3b941..e9f8c26e5c 100644 --- a/examples/morpheusvm/consts/types.go +++ b/examples/morpheusvm/consts/types.go @@ -3,11 +3,13 @@ package consts +import hactions "github.com/ava-labs/hypersdk/actions" + const ( // Action TypeIDs TransferID uint8 = 0 MsgID uint8 = 1 - AnchorRegisterID uint8 = 2 + AnchorRegisterID uint8 = hactions.AnchorRegisterID // Auth TypeIDs ED25519ID uint8 = 0 SECP256R1ID uint8 = 1 diff --git a/examples/morpheusvm/scripts/run.sh b/examples/morpheusvm/scripts/run.sh index a8cc7cbe7d..1677a30869 100755 --- a/examples/morpheusvm/scripts/run.sh +++ b/examples/morpheusvm/scripts/run.sh @@ -20,7 +20,7 @@ fi AGO_VERSION=v1.11.3 MAX_UINT64=18446744073709551615 MODE=${MODE:-run} -LOG_LEVEL=${LOG_LEVEL:-INFO} +LOG_LEVEL=${LOG_LEVEL:-DEBUG} AGO_LOG_LEVEL=${AGO_LOG_LEVEL:-INFO} AGO_LOG_DISPLAY_LEVEL=${AGO_LOG_DISPLAY_LEVEL:-INFO} EPOCH_DURATION=${EPOCH_DURATION:-10000} diff --git a/examples/morpheusvm/storage/storage.go b/examples/morpheusvm/storage/storage.go index 31d9ee81fe..a4f06881a2 100644 --- a/examples/morpheusvm/storage/storage.go +++ b/examples/morpheusvm/storage/storage.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" smath "github.com/ava-labs/avalanchego/utils/math" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/consts" @@ -44,16 +45,18 @@ const ( txPrefix = 0x0 // stateDB - balancePrefix = 0x0 - heightPrefix = 0x1 - pHeightPrefix = 0x2 - timestampPrefix = 0x3 - feePrefix = 0x4 - incomingWarpPrefix = 0x5 - outgoingWarpPrefix = 0x6 - epochPrefix = 0x7 - anchorRegisteryPrefix = 0x8 - anchorPrefix = 0x9 + balancePrefix = 0x0 + heightPrefix = 0x1 + pHeightPrefix = 0x2 + timestampPrefix = 0x3 + feePrefix = 0x4 + incomingWarpPrefix = 0x5 + outgoingWarpPrefix = 0x6 + epochPrefix = 0x7 + + // anchor related prefixs, see hypersdk/actions + // anchorRegistryPrefix = 0xf0 + // anchorPrefix = 0xf1 ) const BalanceChunks uint16 = 1 @@ -286,33 +289,21 @@ func EpochKey(epoch uint64) string { } func AnchorRegistryKey() string { - // state key must >= 2 bytes - k := make([]byte, 1+consts.Uint16Len) - k[0] = anchorRegisteryPrefix - binary.BigEndian.PutUint16(k[1:], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks - return string(k) + return hactions.AnchorRegistryKey() + + // // state key must >= 2 bytes + // k := make([]byte, 1+consts.Uint16Len) + // k[0] = anchorRegisteryPrefix + // binary.BigEndian.PutUint16(k[1:], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks + // return string(k) } func PackNamespaces(namespaces [][]byte) ([]byte, error) { - p := codec.NewWriter(len(namespaces)*8, consts.NetworkSizeLimit) - p.PackInt(len(namespaces)) - for _, ns := range namespaces { - p.PackBytes(ns) - } - return p.Bytes(), p.Err() + return hactions.PackNamespaces(namespaces) } func UnpackNamespaces(raw []byte) ([][]byte, error) { - p := codec.NewReader(raw, consts.NetworkSizeLimit) - nsLen := p.UnpackInt(false) - namespaces := make([][]byte, 0, nsLen) - for i := 0; i < nsLen; i++ { - ns := make([]byte, 0, 8) - p.UnpackBytes(-1, false, &ns) - namespaces = append(namespaces, ns) - } - - return namespaces, p.Err() + return hactions.UnpackNamespaces(raw) } func GetAnchors( @@ -409,11 +400,12 @@ func setAnchors( } func AnchorKey(namespace []byte) string { - k := make([]byte, 1+len(namespace)+consts.Uint16Len) - k[0] = anchorPrefix - copy(k[1:], namespace[:]) - binary.BigEndian.PutUint16(k[1+len(namespace):], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks - return string(k) + return hactions.AnchorKey(namespace) + // k := make([]byte, 1+len(namespace)+consts.Uint16Len) + // k[0] = anchorPrefix + // copy(k[1:], namespace[:]) + // binary.BigEndian.PutUint16(k[1+len(namespace):], BalanceChunks) //TODO: update the BalanceChunks to AnchorChunks + // return string(k) } // If locked is 0, then account does not exist diff --git a/vm/resolutions.go b/vm/resolutions.go index af092ae351..6e3043dc7f 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -361,13 +361,19 @@ func (vm *VM) Accepted(ctx context.Context, b *chain.StatelessBlock, chunks []*c vm.Fatal("unable to update last accepted", zap.Error(err)) } - for _, anchor := range b.AnchorRegistrations { - vm.anchorRegistry.Register(anchor.Url, anchor.Namespace) - } - // Cleanup expired chunks we are tracking and chunk certificates vm.cm.SetBuildableMin(ctx, b.StatefulBlock.Timestamp) // clear unnecessary certs + vm.anchorRegistry.Reset() + for _, anchor := range b.Anchors { + if err := vm.anchorRegistry.Register(anchor.Url, anchor.Namespace); err != nil { + vm.Logger().Error("unable to register anchor", zap.Error(err)) + continue + } + + vm.Logger().Debug("registered anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + } + // Remove from verified caches // // We do this after setting [lastAccepted] to avoid From 5cc096090c2f5b88f9ba61106c89278afe7d0400 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Tue, 20 Aug 2024 09:58:45 -0400 Subject: [PATCH 15/18] anchor info registration --- actions/structs.go | 52 +++++ anchor/anchor.go | 108 +---------- anchor/dependencies.go | 2 +- anchor/registry.go | 36 ++++ chain/block.go | 9 +- chain/chunk.go | 58 +++--- chain/engine.go | 7 +- chain/processor.go | 34 ++-- examples/morpheusvm/actions/anchorreg.go | 56 ++++-- .../morpheusvm/cmd/morpheus-cli/cmd/action.go | 15 +- .../morpheusvm/cmd/morpheus-cli/cmd/chain.go | 4 +- examples/morpheusvm/controller/resolutions.go | 4 +- examples/morpheusvm/rpc/dependencies.go | 3 +- examples/morpheusvm/rpc/jsonrpc_client.go | 5 +- examples/morpheusvm/rpc/jsonrpc_server.go | 9 +- examples/morpheusvm/storage/storage.go | 60 +++--- vm/chunk_manager.go | 181 +++++++++--------- vm/resolutions.go | 11 +- 18 files changed, 341 insertions(+), 313 deletions(-) create mode 100644 actions/structs.go create mode 100644 anchor/registry.go diff --git a/actions/structs.go b/actions/structs.go new file mode 100644 index 0000000000..8ac5c11ca0 --- /dev/null +++ b/actions/structs.go @@ -0,0 +1,52 @@ +package actions + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/utils" +) + +// TODO: do we need to rename it to `RollupInfo` +type AnchorInfo struct { + FeeRecipient codec.Address `json:"feeRecipient"` + Namespace []byte `json:"namespace"` +} + +func NewAnchorInfo(namespace []byte, feeRecipient codec.Address) *AnchorInfo { + return &AnchorInfo{ + FeeRecipient: feeRecipient, + Namespace: namespace, + } +} + +func (a *AnchorInfo) ID() ids.ID { + return utils.ToID([]byte(a.Namespace)) +} + +func (a *AnchorInfo) Size() int { + return codec.AddressLen + codec.BytesLen(a.Namespace) +} + +func (a *AnchorInfo) Marshal(p *codec.Packer) error { + p.PackBytes(a.Namespace) + p.PackAddress(a.FeeRecipient) + + if err := p.Err(); err != nil { + return err + } + + return nil +} + +func UnmarshalAnchorInfo(p *codec.Packer) (*AnchorInfo, error) { + ret := new(AnchorInfo) + + // p := codec.NewReader(raw, consts.NetworkSizeLimit) + p.UnpackBytes(32, false, &ret.Namespace) // TODO: set limit for the length of namespace bytes + p.UnpackAddress(&ret.FeeRecipient) + + if err := p.Err(); err != nil { + return nil, err + } + return ret, nil +} diff --git a/anchor/anchor.go b/anchor/anchor.go index 73b4c581fa..c71f5f75d0 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,109 +1,3 @@ package anchor -import ( - "slices" - "strings" - "sync" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/hypersdk/chain" - "github.com/ava-labs/hypersdk/codec" - "github.com/ava-labs/hypersdk/utils" -) - -type AnchorRegistry struct { - clients map[ids.ID]*Anchor - clientsL sync.Mutex - vm VM -} - -func NewAnchorRegistry(vm VM) *AnchorRegistry { - return &AnchorRegistry{ - vm: vm, - } -} - -func (r *AnchorRegistry) Reset() { - r.clientsL.Lock() - defer r.clientsL.Unlock() - - r.clients = make(map[ids.ID]*Anchor) -} - -func (r *AnchorRegistry) Register(url string, namespace string) error { - anchorCli := &Anchor{ - Url: url, - vm: r.vm, - Namespace: namespace, - } - clientID := anchorCli.ID() - - r.clients[clientID] = anchorCli - return nil -} - -func (r *AnchorRegistry) Remove(url string) error { - r.clientsL.Lock() - defer r.clientsL.Unlock() - - cilentID, err := ids.ToID([]byte(url)) - if err != nil { - return err - } - - delete(r.clients, cilentID) - return nil -} - -func (r *AnchorRegistry) Len() int { - return len(r.clients) -} - -func (r *AnchorRegistry) SortedAnchors() []*Anchor { - anchors := make([]*Anchor, 0, len(r.clients)) - for _, anchor := range r.clients { - anchors = append(anchors, anchor) - } - - slices.SortFunc(anchors, func(a, b *Anchor) int { - return strings.Compare(a.Url, b.Url) - }) - - return anchors -} - -type Anchor struct { - vm VM - Url string `json:"url"` - UrlL sync.Mutex - Namespace string `json:"namespace"` -} - -func NewAnchor(url string, vm VM) *Anchor { - return &Anchor{ - Url: url, - vm: vm, - } -} - -func (a *Anchor) ID() ids.ID { - return utils.ToID([]byte(a.Namespace + a.Url)) -} - -// only the Anchor provide the signature signed by the same key the validator has will be accepted -func (a *Anchor) Replace(url string) { - a.UrlL.Lock() - defer a.UrlL.Unlock() - - a.Url = url -} - -func (a *Anchor) RequestAnchorDigest() ([]byte, error) { - return nil, nil -} - -// returns Slot, Txs, FeeReceiver, error -func (a *Anchor) RequestAnchorChunk(sig *bls.Signature) (*chain.Anchor, int64, []*chain.Transaction, codec.Address, error) { - return nil, 0, nil, codec.EmptyAddress, nil -} +// TODO: this file to define anchor client diff --git a/anchor/dependencies.go b/anchor/dependencies.go index 3185fc8521..2e8831544f 100644 --- a/anchor/dependencies.go +++ b/anchor/dependencies.go @@ -8,6 +8,6 @@ import ( ) type VM interface { - HandleAnchorChunk(ctx context.Context, meta *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error + HandleAnchorChunk(ctx context.Context, meta *chain.AnchorMeta, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error SignAnchorDigest(ctx context.Context, digest []byte) ([]byte, error) } diff --git a/anchor/registry.go b/anchor/registry.go new file mode 100644 index 0000000000..edbc429bfd --- /dev/null +++ b/anchor/registry.go @@ -0,0 +1,36 @@ +package anchor + +import ( + "sync" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/actions" +) + +type AnchorRegistry struct { + anchors map[ids.ID]*actions.AnchorInfo + anchorsL sync.Mutex + vm VM +} + +func NewAnchorRegistry(vm VM) *AnchorRegistry { + return &AnchorRegistry{ + vm: vm, + anchors: make(map[ids.ID]*actions.AnchorInfo), + } +} + +func (r *AnchorRegistry) Update(info []*actions.AnchorInfo) { + r.anchorsL.Lock() + defer r.anchorsL.Unlock() + + r.anchors = make(map[ids.ID]*actions.AnchorInfo, len(info)) + for _, a := range info { + id := a.ID() + r.anchors[id] = a + } +} + +func (r *AnchorRegistry) Len() int { + return len(r.anchors) +} diff --git a/chain/block.go b/chain/block.go index df1f090a49..3eae77a05e 100644 --- a/chain/block.go +++ b/chain/block.go @@ -19,6 +19,7 @@ import ( oteltrace "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/utils" @@ -43,7 +44,7 @@ type StatefulBlock struct { Height uint64 `json:"height"` Timestamp int64 `json:"timestamp"` - Anchors []*Anchor `json:"anchors"` + Anchors []*actions.AnchorInfo `json:"anchors"` // AvailableChunks is a collection of valid Chunks that will be executed in // the future. @@ -118,9 +119,9 @@ func UnmarshalBlock(raw []byte) (*StatefulBlock, error) { b.Timestamp = p.UnpackInt64(false) numAnchors := p.UnpackInt(false) - b.Anchors = make([]*Anchor, 0, 16) + b.Anchors = make([]*actions.AnchorInfo, 0, 16) // prevent DoS for i := 0; i < numAnchors; i++ { - anchor, err := UnmarshalAnchor(p) + anchor, err := actions.UnmarshalAnchorInfo(p) if err != nil { return nil, err } @@ -528,7 +529,7 @@ func (b *StatelessBlock) Accept(ctx context.Context) error { b.Anchors = anchors b.vm.Logger().Debug("anchors of block", zap.Uint64("blockHeight", b.Height()), zap.Int("numAnchors", len(anchors))) for _, anchor := range anchors { - b.vm.Logger().Debug("anchor info", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + b.vm.Logger().Debug("anchor info", zap.ByteString("namespace", anchor.Namespace), zap.String("feeRecipient", string(anchor.FeeRecipient[:]))) } } diff --git a/chain/chunk.go b/chain/chunk.go index d67fbd3a64..64ec15ae3d 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -23,7 +23,7 @@ const ( AnchorRoB ) -type Anchor struct { +type AnchorMeta struct { BlockType int `json:"blockType"` // use to determine if it is TOB or ROB Namespace string `json:"namespace"` Url string `json:"url"` @@ -31,11 +31,11 @@ type Anchor struct { bytes []byte } -func (a *Anchor) Size() int { +func (a *AnchorMeta) Size() int { return consts.IntLen + codec.StringLen(a.Namespace) + codec.StringLen(a.Url) } -func (a *Anchor) Marshal(p *codec.Packer) error { +func (a *AnchorMeta) Marshal(p *codec.Packer) error { if len(a.bytes) > 0 { p.PackFixedBytes(a.bytes) return p.Err() @@ -48,8 +48,8 @@ func (a *Anchor) Marshal(p *codec.Packer) error { return p.Err() } -func UnmarshalAnchor(p *codec.Packer) (*Anchor, error) { - ret := new(Anchor) +func UnmarshalAnchorMeta(p *codec.Packer) (*AnchorMeta, error) { + ret := new(AnchorMeta) ret.BlockType = p.UnpackInt(false) ret.Namespace = p.UnpackString(false) ret.Url = p.UnpackString(false) @@ -61,7 +61,7 @@ func UnmarshalAnchor(p *codec.Packer) (*Anchor, error) { return ret, nil } -func MarshalAnchors(anchors []*Anchor) ([]byte, error) { +func MarshalAnchorMetas(anchors []*AnchorMeta) ([]byte, error) { size := consts.IntLen for _, a := range anchors { size += a.Size() @@ -78,12 +78,12 @@ func MarshalAnchors(anchors []*Anchor) ([]byte, error) { return p.Bytes(), p.Err() } -func UnmarshalAnchors(raw []byte) ([]*Anchor, error) { +func UnmarshalAnchorMetas(raw []byte) ([]*AnchorMeta, error) { p := codec.NewReader(raw, consts.NetworkSizeLimit) - numAnchors := p.UnpackInt(false) - ret := make([]*Anchor, 0, numAnchors) - for i := 0; i < numAnchors; i++ { - a, err := UnmarshalAnchor(p) + numAnchorMetas := p.UnpackInt(false) + ret := make([]*AnchorMeta, 0, numAnchorMetas) + for i := 0; i < numAnchorMetas; i++ { + a, err := UnmarshalAnchorMeta(p) if err != nil { return nil, err } @@ -98,7 +98,7 @@ func UnmarshalAnchors(raw []byte) ([]*Anchor, error) { } type Chunk struct { - Anchor *Anchor `json:"anchor"` // if null then the chunk is generated from txs in mempool + AnchorMeta *AnchorMeta `json:"anchor"` // if null then the chunk is generated from txs in mempool Slot int64 `json:"slot"` // rounded to nearest 100ms Txs []*Transaction `json:"txs"` @@ -116,7 +116,7 @@ type Chunk struct { authCounts map[uint8]int } -func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *Anchor, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { +func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *AnchorMeta, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance sm := vm.StateManager() @@ -434,9 +434,9 @@ func (c *Chunk) Digest() ([]byte, error) { size := consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + bls.PublicKeyLen p := codec.NewWriter(size, consts.NetworkSizeLimit) - p.PackBool(c.Anchor != nil) - if c.Anchor != nil { - c.Anchor.Marshal(p) + p.PackBool(c.AnchorMeta != nil) + if c.AnchorMeta != nil { + c.AnchorMeta.Marshal(p) } // Marshal transactions p.PackInt64(c.Slot) @@ -462,10 +462,10 @@ func (c *Chunk) ID() ids.ID { func (c *Chunk) Size() int { size := consts.BoolLen + consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + codec.AddressLen + bls.PublicKeyLen + bls.SignatureLen - isAnchor := c.Anchor != nil - if isAnchor { + isAnchorMeta := c.AnchorMeta != nil + if isAnchorMeta { size += consts.IntLen - size += codec.StringLen(c.Anchor.Namespace) + size += codec.StringLen(c.AnchorMeta.Namespace) } return size } @@ -512,11 +512,11 @@ func (c *Chunk) Marshal() ([]byte, error) { p.PackFixedBytes(bls.PublicKeyToCompressedBytes(c.Signer)) p.PackFixedBytes(bls.SignatureToBytes(c.Signature)) - isAnchorChunk := c.Anchor != nil - p.PackBool(isAnchorChunk) - fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) - if isAnchorChunk { - if err := c.Anchor.Marshal(p); err != nil { + isAnchorMetaChunk := c.AnchorMeta != nil + p.PackBool(isAnchorMetaChunk) + fmt.Printf("anchor chunk: %+v\n", isAnchorMetaChunk) + if isAnchorMetaChunk { + if err := c.AnchorMeta.Marshal(p); err != nil { return nil, err } } @@ -590,14 +590,14 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { } c.Signature = signature - isAnchorChunk := p.UnpackBool() - fmt.Printf("anchor chunk: %+v\n", isAnchorChunk) - if isAnchorChunk { - anchor, err := UnmarshalAnchor(p) + isAnchorMetaChunk := p.UnpackBool() + fmt.Printf("anchor chunk: %+v\n", isAnchorMetaChunk) + if isAnchorMetaChunk { + anchor, err := UnmarshalAnchorMeta(p) if err != nil { return nil, err } - c.Anchor = anchor + c.AnchorMeta = anchor } // Ensure no leftover bytes diff --git a/chain/engine.go b/chain/engine.go index 284e14a78e..53fb36a182 100644 --- a/chain/engine.go +++ b/chain/engine.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/maybe" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/utils" "github.com/ava-labs/hypersdk/vilmo" @@ -32,7 +33,7 @@ type output struct { chunks []*FilteredChunk checksum ids.ID - anchors []*Anchor + anchors []*actions.AnchorInfo } // Engine is in charge of orchestrating the execution of @@ -319,7 +320,7 @@ func (e *Engine) processJob(batch *vilmo.Batch, job *engineJob) error { if len(anchors) != 0 { log.Debug("anchor list", zap.Uint64("blkHeight", job.blk.StatefulBlock.Height), zap.Int("numAnchors", len(anchors))) for _, anchor := range anchors { - log.Debug("anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + log.Debug("anchor", zap.String("namespace", string(anchor.Namespace)), zap.ByteString("feeRecipient", anchor.FeeRecipient[:])) } } @@ -417,7 +418,7 @@ func (e *Engine) Results(height uint64) ([]ids.ID /* Executed Chunks */, ids.ID return nil, ids.Empty, fmt.Errorf("%w: results not found for %d", errors.New("not found"), height) } -func (e *Engine) PruneResults(ctx context.Context, height uint64) ([][]*Result, []*FilteredChunk, []*Anchor, error) { +func (e *Engine) PruneResults(ctx context.Context, height uint64) ([][]*Result, []*FilteredChunk, []*actions.AnchorInfo, error) { e.outputsLock.Lock() defer e.outputsLock.Unlock() diff --git a/chain/processor.go b/chain/processor.go index e27688413b..66323939e9 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -2,7 +2,6 @@ package chain import ( "context" - "encoding/hex" "fmt" "time" @@ -10,6 +9,8 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/hypersdk/actions" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/executor" "github.com/ava-labs/hypersdk/opool" "github.com/ava-labs/hypersdk/state" @@ -40,7 +41,7 @@ type Processor struct { txs map[ids.ID]*blockLoc results [][]*Result - anchors []*Anchor + anchors []*actions.AnchorInfo // TODO: track frozen sponsors @@ -87,7 +88,7 @@ func NewProcessor( txs: make(map[ids.ID]*blockLoc, numTxs), results: make([][]*Result, chunks), - anchors: make([]*Anchor, 0), + anchors: make([]*actions.AnchorInfo, 0), } } @@ -224,8 +225,8 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { } // constraint on only allowing one L2 block per SEQ block - if chunk.Anchor != nil { - switch chunk.Anchor.BlockType { + if chunk.AnchorMeta != nil { + switch chunk.AnchorMeta.BlockType { case AnchorToB: if _, exists := p.acceptedNS["TOB"]; exists { p.markChunkTxsInvalid(chunkIndex, chunkTxs) @@ -233,11 +234,11 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { } p.acceptedNS["TOB"] = struct{}{} case AnchorRoB: - if _, exists := p.acceptedNS[chunk.Anchor.Namespace]; exists { + if _, exists := p.acceptedNS[chunk.AnchorMeta.Namespace]; exists { p.markChunkTxsInvalid(chunkIndex, chunkTxs) return } - p.acceptedNS[chunk.Anchor.Namespace] = struct{}{} + p.acceptedNS[chunk.AnchorMeta.Namespace] = struct{}{} } } @@ -312,7 +313,7 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { // If this passes, we know that latest pHeight must be non-nil // Check that transaction is in right partition - if chunk.Anchor == nil { // from mempool + if chunk.AnchorMeta == nil { // from mempool parition, err := p.vm.AddressPartition(ctx, txEpoch, *epochHeight, tx.Sponsor(), tx.Partition()) if err != nil { p.vm.Logger().Warn("unable to compute tx partition", zap.Stringer("txID", tx.ID()), zap.Error(err)) @@ -342,7 +343,7 @@ func (p *Processor) Add(ctx context.Context, chunkIndex int, chunk *Chunk) { p.queueWait += time.Since(queueStart) } -func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, []*Anchor, error) { +func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, []*actions.AnchorInfo, error) { p.vm.RecordWaitRepeat(p.repeatWait) p.vm.RecordWaitQueue(p.queueWait) p.vm.RecordWaitAuth(p.authWait) // we record once so we can see how much of a block was spend waiting (this is not the same as the total time) @@ -366,19 +367,20 @@ func (p *Processor) Wait() (map[ids.ID]*blockLoc, *tstate.TState, [][]*Result, [ return nil, nil, nil, nil, err } for _, ns := range namespaces { - url, err := p.im.Get(context.TODO(), actions.AnchorKey(ns)) + info, err := p.im.Get(context.TODO(), actions.AnchorKey(ns)) if err != nil { // should never happen since url and namespace are paired, should be created & deleted the same time return nil, nil, nil, nil, err } - anchor := Anchor{ - Url: string(url), - Namespace: hex.EncodeToString(ns), - BlockType: -1, + packer := codec.NewReader(info, consts.NetworkSizeLimit) + anchorInfo, err := actions.UnmarshalAnchorInfo(packer) + if err != nil { + return nil, nil, nil, nil, err } - p.vm.Logger().Debug("anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) - p.anchors = append(p.anchors, &anchor) + + p.vm.Logger().Debug("anchor", zap.ByteString("namespace", anchorInfo.Namespace), zap.Any("info", anchorInfo)) + p.anchors = append(p.anchors, anchorInfo) } default: return nil, nil, nil, nil, fmt.Errorf("state: %+v", err) diff --git a/examples/morpheusvm/actions/anchorreg.go b/examples/morpheusvm/actions/anchorreg.go index 81ccf5316d..685f53d441 100644 --- a/examples/morpheusvm/actions/anchorreg.go +++ b/examples/morpheusvm/actions/anchorreg.go @@ -6,6 +6,8 @@ package actions import ( "bytes" "context" + "encoding/hex" + "fmt" "slices" "github.com/ava-labs/avalanchego/ids" @@ -21,10 +23,16 @@ import ( var _ chain.Action = (*AnchorRegister)(nil) +const ( + CreateAnchor = iota + DeleteAnchor + UpdateAnchor +) + type AnchorRegister struct { - Url string `json:"url"` - Namespace []byte `json:"namespace"` - Delete bool `json:"delete"` + Info hactions.AnchorInfo `json:"info"` + Namespace []byte `json:"namespace"` + OpCode int `json:"opcode"` } func (*AnchorRegister) GetTypeID() uint8 { @@ -39,7 +47,7 @@ func (t *AnchorRegister) StateKeys(actor codec.Address, _ ids.ID) state.Keys { } func (*AnchorRegister) StateKeyChunks() []uint16 { - return []uint16{storage.BalanceChunks, storage.BalanceChunks} + return []uint16{hactions.AnchorChunks, hactions.AnchorChunks} } func (*AnchorRegister) OutputsWarpMessage() bool { @@ -55,12 +63,27 @@ func (t *AnchorRegister) Execute( _ ids.ID, _ bool, ) (bool, []byte, *warp.UnsignedMessage, error) { + if !bytes.Equal(t.Namespace, t.Info.Namespace) { + return false, utils.ErrBytes(fmt.Errorf("provided namespace(%s) not match to the one(%s) in anchor info", hex.EncodeToString(t.Namespace), hex.EncodeToString(t.Info.Namespace))), nil, nil + } + namespaces, _, err := storage.GetAnchors(ctx, mu) if err != nil { return false, utils.ErrBytes(err), nil, nil } - if t.Delete { + switch t.OpCode { + case CreateAnchor: + namespaces = append(namespaces, t.Namespace) + if err := storage.SetAnchor(ctx, mu, t.Namespace, &t.Info); err != nil { + return false, utils.ErrBytes(err), nil, nil + } + case UpdateAnchor: + namespaces = append(namespaces, t.Namespace) + if err := storage.SetAnchor(ctx, mu, t.Namespace, &t.Info); err != nil { + return false, utils.ErrBytes(err), nil, nil + } + case DeleteAnchor: nsIdx := -1 for i, ns := range namespaces { if bytes.Equal(t.Namespace, ns) { @@ -72,15 +95,14 @@ func (t *AnchorRegister) Execute( if err := storage.DelAnchor(ctx, mu, t.Namespace); err != nil { return false, utils.ErrBytes(err), nil, nil } - } else { - namespaces = append(namespaces, t.Namespace) - if err := storage.SetAnchor(ctx, mu, t.Namespace, t.Url); err != nil { - return false, utils.ErrBytes(err), nil, nil - } + default: + return false, utils.ErrBytes(fmt.Errorf("op code(%d) not supported", t.OpCode)), nil, nil } + if err := storage.SetAnchors(ctx, mu, namespaces); err != nil { return false, utils.ErrBytes(err), nil, nil } + return true, nil, nil, nil } @@ -89,20 +111,24 @@ func (*AnchorRegister) ComputeUnits(chain.Rules) uint64 { } func (t *AnchorRegister) Size() int { - return codec.BytesLen(t.Namespace) + codec.StringLen(t.Url) + consts.BoolLen + return codec.BytesLen(t.Namespace) + codec.AddressLen + consts.BoolLen } func (t *AnchorRegister) Marshal(p *codec.Packer) { + t.Info.Marshal(p) p.PackBytes(t.Namespace) - p.PackString(t.Url) - p.PackBool(t.Delete) + p.PackInt(t.OpCode) } func UnmarshalAnchorRegister(p *codec.Packer, _ *warp.Message) (chain.Action, error) { var anchorReg AnchorRegister + info, err := hactions.UnmarshalAnchorInfo(p) + if err != nil { + return nil, err + } + anchorReg.Info = *info p.UnpackBytes(-1, false, &anchorReg.Namespace) - anchorReg.Url = p.UnpackString(false) - anchorReg.Delete = p.UnpackBool() + anchorReg.OpCode = p.UnpackInt(false) return &anchorReg, nil } diff --git a/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go b/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go index 8881526b37..c874e4c95d 100644 --- a/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go +++ b/examples/morpheusvm/cmd/morpheus-cli/cmd/action.go @@ -6,6 +6,7 @@ package cmd import ( "context" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/examples/morpheusvm/actions" "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" "github.com/spf13/cobra" @@ -74,20 +75,26 @@ var anchorCmd = &cobra.Command{ return err } namespace := []byte(namespaceStr) - url, err := handler.Root().PromptString("url", 0, 100) + feeRecipient, err := handler.Root().PromptAddress("feeRecipient") if err != nil { return err } - delete, err := handler.Root().PromptBool("delete") + + op, err := handler.Root().PromptChoice("(0)create (1)delete (2)update", 3) if err != nil { return err } + info := hactions.AnchorInfo{ + FeeRecipient: feeRecipient, + Namespace: namespace, + } + // Generate transaction _, _, err = sendAndWait(ctx, nil, &actions.AnchorRegister{ Namespace: namespace, - Delete: delete, - Url: url, + Info: info, + OpCode: op, }, cli, bcli, ws, factory, true) return err }, diff --git a/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go b/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go index d68b587c88..9ba9f0da88 100644 --- a/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go +++ b/examples/morpheusvm/cmd/morpheus-cli/cmd/chain.go @@ -82,13 +82,13 @@ var anchorsCmd = &cobra.Command{ if err != nil { return err } - namespaces, urls, err := bcli.RegisteredAnchors(ctx) + namespaces, infos, err := bcli.RegisteredAnchors(ctx) if err != nil { return err } fmt.Printf("num of anchors registered: %d\n", len(namespaces)) for i := 0; i < len(namespaces); i++ { - fmt.Printf("%s: %s\n", string(namespaces[i]), urls[i]) + fmt.Printf("%s: %+v\n", string(namespaces[i]), infos[i]) } return nil diff --git a/examples/morpheusvm/controller/resolutions.go b/examples/morpheusvm/controller/resolutions.go index a7b21a3268..ca6d328bf7 100644 --- a/examples/morpheusvm/controller/resolutions.go +++ b/examples/morpheusvm/controller/resolutions.go @@ -6,6 +6,8 @@ package controller import ( "context" + hactions "github.com/ava-labs/hypersdk/actions" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/trace" "github.com/ava-labs/avalanchego/utils/logging" @@ -43,6 +45,6 @@ func (c *Controller) GetBalanceFromState( func (c *Controller) GetRegisteredAnchorsFromState( ctx context.Context, -) ([][]byte, []string, error) { +) ([][]byte, []*hactions.AnchorInfo, error) { return storage.GetAnchorsFromState(ctx, c.inner.ReadState) } diff --git a/examples/morpheusvm/rpc/dependencies.go b/examples/morpheusvm/rpc/dependencies.go index 10d1120bee..b9dac2550e 100644 --- a/examples/morpheusvm/rpc/dependencies.go +++ b/examples/morpheusvm/rpc/dependencies.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/trace" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/examples/morpheusvm/genesis" @@ -18,5 +19,5 @@ type Controller interface { Tracer() trace.Tracer GetTransaction(context.Context, ids.ID) (bool, int64, bool, chain.Dimensions, uint64, error) GetBalanceFromState(context.Context, codec.Address) (uint64, error) - GetRegisteredAnchorsFromState(context.Context) ([][]byte, []string, error) + GetRegisteredAnchorsFromState(context.Context) ([][]byte, []*hactions.AnchorInfo, error) } diff --git a/examples/morpheusvm/rpc/jsonrpc_client.go b/examples/morpheusvm/rpc/jsonrpc_client.go index c287337fcb..3d34f6121b 100644 --- a/examples/morpheusvm/rpc/jsonrpc_client.go +++ b/examples/morpheusvm/rpc/jsonrpc_client.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/ids" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" "github.com/ava-labs/hypersdk/examples/morpheusvm/genesis" @@ -86,7 +87,7 @@ func (cli *JSONRPCClient) Balance(ctx context.Context, addr string) (uint64, err return resp.Amount, err } -func (cli *JSONRPCClient) RegisteredAnchors(ctx context.Context) ([][]byte, []string, error) { +func (cli *JSONRPCClient) RegisteredAnchors(ctx context.Context) ([][]byte, []*hactions.AnchorInfo, error) { resp := new(RegisteredAnchorReply) err := cli.requester.SendRequest( ctx, @@ -94,7 +95,7 @@ func (cli *JSONRPCClient) RegisteredAnchors(ctx context.Context) ([][]byte, []st nil, resp, ) - return resp.Namespaces, resp.Urls, err + return resp.Namespaces, resp.Anchors, err } func (cli *JSONRPCClient) WaitForBalance( diff --git a/examples/morpheusvm/rpc/jsonrpc_server.go b/examples/morpheusvm/rpc/jsonrpc_server.go index 06ed8b4b3f..50c4520ee9 100644 --- a/examples/morpheusvm/rpc/jsonrpc_server.go +++ b/examples/morpheusvm/rpc/jsonrpc_server.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/ids" + hactions "github.com/ava-labs/hypersdk/actions" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" "github.com/ava-labs/hypersdk/examples/morpheusvm/consts" @@ -85,19 +86,19 @@ func (j *JSONRPCServer) Balance(req *http.Request, args *BalanceArgs, reply *Bal } type RegisteredAnchorReply struct { - Namespaces [][]byte `json:"namespaces"` - Urls []string `json:"urls"` + Namespaces [][]byte `json:"namespaces"` + Anchors []*hactions.AnchorInfo `json:"anchors"` } func (j *JSONRPCServer) RegisteredAnchors(req *http.Request, args *struct{}, reply *RegisteredAnchorReply) error { ctx, span := j.c.Tracer().Start(req.Context(), "Server.Balance") defer span.End() - namespaces, urls, err := j.c.GetRegisteredAnchorsFromState(ctx) + namespaces, infos, err := j.c.GetRegisteredAnchorsFromState(ctx) if err != nil { return err } reply.Namespaces = namespaces - reply.Urls = urls + reply.Anchors = infos return err } diff --git a/examples/morpheusvm/storage/storage.go b/examples/morpheusvm/storage/storage.go index a4f06881a2..e6c7f08e60 100644 --- a/examples/morpheusvm/storage/storage.go +++ b/examples/morpheusvm/storage/storage.go @@ -309,37 +309,37 @@ func UnpackNamespaces(raw []byte) ([][]byte, error) { func GetAnchors( ctx context.Context, im state.Immutable, -) ([][]byte, []string, error) { - _, namespaces, urls, _, err := getAnchors(ctx, im) - return namespaces, urls, err +) ([][]byte, []*hactions.AnchorInfo, error) { + _, namespaces, infos, _, err := getAnchors(ctx, im) + return namespaces, infos, err } func getAnchors( ctx context.Context, im state.Immutable, -) (string, [][]byte, []string, bool, error) { +) (string, [][]byte, []*hactions.AnchorInfo, bool, error) { k := AnchorRegistryKey() namespaces, exists, err := innerGetAnchors(im.Get(ctx, k)) if err != nil { return "", nil, nil, false, err } - urls := make([]string, 0, len(namespaces)) + infos := make([]*hactions.AnchorInfo, 0, len(namespaces)) for _, ns := range namespaces { - url, err := GetAnchor(ctx, im, ns) + info, err := GetAnchor(ctx, im, ns) if err != nil { return "", nil, nil, false, err } - urls = append(urls, url) + infos = append(infos, info) } - return k, namespaces, urls, exists, err + return k, namespaces, infos, exists, err } // Used to serve RPC queries func GetAnchorsFromState( ctx context.Context, f ReadState, -) ([][]byte, []string, error) { +) ([][]byte, []*hactions.AnchorInfo, error) { k := AnchorRegistryKey() values, errs := f(ctx, []string{k}) namespaces, _, err := innerGetAnchors(values[0], errs[0]) @@ -347,17 +347,17 @@ func GetAnchorsFromState( return nil, nil, err } - urls := make([]string, 0, len(namespaces)) + infos := make([]*hactions.AnchorInfo, 0, len(namespaces)) for _, ns := range namespaces { k := AnchorKey(ns) values, errs := f(ctx, []string{k}) - url, _, err := innerGetAnchor(values[0], errs[0]) + info, _, err := innerGetAnchor(values[0], errs[0]) if err != nil { return nil, nil, err } - urls = append(urls, url) + infos = append(infos, info) } - return namespaces, urls, err + return namespaces, infos, err } func innerGetAnchors( @@ -413,7 +413,7 @@ func GetAnchor( ctx context.Context, im state.Immutable, namespace []byte, -) (string, error) { +) (*hactions.AnchorInfo, error) { _, anchor, _, err := getAnchor(ctx, im, namespace) return anchor, err } @@ -422,7 +422,7 @@ func getAnchor( ctx context.Context, im state.Immutable, namespace []byte, -) (string, string, bool, error) { +) (string, *hactions.AnchorInfo, bool, error) { k := AnchorKey(namespace) anchor, exists, err := innerGetAnchor(im.Get(ctx, k)) return k, anchor, exists, err @@ -433,7 +433,7 @@ func GetAnchorFromState( ctx context.Context, f ReadState, namespace []byte, -) (string, error) { +) (*hactions.AnchorInfo, error) { k := AnchorKey(namespace) values, errs := f(ctx, []string{k}) anchor, _, err := innerGetAnchor(values[0], errs[0]) @@ -443,34 +443,44 @@ func GetAnchorFromState( func innerGetAnchor( v []byte, err error, -) (string, bool, error) { +) (*hactions.AnchorInfo, bool, error) { if errors.Is(err, database.ErrNotFound) { - return "", false, nil + return nil, false, nil + } + if err != nil { + return nil, false, err } + p := codec.NewReader(v, consts.NetworkSizeLimit) + info, err := hactions.UnmarshalAnchorInfo(p) if err != nil { - return "", false, err + return nil, false, err } - return string(v), true, nil + return info, true, nil } func SetAnchor( ctx context.Context, mu state.Mutable, namespace []byte, - url string, + info *hactions.AnchorInfo, ) error { k := AnchorKey(namespace) - return setAnchor(ctx, mu, k, url) + return setAnchor(ctx, mu, k, info) } func setAnchor( ctx context.Context, mu state.Mutable, key string, - url string, + info *hactions.AnchorInfo, ) error { - urlBytes := []byte(url) - return mu.Put(ctx, key, urlBytes) + p := codec.NewWriter(info.Size(), consts.NetworkSizeLimit) + err := info.Marshal(p) + if err != nil { + return err + } + infoBytes := p.Bytes() + return mu.Put(ctx, key, infoBytes) } func DelAnchor( diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index 850475ae26..bf0a260272 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -18,7 +18,6 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ava-labs/hypersdk/anchor" "github.com/ava-labs/hypersdk/cache" "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" @@ -852,95 +851,95 @@ func (c *ChunkManager) Run(appSender common.AppSender) { for { select { case <-t.C: - if !c.vm.isReady() { - c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") - continue - } - if skipChunks { - continue - } - ctx := context.TODO() - now := time.Now().UnixMilli() - consts.ClockSkewAllowance - r := c.vm.Rules(now) - slot := utils.UnixRDeci(now, r.GetValidityWindow()) // chunk validity window is 9 seconds @todo - - _, epochHeight, err := c.getEpochInfo(ctx, slot) - if err != nil { - c.vm.metrics.gossipChunkSigInvalid.Inc() - c.vm.Logger().Warn("unable to determine chunk epoch", zap.Int64("slot", slot)) - return nil - } - - canonicalValidators, _, err := c.vm.proposerMonitor.GetWarpValidatorSet(ctx, epochHeight) - if err != nil { - c.vm.Logger().Warn("cannot get canonical validator set", zap.Error(err)) - } - - totalAnchors := c.vm.AnchorRegistry().Len() - - partition := c.vm.proposerMonitor.PartitionArray(ctx, epochHeight, epochHeight, totalAnchors, len(canonicalValidators)) - - myValidatorIdx := 0 - myPubkey := c.vm.snowCtx.PublicKey - for i, validator := range canonicalValidators { - if *validator.PublicKey == *myPubkey { - myValidatorIdx = i - break - } - } - partitionedAnchors, assigned := partition[myValidatorIdx] - if !assigned || len(partitionedAnchors) == 0 { - continue - } - - anchors := c.vm.AnchorRegistry().SortedAnchors() - anchorClis := make([]*anchor.Anchor, 0) - for _, anchorIdx := range partitionedAnchors { - anchorClis = append(anchorClis, anchors[anchorIdx]) - } - - for _, anchorCli := range anchorClis { - go func() { - // // Attempt to build a chunk - now := time.Now().UnixMilli() - consts.ClockSkewAllowance - r := c.vm.Rules(now) - digest, err := anchorCli.RequestAnchorDigest() - if err != nil { - c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) - return - } - wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) - if err != nil { - c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) - return - } - sigBytes, err := c.vm.Sign(wm) - if err != nil { - c.vm.Logger().Error("unable to sign message", zap.Error(err)) - return - } - sig, err := bls.SignatureFromBytes(sigBytes) - if err != nil { - c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) - return - } - - meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) - if err != nil { - c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) - return - } - - chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) - if err != nil { - c.vm.Logger().Error("unable to build chunk", zap.Error(err)) - return - } - c.auth.Add(chunk) // this will be a no-op because we are the producer - c.PushChunk(context.TODO(), chunk) - - }() - } + // if !c.vm.isReady() { + // c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") + // continue + // } + // if skipChunks { + // continue + // } + // ctx := context.TODO() + // now := time.Now().UnixMilli() - consts.ClockSkewAllowance + // r := c.vm.Rules(now) + // slot := utils.UnixRDeci(now, r.GetValidityWindow()) // chunk validity window is 9 seconds @todo + + // _, epochHeight, err := c.getEpochInfo(ctx, slot) + // if err != nil { + // c.vm.metrics.gossipChunkSigInvalid.Inc() + // c.vm.Logger().Warn("unable to determine chunk epoch", zap.Int64("slot", slot)) + // return nil + // } + + // canonicalValidators, _, err := c.vm.proposerMonitor.GetWarpValidatorSet(ctx, epochHeight) + // if err != nil { + // c.vm.Logger().Warn("cannot get canonical validator set", zap.Error(err)) + // } + + // totalAnchors := c.vm.AnchorRegistry().Len() + + // partition := c.vm.proposerMonitor.PartitionArray(ctx, epochHeight, epochHeight, totalAnchors, len(canonicalValidators)) + + // myValidatorIdx := 0 + // myPubkey := c.vm.snowCtx.PublicKey + // for i, validator := range canonicalValidators { + // if *validator.PublicKey == *myPubkey { + // myValidatorIdx = i + // break + // } + // } + // partitionedAnchors, assigned := partition[myValidatorIdx] + // if !assigned || len(partitionedAnchors) == 0 { + // continue + // } + + // anchors := c.vm.AnchorRegistry().SortedAnchors() + // anchorClis := make([]*anchor.Anchor, 0) + // for _, anchorIdx := range partitionedAnchors { + // anchorClis = append(anchorClis, anchors[anchorIdx]) + // } + + // for _, anchorCli := range anchorClis { + // go func() { + // // // Attempt to build a chunk + // now := time.Now().UnixMilli() - consts.ClockSkewAllowance + // r := c.vm.Rules(now) + // digest, err := anchorCli.RequestAnchorDigest() + // if err != nil { + // c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) + // return + // } + // wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) + // if err != nil { + // c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) + // return + // } + // sigBytes, err := c.vm.Sign(wm) + // if err != nil { + // c.vm.Logger().Error("unable to sign message", zap.Error(err)) + // return + // } + // sig, err := bls.SignatureFromBytes(sigBytes) + // if err != nil { + // c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) + // return + // } + + // meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) + // if err != nil { + // c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) + // return + // } + + // chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) + // if err != nil { + // c.vm.Logger().Error("unable to build chunk", zap.Error(err)) + // return + // } + // c.auth.Add(chunk) // this will be a no-op because we are the producer + // c.PushChunk(context.TODO(), chunk) + + // }() + // } case <-c.vm.stop: // If engine taking too long to process message, Shutdown will not @@ -1572,7 +1571,7 @@ func (c *ChunkManager) SignAnchorDigest(ctx context.Context, digest []byte) ([]b // fields that are guaranteed populated: // Slot, Txs, PriorityFeeReceiverAddr -func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { +func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, anchor *chain.AnchorMeta, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, anchor, slot, txs, priorityFeeReceiverAddr) if err != nil { return err diff --git a/vm/resolutions.go b/vm/resolutions.go index 6e3043dc7f..9ff9037507 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -364,14 +364,9 @@ func (vm *VM) Accepted(ctx context.Context, b *chain.StatelessBlock, chunks []*c // Cleanup expired chunks we are tracking and chunk certificates vm.cm.SetBuildableMin(ctx, b.StatefulBlock.Timestamp) // clear unnecessary certs - vm.anchorRegistry.Reset() + vm.anchorRegistry.Update(b.Anchors) for _, anchor := range b.Anchors { - if err := vm.anchorRegistry.Register(anchor.Url, anchor.Namespace); err != nil { - vm.Logger().Error("unable to register anchor", zap.Error(err)) - continue - } - - vm.Logger().Debug("registered anchor", zap.String("namespace", anchor.Namespace), zap.String("url", anchor.Url)) + vm.Logger().Debug("registered anchor", zap.ByteString("namespace", anchor.Namespace), zap.Any("info", anchor)) } // Remove from verified caches @@ -603,7 +598,7 @@ func (vm *VM) SignAnchorDigest(ctx context.Context, digest []byte) ([]byte, erro return vm.cm.SignAnchorDigest(ctx, digest) } -func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.Anchor, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { +func (vm *VM) HandleAnchorChunk(ctx context.Context, anchor *chain.AnchorMeta, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { return vm.cm.HandleAnchorChunk(ctx, anchor, slot, txs, priorityFeeReceiverAddr) } From 4441cebf1e4b119b9f7376116e24ee76c6efa6c5 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Tue, 20 Aug 2024 16:04:16 -0400 Subject: [PATCH 16/18] resolve dependencies conflicts between go-eth and ava-go --- anchor/anchor.go | 86 +++++++++++++++ anchor/anchor_test.go | 46 ++++++++ anchor/types.go | 74 +++++++++++++ config/config.go | 1 + examples/morpheusvm/config/config.go | 8 ++ examples/morpheusvm/go.mod | 67 ++++++----- examples/morpheusvm/go.sum | 159 ++++++++++++++++----------- examples/morpheusvm/scripts/run.sh | 2 +- go.mod | 50 ++++++--- go.sum | 159 ++++++++++++++++++++++----- pebble/metrics.go | 6 +- pebble/pebble.go | 6 +- vm/chunk_manager.go | 97 ++-------------- vm/dependencies.go | 1 + vm/metrics.go | 75 +++++-------- vm/resolutions.go | 4 + vm/vm.go | 6 +- 17 files changed, 567 insertions(+), 280 deletions(-) create mode 100644 anchor/types.go diff --git a/anchor/anchor.go b/anchor/anchor.go index c71f5f75d0..f2a2241f0c 100644 --- a/anchor/anchor.go +++ b/anchor/anchor.go @@ -1,3 +1,89 @@ package anchor +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" +) + // TODO: this file to define anchor client + +type AnchorClient struct { + Url string `json:"url"` + vm VM +} + +func NewAnchorClient(vm VM, url string) *AnchorClient { + url = strings.TrimRight(url, "/") + return &AnchorClient{ + vm: vm, + Url: url, + } +} + +// TODO: implement client methods below +func (cli *AnchorClient) GetHeaderV2(slot int64) (*SEQHeaderResponse, error) { + // slot := 0 + parentHash := "0x0" + pubkey := "0x0" + numToBTxs := 5 + numRoBChains := 1 + numRobChunkTxs := 10 + + path := fmt.Sprintf("/eth/v1/builder/header2/%d/%s/%s/%d/%d/%d", slot, parentHash, pubkey, numToBTxs, numRoBChains, numRobChunkTxs) + url := cli.Url + path + + var client http.Client + + resp, err := client.Get(url) + if err != nil { + return nil, err + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var header SEQHeaderResponse + if err := json.Unmarshal(bodyBytes, &header); err != nil { + return nil, err + } + + return &header, nil +} + +func (cli *AnchorClient) GetPayloadV2(slot int64) (*SEQPayloadResponse, error) { + path := "/eth/v1/builder/blinded_blocks2" + url := cli.Url + path + + req := SEQPayloadRequest{ + Slot: uint64(slot), + } + + reqBytes, err := json.Marshal(req) + if err != nil { + return nil, err + } + + var client http.Client + resp, err := client.Post(url, "application/json", bytes.NewBuffer(reqBytes)) + if err != nil { + return nil, err + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var payload SEQPayloadResponse + if err := json.Unmarshal(bodyBytes, &payload); err != nil { + return nil, err + } + + return &payload, nil +} diff --git a/anchor/anchor_test.go b/anchor/anchor_test.go index 44d3ed28f5..3a73cc0f7c 100644 --- a/anchor/anchor_test.go +++ b/anchor/anchor_test.go @@ -1 +1,47 @@ package anchor + +import ( + "fmt" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +const ANCHOR_URL = "http://localhost:18550" + +type MockVM struct{} + +func TestAnchorFlow(t *testing.T) { + slot := int64(1) + cli := NewAnchorClient(nil, ANCHOR_URL) + header, err := cli.GetHeaderV2(slot) + require.NoError(t, err) + fmt.Printf("%+v\n", header) + + payload, err := cli.GetPayloadV2(slot) + require.NoError(t, err) + + tobPayload := payload.ToBPayload + txs := tobPayload.Transactions + fmt.Printf("ToB txs: ") + for _, txRaw := range txs { + var tx ethtypes.Transaction + err := tx.UnmarshalBinary(txRaw) + require.NoError(t, err) + chainID := tx.ChainId() + fmt.Printf("txHash: %s\tchainID: %d\n", tx.Hash().Hex(), chainID.Int64()) + } + + for chainID, robPayload := range payload.RoBPayloads { + fmt.Printf("RoB-%s txs\n", chainID) + txs := robPayload.Transactions + for _, txRaw := range txs { + var tx ethtypes.Transaction + err := tx.UnmarshalBinary(txRaw) + require.NoError(t, err) + chainID := tx.ChainId() + fmt.Printf("txHash: %s\tchainID: %d\n", tx.Hash().Hex(), chainID.Int64()) + } + } +} diff --git a/anchor/types.go b/anchor/types.go new file mode 100644 index 0000000000..6ee999c72b --- /dev/null +++ b/anchor/types.go @@ -0,0 +1,74 @@ +package anchor + +import ( + "github.com/attestantio/go-eth2-client/spec/bellatrix" + "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/codec" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +type Data = hexutil.Bytes + +type SEQPayloadRequest struct { + Slot uint64 `json:"slot"` + ToBBlindedBeaconBlock AnchorSignedBlindedBeaconBlock `json:"tobblindedbeaconblock"` + RoBBlindedBeaconBlocks map[string]AnchorSignedBlindedBeaconBlock `json:"robblindedbeaconblocks"` +} + +type SEQHeaderResponse struct { + Slot uint64 `json:"slot"` + // nodeID of chunk producing validator. + Producer ids.NodeID `json:"producer"` + // block builder address + PriorityFeeReceiverAddr codec.Address `json:"priorityfeereceiveraddr"` + // hash of the anchor chunks (tob + robs) + ChunkHash phase0.Hash32 `json:"chunkhash"` + ToBHash phase0.Hash32 `json:"tobhash"` + RoBHashes map[string]phase0.Hash32 `json:"robhashes"` +} + +type AnchorSignedBlindedBeaconBlock struct { + Message *AnchorBlindedBeaconBlock + Signature phase0.BLSSignature `ssz-size:"96"` +} + +type AnchorBlindedBeaconBlock struct { + Slot phase0.Slot + ProposerIndex phase0.ValidatorIndex + ParentRoot phase0.Root `ssz-size:"32"` + StateRoot phase0.Root `ssz-size:"32"` + Body *AnchorBlindedBeaconBlockBody +} + +type AnchorBlindedBeaconBlockBody struct { + ExecutionPayloadHeader *AnchorExecutionPayloadHeader +} + +// receiving payload from SEQ +type AnchorExecutionPayloadHeader struct { + FeeRecipient bellatrix.ExecutionAddress `ssz-size:"20"` + StateRoot [32]byte `ssz-size:"32"` + ReceiptsRoot [32]byte `ssz-size:"32"` + LogsBloom [256]byte `ssz-size:"256"` + BlockNumber uint64 + Timestamp uint64 + BlockHash phase0.Hash32 `ssz-size:"32"` + TransactionsRoot phase0.Root `ssz-size:"32"` + ChunkDigest phase0.Root `ssz-size:"32"` +} + +type SEQPayloadResponse struct { + Slot uint64 `json:"slot"` + ToBPayload ExecutionPayload2 `json:"tobpayload"` + RoBPayloads map[string]ExecutionPayload2 `json:"robpayloads"` +} + +type ExecutionPayload2 struct { + Slot uint64 `json:"slot"` + BlockHash common.Hash `json:"blockHash"` + // Array of transaction objects, each object is a byte list (DATA) representing + // TransactionType || TransactionPayload or LegacyTransaction as defined in EIP-2718 + Transactions []Data `json:"transactions"` +} diff --git a/config/config.go b/config/config.go index 0372d420cd..17b50a4a04 100644 --- a/config/config.go +++ b/config/config.go @@ -47,3 +47,4 @@ func (c *Config) GetBlockBuildFrequency() time.Duration { return time. func (c *Config) GetProcessingBuildSkip() int { return 16 } func (c *Config) GetMinimumCertificateBroadcastNumerator() uint64 { return 85 } // out of 100 (more weight == more fees) // @todo func (c *Config) GetBeneficiary() codec.Address { return codec.EmptyAddress } +func (c *Config) GetAnchorURL() string { return "" } diff --git a/examples/morpheusvm/config/config.go b/examples/morpheusvm/config/config.go index 53e9e38bc9..46c3593589 100644 --- a/examples/morpheusvm/config/config.go +++ b/examples/morpheusvm/config/config.go @@ -31,6 +31,9 @@ const ( type Config struct { *config.Config + // Anchor + AnchorURL string `json:"anchorUrl"` + // Building ChunkBuildFrequency int64 `json:"chunkBuildFrequency"` // in milliseconds TargetChunkBuildDuration int64 `json:"targetChunkBuildDuration"` // in milliseconds @@ -115,6 +118,7 @@ func (c *Config) setDefault() { c.AuthGossipBacklog = c.Config.GetAuthGossipBacklog() c.ChunkStorageCores = c.Config.GetChunkStorageCores() c.ChunkStorageBacklog = c.Config.GetChunkStorageBacklog() + c.AnchorURL = c.Config.GetAnchorURL() } func (c *Config) GetLogLevel() logging.Level { return c.LogLevel } @@ -197,3 +201,7 @@ func (c *Config) GetChunkStorageCores() int { func (c *Config) GetChunkStorageBacklog() int { return c.ChunkStorageBacklog } + +func (c *Config) GetAnchorURL() string { + return c.AnchorURL +} diff --git a/examples/morpheusvm/go.mod b/examples/morpheusvm/go.mod index 5b171f5713..0e834086f4 100644 --- a/examples/morpheusvm/go.mod +++ b/examples/morpheusvm/go.mod @@ -1,14 +1,12 @@ module github.com/ava-labs/hypersdk/examples/morpheusvm -go 1.21 - -toolchain go1.21.1 +go 1.21.12 require ( github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0 - github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044 + github.com/ava-labs/avalanchego v1.11.10 github.com/ava-labs/hypersdk v0.0.1 - github.com/fatih/color v1.13.0 + github.com/fatih/color v1.16.0 github.com/onsi/ginkgo/v2 v2.13.1 github.com/onsi/gomega v1.29.0 github.com/prometheus/client_golang v1.16.0 @@ -21,10 +19,11 @@ require ( filippo.io/edwards25519 v1.0.0 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect - github.com/ava-labs/coreth v0.13.2-rc.2 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/attestantio/go-eth2-client v0.19.10 // indirect + github.com/ava-labs/coreth v0.13.7 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -32,33 +31,37 @@ require ( github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c // indirect + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/ethereum/c-kzg-4844 v0.3.1 // indirect - github.com/ethereum/go-ethereum v1.12.2 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/go-ethereum v1.13.10 // indirect + github.com/ferranbt/fastssz v0.1.3 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/gizak/termui/v3 v3.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/goccy/go-yaml v1.9.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -76,21 +79,22 @@ require ( github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.3 // indirect - github.com/huin/goupnp v1.0.3 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackpal/gateway v1.0.6 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/klauspost/compress v1.15.15 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect @@ -109,7 +113,9 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect @@ -123,10 +129,10 @@ require ( github.com/subosito/gotenv v1.3.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.24.1 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect @@ -142,20 +148,21 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/net v0.20.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.16.0 // indirect + golang.org/x/tools v0.17.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect gonum.org/v1/gonum v0.11.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/examples/morpheusvm/go.sum b/examples/morpheusvm/go.sum index 0d8cef5aad..f72b698f98 100644 --- a/examples/morpheusvm/go.sum +++ b/examples/morpheusvm/go.sum @@ -46,21 +46,23 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/attestantio/go-eth2-client v0.19.10 h1:NLs9mcBvZpBTZ3du7Ey2NHQoj8d3UePY7pFBXX6C6qs= +github.com/attestantio/go-eth2-client v0.19.10/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0 h1:xNbCMNqenaDr0bb35j27sqwa+C8t8BgRz51vXd6q0QM= github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0/go.mod h1:B7Ynk/avkCk49CCIWbM4j1UrPlqIi0IHCPAB2MZNvLw= -github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044 h1:sI8Oa6awxb1A2w7fBCwnHQUfJqJQBcjjZj/3qUjWGzs= -github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044/go.mod h1:gERvI2cUBGylfAoRT0eRQs+F+BIsDXFRhCfenUUlGUI= -github.com/ava-labs/coreth v0.13.2-rc.2 h1:GmXSyDykDUuDyW7933T8lK7Fp6/4k/IcHhLJjkvjUYI= -github.com/ava-labs/coreth v0.13.2-rc.2/go.mod h1:jOapwtgvroqZ2U8PJpoaq1PHrUFOrlgshUWQfM3nba0= +github.com/ava-labs/avalanchego v1.11.10 h1:QujciF5OEp5FwAoe/RciFF/i47rxU5rkEr6fVuUBS1Q= +github.com/ava-labs/avalanchego v1.11.10/go.mod h1:POgZPryqe80OeHCDNrXrPOKoFre736iFuMgmUBeKaLc= +github.com/ava-labs/coreth v0.13.7 h1:k8T9u/ROifl8f7oXjHRc1KvSISRl9txvy7gGVmHEz6g= +github.com/ava-labs/coreth v0.13.7/go.mod h1:tXDujonxXFOF6oK5HS2EmgtSXJK3Gy6RpZxb5WzR9rM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= @@ -90,7 +92,6 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -115,18 +116,22 @@ github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZ github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c h1:BvCMEtKLZrlcBY2li3COY2q9335JHRK9bC8YTsx60/E= -github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c/go.mod h1:9lRMC4XN3/BLPtIp6kAKwIaHu369NOf2rMucPzipz50= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-kzg-4844 v0.3.0 h1:UBlWE0CgyFqqzTI+IFyCzA7A3Zw4iip6uzRv5NIXG0A= -github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -144,8 +149,8 @@ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwu github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= +github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= @@ -156,12 +161,15 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= -github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6gDq/6Y= -github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek= +github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo= +github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -173,6 +181,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= @@ -189,13 +199,23 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-yaml v1.9.2 h1:2Njwzw+0+pjU2gb805ZC1B/uBuAs2VcZ3K+ZgHwDs7w= +github.com/goccy/go-yaml v1.9.2/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -229,8 +249,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -301,12 +321,15 @@ github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZ github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= -github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/huandu/go-clone v1.6.0 h1:HMo5uvg4wgfiy5FoGOqlFLQED/VGRm2D9Pi8g1FXPGc= +github.com/huandu/go-clone v1.6.0/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= +github.com/huandu/go-clone/generic v1.6.0 h1:Wgmt/fUZ28r16F2Y3APotFD59sHk1p78K0XLdbUYN5U= +github.com/huandu/go-clone/generic v1.6.0/go.mod h1:xgd9ZebcMsBWWcBx5mVMCoqMX24gLWr5lQicr+nVXNs= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -326,8 +349,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -342,23 +365,28 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -429,11 +457,15 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw= +github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -478,14 +510,16 @@ github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5f github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= -github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10 h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10/go.mod h1:x/Pa0FF5Te9kdrlZKJK82YmAkvL8+f989USgz6Jiw7M= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -542,8 +576,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -580,8 +614,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -621,8 +653,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -688,26 +720,27 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -775,13 +808,15 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -882,8 +917,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/examples/morpheusvm/scripts/run.sh b/examples/morpheusvm/scripts/run.sh index 1677a30869..ecbee83ed3 100755 --- a/examples/morpheusvm/scripts/run.sh +++ b/examples/morpheusvm/scripts/run.sh @@ -17,7 +17,7 @@ if ! [[ "$0" =~ scripts/run.sh ]]; then exit 255 fi -AGO_VERSION=v1.11.3 +AGO_VERSION=v1.11.10 MAX_UINT64=18446744073709551615 MODE=${MODE:-run} LOG_LEVEL=${LOG_LEVEL:-DEBUG} diff --git a/go.mod b/go.mod index a40e414d87..0661d91cf4 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module github.com/ava-labs/hypersdk -go 1.21 - -toolchain go1.21.1 +go 1.21.12 require ( github.com/NYTimes/gziphandler v1.1.1 + github.com/attestantio/go-eth2-client v0.19.10 github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0 - github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044 + github.com/ava-labs/avalanchego v1.11.10 github.com/bytecodealliance/wasmtime-go/v14 v14.0.0 - github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 github.com/dustin/go-humanize v1.0.0 + github.com/ethereum/go-ethereum v1.13.8 github.com/gizak/termui/v3 v3.1.0 github.com/golang/mock v1.6.0 github.com/gorilla/mux v1.8.0 @@ -34,7 +34,7 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/mock v0.4.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.21.0 golang.org/x/exp v0.0.0-20231127185646-65229373498e golang.org/x/sync v0.6.0 gopkg.in/yaml.v2 v2.4.0 @@ -44,31 +44,47 @@ require ( filippo.io/edwards25519 v1.0.0 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v1.5.1 // indirect - github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/ferranbt/fastssz v0.1.3 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/goccy/go-yaml v1.9.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect github.com/google/renameio/v2 v2.0.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/klauspost/compress v1.15.15 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect @@ -78,7 +94,9 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/supranational/blst v0.3.11 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect @@ -86,16 +104,18 @@ require ( go.opentelemetry.io/otel/metric v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect gonum.org/v1/gonum v0.11.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index d8690c65ba..cf2add40d5 100644 --- a/go.sum +++ b/go.sum @@ -6,23 +6,33 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/attestantio/go-eth2-client v0.19.10 h1:NLs9mcBvZpBTZ3du7Ey2NHQoj8d3UePY7pFBXX6C6qs= +github.com/attestantio/go-eth2-client v0.19.10/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0 h1:xNbCMNqenaDr0bb35j27sqwa+C8t8BgRz51vXd6q0QM= github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0/go.mod h1:B7Ynk/avkCk49CCIWbM4j1UrPlqIi0IHCPAB2MZNvLw= -github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044 h1:sI8Oa6awxb1A2w7fBCwnHQUfJqJQBcjjZj/3qUjWGzs= -github.com/ava-labs/avalanchego v1.11.4-rc.2.0.20240405173859-4a1d0bbaf044/go.mod h1:gERvI2cUBGylfAoRT0eRQs+F+BIsDXFRhCfenUUlGUI= +github.com/ava-labs/avalanchego v1.11.10 h1:QujciF5OEp5FwAoe/RciFF/i47rxU5rkEr6fVuUBS1Q= +github.com/ava-labs/avalanchego v1.11.10/go.mod h1:POgZPryqe80OeHCDNrXrPOKoFre736iFuMgmUBeKaLc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -54,22 +64,46 @@ github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZ github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c h1:BvCMEtKLZrlcBY2li3COY2q9335JHRK9bC8YTsx60/E= -github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c/go.mod h1:9lRMC4XN3/BLPtIp6kAKwIaHu369NOf2rMucPzipz50= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= +github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo= +github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= @@ -81,8 +115,24 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-yaml v1.9.2 h1:2Njwzw+0+pjU2gb805ZC1B/uBuAs2VcZ3K+ZgHwDs7w= +github.com/goccy/go-yaml v1.9.2/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= @@ -97,22 +147,21 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20230406165453-00490a63f317 h1:hFhpt7CTmR3DX+b4R19ydQFtofxT0Sv3QsKNMVQYTMQ= github.com/google/pprof v0.0.0-20230406165453-00490a63f317/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= @@ -123,7 +172,13 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rH github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/go-clone v1.6.0 h1:HMo5uvg4wgfiy5FoGOqlFLQED/VGRm2D9Pi8g1FXPGc= +github.com/huandu/go-clone v1.6.0/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= +github.com/huandu/go-clone/generic v1.6.0 h1:Wgmt/fUZ28r16F2Y3APotFD59sHk1p78K0XLdbUYN5U= +github.com/huandu/go-clone/generic v1.6.0/go.mod h1:xgd9ZebcMsBWWcBx5mVMCoqMX24gLWr5lQicr+nVXNs= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -132,21 +187,42 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= @@ -160,6 +236,8 @@ github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce h1:/pEpMk55wH0X+E5zedGEMOdLuWmV8P4+4W3+LZaM6kg= github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -191,26 +269,43 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw= +github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10 h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10/go.mod h1:x/Pa0FF5Te9kdrlZKJK82YmAkvL8+f989USgz6Jiw7M= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= @@ -247,8 +342,8 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -263,8 +358,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -281,6 +376,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -290,11 +387,14 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -305,12 +405,14 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= @@ -327,10 +429,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -339,6 +439,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXL gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -346,3 +447,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/pebble/metrics.go b/pebble/metrics.go index 0e8db36c9e..bb580ab9d3 100644 --- a/pebble/metrics.go +++ b/pebble/metrics.go @@ -36,8 +36,7 @@ type metrics struct { func newMetrics() (*prometheus.Registry, *metrics, error) { r := prometheus.NewRegistry() writeStall, err := metric.NewAverager( - "pebble", - "write_stall", + "pebble_write_stall", "time spent waiting for disk write", r, ) @@ -45,8 +44,7 @@ func newMetrics() (*prometheus.Registry, *metrics, error) { return nil, nil, err } getLatency, err := metric.NewAverager( - "pebble", - "read_latency", + "pebble_read_latency", "time spent waiting for db get", r, ) diff --git a/pebble/pebble.go b/pebble/pebble.go index 0ae3fbd144..e201fda0be 100644 --- a/pebble/pebble.go +++ b/pebble/pebble.go @@ -78,7 +78,7 @@ func New(file string, cfg Config) (database.Database, *prometheus.Registry, erro L0CompactionThreshold: cfg.L0CompactionThreshold, L0StopWritesThreshold: cfg.L0StopWritesThreshold, MemTableStopWritesThreshold: cfg.MemTableStopWritesThreshold, - MemTableSize: cfg.MemTableSize, + MemTableSize: uint64(cfg.MemTableSize), MaxOpenFiles: cfg.MaxOpenFiles, MaxConcurrentCompactions: cfg.ConcurrentCompactions, // TODO: may want to tweak this? Levels: make([]pebble.LevelOptions, 7), @@ -247,9 +247,11 @@ type iter struct { } func (db *Database) newIter(args *pebble.IterOptions) *iter { + it, err := db.db.NewIter(args) return &iter{ db: db, - iter: db.db.NewIter(args), + iter: it, + err: err, } } diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index bf0a260272..ef5a53e52e 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -851,94 +851,17 @@ func (c *ChunkManager) Run(appSender common.AppSender) { for { select { case <-t.C: - // if !c.vm.isReady() { - // c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") - // continue - // } - // if skipChunks { - // continue - // } - // ctx := context.TODO() - // now := time.Now().UnixMilli() - consts.ClockSkewAllowance - // r := c.vm.Rules(now) - // slot := utils.UnixRDeci(now, r.GetValidityWindow()) // chunk validity window is 9 seconds @todo - - // _, epochHeight, err := c.getEpochInfo(ctx, slot) - // if err != nil { - // c.vm.metrics.gossipChunkSigInvalid.Inc() - // c.vm.Logger().Warn("unable to determine chunk epoch", zap.Int64("slot", slot)) - // return nil - // } - - // canonicalValidators, _, err := c.vm.proposerMonitor.GetWarpValidatorSet(ctx, epochHeight) + if !c.vm.isReady() { + c.vm.Logger().Debug("skipping chunk loop because vm isn't ready") + continue + } + if skipChunks { + continue + } + // anchorCli := c.vm.AnchorCli() + // _, err := anchorCli.GetHeaderV2() // if err != nil { - // c.vm.Logger().Warn("cannot get canonical validator set", zap.Error(err)) - // } - - // totalAnchors := c.vm.AnchorRegistry().Len() - - // partition := c.vm.proposerMonitor.PartitionArray(ctx, epochHeight, epochHeight, totalAnchors, len(canonicalValidators)) - - // myValidatorIdx := 0 - // myPubkey := c.vm.snowCtx.PublicKey - // for i, validator := range canonicalValidators { - // if *validator.PublicKey == *myPubkey { - // myValidatorIdx = i - // break - // } - // } - // partitionedAnchors, assigned := partition[myValidatorIdx] - // if !assigned || len(partitionedAnchors) == 0 { - // continue - // } - - // anchors := c.vm.AnchorRegistry().SortedAnchors() - // anchorClis := make([]*anchor.Anchor, 0) - // for _, anchorIdx := range partitionedAnchors { - // anchorClis = append(anchorClis, anchors[anchorIdx]) - // } - - // for _, anchorCli := range anchorClis { - // go func() { - // // // Attempt to build a chunk - // now := time.Now().UnixMilli() - consts.ClockSkewAllowance - // r := c.vm.Rules(now) - // digest, err := anchorCli.RequestAnchorDigest() - // if err != nil { - // c.vm.Logger().Error("unable to fetch chunk digest from anchor", zap.Error(err)) - // return - // } - // wm, err := warp.NewUnsignedMessage(r.NetworkID(), r.ChainID(), digest) - // if err != nil { - // c.vm.Logger().Error("unable to generate warp message", zap.Error(err)) - // return - // } - // sigBytes, err := c.vm.Sign(wm) - // if err != nil { - // c.vm.Logger().Error("unable to sign message", zap.Error(err)) - // return - // } - // sig, err := bls.SignatureFromBytes(sigBytes) - // if err != nil { - // c.vm.Logger().Error("unable to unmarshal sig", zap.Error(err)) - // return - // } - - // meta, slot, txs, priorityFeeReceiver, err := anchorCli.RequestAnchorChunk(sig) - // if err != nil { - // c.vm.Logger().Error("unable to fetch chunk from Anchor", zap.Error(err)) - // return - // } - - // chunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, meta, slot, txs, priorityFeeReceiver) - // if err != nil { - // c.vm.Logger().Error("unable to build chunk", zap.Error(err)) - // return - // } - // c.auth.Add(chunk) // this will be a no-op because we are the producer - // c.PushChunk(context.TODO(), chunk) - - // }() + // c.vm.Logger().Error("unable to get header from anchor", zap.Error(err)) // } case <-c.vm.stop: diff --git a/vm/dependencies.go b/vm/dependencies.go index 246e55eb90..e8f624b65c 100644 --- a/vm/dependencies.go +++ b/vm/dependencies.go @@ -50,6 +50,7 @@ type Config interface { GetBlockBuildFrequency() time.Duration GetProcessingBuildSkip() int GetMinimumCertificateBroadcastNumerator() uint64 + GetAnchorURL() string } type Genesis interface { diff --git a/vm/metrics.go b/vm/metrics.go index 4ab8ed84f6..826998f981 100644 --- a/vm/metrics.go +++ b/vm/metrics.go @@ -122,8 +122,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { r := prometheus.NewRegistry() waitRepeat, err := metric.NewAverager( - "chain", - "wait_repeat", + "chain_wait_repeat", "time spent waiting for repeat", r, ) @@ -131,8 +130,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } waitQueue, err := metric.NewAverager( - "chain", - "wait_queue", + "chain_wait_queue", "time spent iterating over chunk to queue txs for execution", r, ) @@ -140,8 +138,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } waitAuth, err := metric.NewAverager( - "chain", - "wait_auth", + "chain_wait_auth", "time spent waiting for auth", r, ) @@ -149,8 +146,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } waitExec, err := metric.NewAverager( - "chain", - "wait_exec", + "chain_wait_exec", "time spent waiting for execution after auth finishes", r, ) @@ -158,8 +154,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } waitPrecheck, err := metric.NewAverager( - "chain", - "wait_precheck", + "chain_wait_precheck", "time spent waiting for precheck", r, ) @@ -167,8 +162,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } waitCommit, err := metric.NewAverager( - "chain", - "wait_commit", + "chain_wait_commit", "time spent waiting to commit state after execution", r, ) @@ -176,8 +170,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } chunkBuild, err := metric.NewAverager( - "chain", - "chunk_build", + "chain_chunk_build", "time spent building chunks", r, ) @@ -185,8 +178,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockBuild, err := metric.NewAverager( - "chain", - "block_build", + "chain_block_build", "time spent building blocks", r, ) @@ -194,8 +186,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockParse, err := metric.NewAverager( - "chain", - "block_parse", + "chain_block_parse", "time spent parsing blocks", r, ) @@ -203,8 +194,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockVerify, err := metric.NewAverager( - "chain", - "block_verify", + "chain_block_verify", "time spent verifying blocks", r, ) @@ -212,8 +202,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockAccept, err := metric.NewAverager( - "chain", - "block_accept", + "chain_block_accept", "time spent accepting blocks", r, ) @@ -221,8 +210,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockProcess, err := metric.NewAverager( - "chain", - "block_process", + "chain_block_process", "time spent processing accepted blocks", r, ) @@ -230,8 +218,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } blockExecute, err := metric.NewAverager( - "chain", - "block_execute", + "chain_block_execute", "time spent executing blocks", r, ) @@ -239,8 +226,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } executedChunkProcess, err := metric.NewAverager( - "chain", - "executed_chunk_process", + "chain_executed_chunk_process", "time spent processing executed chunks", r, ) @@ -248,8 +234,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } executedBlockProcess, err := metric.NewAverager( - "chain", - "executed_block_process", + "chain_executed_block_process", "time spent processing executed blocks", r, ) @@ -257,8 +242,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } fetchMissingChunks, err := metric.NewAverager( - "chain", - "fetch_missing_chunks", + "chain_fetch_missing_chunks", "time spent fetching missing chunks", r, ) @@ -266,8 +250,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } collectChunkSignatures, err := metric.NewAverager( - "chain", - "collect_chunk_signatures", + "chain_collect_chunk_signatures", "time spent collecting chunk signatures", r, ) @@ -275,8 +258,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } txTimeRemainingMempool, err := metric.NewAverager( - "chain", - "tx_time_remaining_mempool", + "chain_tx_time_remaining_mempool", "valid time for inclusion when a tx is included in the mempool", r, ) @@ -284,8 +266,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } chunkAuth, err := metric.NewAverager( - "chain", - "chunk_auth", + "chain_chunk_auth", "time spent authenticating chunks", r, ) @@ -293,8 +274,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } stateChanges, err := metric.NewAverager( - "chain", - "state_changes", + "chain_state_changes", "changes to state in a block", r, ) @@ -302,8 +282,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } appendDBBatchInit, err := metric.NewAverager( - "vilmo", - "batch_init", + "vilmo_batch_init", "batch initialization latency", r, ) @@ -311,8 +290,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } appendDBBatchInitBytes, err := metric.NewAverager( - "vilmo", - "batch_init_bytes", + "vilmo_batch_init_bytes", "bytes written during batch initialization", r, ) @@ -320,8 +298,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } appendDBBatchPrepare, err := metric.NewAverager( - "vilmo", - "batch_prepare", + "vilmo_batch_prepare", "batch preparation latency", r, ) @@ -329,8 +306,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } tstateIterate, err := metric.NewAverager( - "chain", - "tstate_iterate", + "chain_tstate_iterate", "time spent iterating over tstate", r, ) @@ -338,8 +314,7 @@ func newMetrics() (*prometheus.Registry, *Metrics, error) { return nil, nil, err } appendDBBatchWrite, err := metric.NewAverager( - "vilmo", - "batch_write", + "vilmo_batch_write", "batch write latency", r, ) diff --git a/vm/resolutions.go b/vm/resolutions.go index 9ff9037507..579c53b5ec 100644 --- a/vm/resolutions.go +++ b/vm/resolutions.go @@ -606,6 +606,10 @@ func (vm *VM) AnchorRegistry() *anchor.AnchorRegistry { return vm.anchorRegistry } +func (vm *VM) AnchorCli() *anchor.AnchorClient { + return vm.anchorCli +} + func (vm *VM) IsIssuedTx(_ context.Context, tx *chain.Transaction) bool { return vm.issuedTxs.Has(tx) } diff --git a/vm/vm.go b/vm/vm.go index f12d369d7d..e6cb777d26 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -81,6 +81,7 @@ type VM struct { // Handle chunks cm *ChunkManager anchorRegistry *anchor.AnchorRegistry + anchorCli *anchor.AnchorClient engine *chain.Engine // track all issuedTxs (to prevent wasting bandwidth) @@ -172,7 +173,7 @@ func (vm *VM) Initialize( vm.ready = make(chan struct{}) vm.stop = make(chan struct{}) gatherer := ametrics.NewMultiGatherer() - if err := vm.snowCtx.Metrics.Register(gatherer); err != nil { + if err := vm.snowCtx.Metrics.Register("hypersdk", gatherer); err != nil { return err } defaultRegistry, metrics, err := newMetrics() @@ -216,6 +217,9 @@ func (vm *VM) Initialize( anchorRegistry := anchor.NewAnchorRegistry(vm) vm.anchorRegistry = anchorRegistry + anchorCli := anchor.NewAnchorClient(vm, vm.config.GetAnchorURL()) + vm.anchorCli = anchorCli + // Setup tracer vm.tracer, err = htrace.New(vm.config.GetTraceConfig()) if err != nil { From 393acd77f381713db75f2daf77be84b3f87c6ec8 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Wed, 21 Aug 2024 11:13:02 -0400 Subject: [PATCH 17/18] anchor chunk submission --- chain/chunk.go | 99 ++++++++++++++------------------------------- vm/chunk_manager.go | 25 ++++++++++-- 2 files changed, 52 insertions(+), 72 deletions(-) diff --git a/chain/chunk.go b/chain/chunk.go index 64ec15ae3d..40729d9f74 100644 --- a/chain/chunk.go +++ b/chain/chunk.go @@ -24,26 +24,19 @@ const ( ) type AnchorMeta struct { - BlockType int `json:"blockType"` // use to determine if it is TOB or ROB - Namespace string `json:"namespace"` - Url string `json:"url"` - - bytes []byte + BlockType int `json:"blockType"` // use to determine if it is TOB or ROB + Namespace string `json:"namespace"` + PriorityFeeReceiver codec.Address `json:"priorityFeeReceiver"` } func (a *AnchorMeta) Size() int { - return consts.IntLen + codec.StringLen(a.Namespace) + codec.StringLen(a.Url) + return consts.IntLen + codec.StringLen(a.Namespace) + codec.AddressLen } func (a *AnchorMeta) Marshal(p *codec.Packer) error { - if len(a.bytes) > 0 { - p.PackFixedBytes(a.bytes) - return p.Err() - } - p.PackInt(a.BlockType) p.PackString(a.Namespace) - p.PackString(a.Url) + p.PackAddress(a.PriorityFeeReceiver) return p.Err() } @@ -52,7 +45,7 @@ func UnmarshalAnchorMeta(p *codec.Packer) (*AnchorMeta, error) { ret := new(AnchorMeta) ret.BlockType = p.UnpackInt(false) ret.Namespace = p.UnpackString(false) - ret.Url = p.UnpackString(false) + p.UnpackAddress(&ret.PriorityFeeReceiver) if err := p.Err(); err != nil { return nil, p.Err() @@ -61,51 +54,14 @@ func UnmarshalAnchorMeta(p *codec.Packer) (*AnchorMeta, error) { return ret, nil } -func MarshalAnchorMetas(anchors []*AnchorMeta) ([]byte, error) { - size := consts.IntLen - for _, a := range anchors { - size += a.Size() - } - p := codec.NewWriter(size, consts.NetworkSizeLimit) - - p.PackInt(len(anchors)) - for _, a := range anchors { - if err := a.Marshal(p); err != nil { - return nil, err - } - } - - return p.Bytes(), p.Err() -} - -func UnmarshalAnchorMetas(raw []byte) ([]*AnchorMeta, error) { - p := codec.NewReader(raw, consts.NetworkSizeLimit) - numAnchorMetas := p.UnpackInt(false) - ret := make([]*AnchorMeta, 0, numAnchorMetas) - for i := 0; i < numAnchorMetas; i++ { - a, err := UnmarshalAnchorMeta(p) - if err != nil { - return nil, err - } - ret = append(ret, a) - } - - if p.Err() != nil { - return nil, p.Err() - } - - return ret, nil -} - type Chunk struct { AnchorMeta *AnchorMeta `json:"anchor"` // if null then the chunk is generated from txs in mempool Slot int64 `json:"slot"` // rounded to nearest 100ms Txs []*Transaction `json:"txs"` - PriorityFeeReceiverAddr codec.Address `json:"priorityFeeReceiver"` - Producer ids.NodeID `json:"producer"` - Beneficiary codec.Address `json:"beneficiary"` // used for fees + Producer ids.NodeID `json:"producer"` + Beneficiary codec.Address `json:"beneficiary"` // used for fees Signer *bls.PublicKey `json:"signer"` Signature *bls.Signature `json:"signature"` @@ -116,7 +72,11 @@ type Chunk struct { authCounts map[uint8]int } -func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *AnchorMeta, slot int64, txs []*Transaction, priorityFeeReceiver codec.Address) (*Chunk, error) { +func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *AnchorMeta, slot int64, txs []*Transaction) (*Chunk, error) { + if anchor == nil { + return nil, fmt.Errorf("not an anchor chunk") + } + start := time.Now() now := time.Now().UnixMilli() - consts.ClockSkewAllowance sm := vm.StateManager() @@ -205,17 +165,18 @@ func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *AnchorMeta, slot i } // Discard chunk if nothing produced - if len(c.Txs) == 0 { - return nil, ErrNoTxs - } + // TODO: restore this after testing + // if len(c.Txs) == 0 { + // return nil, ErrNoTxs + // } // Setup chunk - c.PriorityFeeReceiverAddr = priorityFeeReceiver c.Producer = vm.NodeID() c.Beneficiary = vm.Beneficiary() c.Signer = vm.Signer() c.units = &chunkUnits c.authCounts = authCounts + c.AnchorMeta = anchor // Sign chunk digest, err := c.Digest() @@ -241,7 +202,9 @@ func BuildChunkFromAnchor(ctx context.Context, vm VM, anchor *AnchorMeta, slot i c.id = utils.ToID(bytes) vm.Logger().Info( - "built chunk with signature from anchor msg", + "built anchor chunk chunk with signature", + zap.Int("anchorType", c.AnchorMeta.BlockType), + zap.String("anchorNamespace", c.AnchorMeta.Namespace), zap.Stringer("nodeID", vm.NodeID()), zap.Uint32("networkID", r.NetworkID()), zap.Stringer("chainID", r.ChainID()), @@ -383,7 +346,6 @@ func BuildChunk(ctx context.Context, vm VM) (*Chunk, error) { } // Setup chunk - c.PriorityFeeReceiverAddr = codec.EmptyAddress c.Producer = vm.NodeID() c.Beneficiary = vm.Beneficiary() c.Signer = vm.Signer() @@ -460,12 +422,12 @@ func (c *Chunk) ID() ids.ID { } func (c *Chunk) Size() int { - size := consts.BoolLen + consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + codec.AddressLen + bls.PublicKeyLen + bls.SignatureLen + size := consts.Int64Len + consts.IntLen + codec.CummSize(c.Txs) + consts.NodeIDLen + codec.AddressLen + bls.PublicKeyLen + bls.SignatureLen + size += consts.BoolLen isAnchorMeta := c.AnchorMeta != nil if isAnchorMeta { - size += consts.IntLen - size += codec.StringLen(c.AnchorMeta.Namespace) + size += c.AnchorMeta.Size() } return size } @@ -512,9 +474,9 @@ func (c *Chunk) Marshal() ([]byte, error) { p.PackFixedBytes(bls.PublicKeyToCompressedBytes(c.Signer)) p.PackFixedBytes(bls.SignatureToBytes(c.Signature)) + // fields introduced for anchor isAnchorMetaChunk := c.AnchorMeta != nil p.PackBool(isAnchorMetaChunk) - fmt.Printf("anchor chunk: %+v\n", isAnchorMetaChunk) if isAnchorMetaChunk { if err := c.AnchorMeta.Marshal(p); err != nil { return nil, err @@ -522,7 +484,6 @@ func (c *Chunk) Marshal() ([]byte, error) { } bytes, err := p.Bytes(), p.Err() - fmt.Printf("chunk bytes: %s\n", hex.EncodeToString(bytes)) if err != nil { return nil, err } @@ -554,14 +515,15 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { c Chunk authCounts = make(map[uint8]int) ) - fmt.Printf("chunk bytes: %s\n", hex.EncodeToString(raw)) c.id = utils.ToID(raw) // Parse transactions c.Slot = p.UnpackInt64(false) - txCount := p.UnpackInt(true) // can't produce empty blocks - c.Txs = []*Transaction{} // don't preallocate all to avoid DoS + // TODO: restore this + // txCount := p.UnpackInt(true) // can't produce empty blocks + txCount := p.UnpackInt(false) // can't produce empty blocks + c.Txs = []*Transaction{} // don't preallocate all to avoid DoS for i := 0; i < txCount; i++ { tx, err := UnmarshalTx(p, actionRegistry, authRegistry) if err != nil { @@ -590,13 +552,14 @@ func UnmarshalChunk(raw []byte, parser Parser) (*Chunk, error) { } c.Signature = signature + // fields introduced for anchor isAnchorMetaChunk := p.UnpackBool() - fmt.Printf("anchor chunk: %+v\n", isAnchorMetaChunk) if isAnchorMetaChunk { anchor, err := UnmarshalAnchorMeta(p) if err != nil { return nil, err } + fmt.Printf("unmarshalled anchor meta: %+v\n", anchor) c.AnchorMeta = anchor } diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index ef5a53e52e..f401f1a249 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/binary" - "encoding/hex" "errors" "fmt" "sync" @@ -457,7 +456,7 @@ func (c *ChunkManager) AppGossip(ctx context.Context, nodeID ids.NodeID, msg []b chunk, err := chain.UnmarshalChunk(msg[1:], c.vm) if err != nil { c.vm.metrics.gossipChunkInvalid.Inc() - c.vm.Logger().Warn("unable to unmarshal chunk", zap.Stringer("nodeID", nodeID), zap.String("chunk", hex.EncodeToString(msg[1:])), zap.Error(err)) + c.vm.Logger().Warn("unable to unmarshal chunk", zap.Stringer("nodeID", nodeID), zap.Error(err)) return nil } @@ -863,7 +862,22 @@ func (c *ChunkManager) Run(appSender common.AppSender) { // if err != nil { // c.vm.Logger().Error("unable to get header from anchor", zap.Error(err)) // } - + now := time.Now().UnixMilli() - consts.ClockSkewAllowance + r := c.vm.Rules(now) + slot := utils.UnixRDeci(now, r.GetValidityWindow()) + + anchorChunk, err := chain.BuildChunkFromAnchor(context.TODO(), c.vm, &chain.AnchorMeta{ + BlockType: chain.AnchorRoB, + Namespace: "t", + PriorityFeeReceiver: codec.BlackholeAddress, + }, slot, nil) + if err != nil { + c.vm.Logger().Error("unable to build a anchor chunk", zap.Error(err)) + continue + } + c.auth.Add(anchorChunk) + c.PushChunk(context.TODO(), anchorChunk) + c.vm.Logger().Debug("anchor chunk pushed", zap.String("chunkID", anchorChunk.ID().String())) case <-c.vm.stop: // If engine taking too long to process message, Shutdown will not // be called. @@ -1216,6 +1230,9 @@ func makeChunkMsg(chunk *chain.Chunk) ([]byte, error) { if err != nil { return nil, err } + if len(chunkBytes) != chunk.Size() { + return nil, fmt.Errorf("marshalled chunk bytes len not equal to Size(), actual: %d, expected: %d", len(chunkBytes), chunk.Size()) + } copy(msg[1:], chunkBytes) return msg, nil } @@ -1495,7 +1512,7 @@ func (c *ChunkManager) SignAnchorDigest(ctx context.Context, digest []byte) ([]b // fields that are guaranteed populated: // Slot, Txs, PriorityFeeReceiverAddr func (c *ChunkManager) HandleAnchorChunk(ctx context.Context, anchor *chain.AnchorMeta, slot int64, txs []*chain.Transaction, priorityFeeReceiverAddr codec.Address) error { - chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, anchor, slot, txs, priorityFeeReceiverAddr) + chunk, err := chain.BuildChunkFromAnchor(ctx, c.vm, anchor, slot, txs) if err != nil { return err } From 5d2ff42931bc9004e8f3791ee39285111eeb4084 Mon Sep 17 00:00:00 2001 From: bianyuanop Date: Wed, 21 Aug 2024 11:55:38 -0400 Subject: [PATCH 18/18] tested anchor chunk flow --- chain/block.go | 5 +++++ chain/processor.go | 7 ++++--- codec/utils.go | 2 +- vm/chunk_manager.go | 9 +++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/chain/block.go b/chain/block.go index 3eae77a05e..783468e0ba 100644 --- a/chain/block.go +++ b/chain/block.go @@ -545,6 +545,11 @@ func (b *StatelessBlock) Accept(ctx context.Context) error { b.vm.Engine().Execute(b) } + b.vm.Logger().Debug("included chunk") + for chunkID := range b.chunks { + b.vm.Logger().Debug("chunk", zap.String("chunkID", chunkID.String())) + } + r := b.vm.Rules(b.StatefulBlock.Timestamp) epoch := utils.Epoch(b.StatefulBlock.Timestamp, r.GetEpochDuration()) b.vm.RecordAcceptedEpoch(epoch) diff --git a/chain/processor.go b/chain/processor.go index 66323939e9..e3a8741007 100644 --- a/chain/processor.go +++ b/chain/processor.go @@ -86,9 +86,10 @@ func NewProcessor( executor: executor.New(numTxs, vm.GetActionExecutionCores(), vm.GetExecutorRecorder()), ts: tstate.New(numTxs * 2), - txs: make(map[ids.ID]*blockLoc, numTxs), - results: make([][]*Result, chunks), - anchors: make([]*actions.AnchorInfo, 0), + txs: make(map[ids.ID]*blockLoc, numTxs), + results: make([][]*Result, chunks), + anchors: make([]*actions.AnchorInfo, 0), + acceptedNS: make(map[string]struct{}), } } diff --git a/codec/utils.go b/codec/utils.go index fffce7d533..7a874af49d 100644 --- a/codec/utils.go +++ b/codec/utils.go @@ -26,5 +26,5 @@ func BytesLenSize(msgSize int) int { } func StringLen(msg string) int { - return consts.IntLen + len(msg) + return consts.Uint16Len + len(msg) } diff --git a/vm/chunk_manager.go b/vm/chunk_manager.go index f401f1a249..b2d0e269ce 100644 --- a/vm/chunk_manager.go +++ b/vm/chunk_manager.go @@ -1238,6 +1238,15 @@ func makeChunkMsg(chunk *chain.Chunk) ([]byte, error) { } func (c *ChunkManager) PushChunk(ctx context.Context, chunk *chain.Chunk) { + p := codec.NewWriter(chunk.AnchorMeta.Size(), consts.NetworkSizeLimit) + err := chunk.AnchorMeta.Marshal(p) + if err != nil { + c.vm.Logger().Error("unable to marshal meta", zap.Error(err)) + return + } + metaBytes := p.Bytes() + c.vm.Logger().Debug("chunk size info", zap.Int("chunk", chunk.Size()), zap.Int("meta", chunk.AnchorMeta.Size()), zap.Int("meta real", len(metaBytes))) + msg, err := makeChunkMsg(chunk) if err != nil { c.vm.Logger().Warn("failed to marshal chunk", zap.Error(err))