From 963f1f8d5ab3fe080ba64452a5cab4722d137b0c Mon Sep 17 00:00:00 2001 From: Nick Pocock Date: Tue, 14 Jun 2022 20:18:55 +0200 Subject: [PATCH 01/24] [httputil] return error from keep alive methods within httputil pkg (#3439) --- pkg/util/httputil/httputil.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/util/httputil/httputil.go b/pkg/util/httputil/httputil.go index 323426655d..d5dbea833b 100644 --- a/pkg/util/httputil/httputil.go +++ b/pkg/util/httputil/httputil.go @@ -52,7 +52,14 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { if err != nil { return nil, err } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) + + if err = tc.SetKeepAlive(true); err != nil { + return nil, err + } + + if err = tc.SetKeepAlivePeriod(3 * time.Minute); err != nil { + return nil, err + } + return tc, nil } From ba24a74d0432e4440880d60dcc09c6d8214e4e65 Mon Sep 17 00:00:00 2001 From: dustinxie Date: Wed, 15 Jun 2022 23:34:57 -0700 Subject: [PATCH 02/24] [block] deprecate some code in block.go and body.go (#3453) --- blockchain/block/block.go | 29 -------- blockchain/block/block_deserializer.go | 33 +++++++--- blockchain/block/block_deserializer_test.go | 8 +-- blockchain/block/block_test.go | 19 ------ blockchain/block/body.go | 24 ------- blockchain/block/body_test.go | 24 ++++--- consensus/scheme/rolldpos/subchain_test.go | 73 --------------------- 7 files changed, 41 insertions(+), 169 deletions(-) delete mode 100644 consensus/scheme/rolldpos/subchain_test.go diff --git a/blockchain/block/block.go b/blockchain/block/block.go index a5283136e7..b3a00d1e98 100644 --- a/blockchain/block/block.go +++ b/blockchain/block/block.go @@ -52,35 +52,6 @@ func (b *Block) Serialize() ([]byte, error) { return proto.Marshal(b.ConvertToBlockPb()) } -// ConvertFromBlockPb converts Block to Block -func (b *Block) ConvertFromBlockPb(pbBlock *iotextypes.Block, id uint32) error { - b.Header = Header{} - if err := b.Header.LoadFromBlockHeaderProto(pbBlock.GetHeader()); err != nil { - return err - } - b.Body = Body{} - if err := b.Body.LoadProto(pbBlock.GetBody(), id); err != nil { - return err - } - - return b.ConvertFromBlockFooterPb(pbBlock.GetFooter()) -} - -// Deserialize parses the byte stream into a Block -func (b *Block) Deserialize(buf []byte, id uint32) error { - pbBlock := iotextypes.Block{} - if err := proto.Unmarshal(buf, &pbBlock); err != nil { - return err - } - if err := b.ConvertFromBlockPb(&pbBlock, id); err != nil { - return err - } - b.Receipts = nil - - // verify merkle root can match after deserialize - return b.VerifyTxRoot() -} - // VerifyTxRoot verifies the transaction root hash func (b *Block) VerifyTxRoot() error { root, err := b.CalculateTxRoot() diff --git a/blockchain/block/block_deserializer.go b/blockchain/block/block_deserializer.go index b7deeaf1b6..424e59624a 100644 --- a/blockchain/block/block_deserializer.go +++ b/blockchain/block/block_deserializer.go @@ -10,6 +10,8 @@ import ( "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" "google.golang.org/protobuf/proto" + + "github.com/iotexproject/iotex-core/action" ) // Deserializer de-serializes a block @@ -32,14 +34,17 @@ func (bd *Deserializer) SetEvmNetworkID(id uint32) *Deserializer { // FromBlockProto converts protobuf to block func (bd *Deserializer) FromBlockProto(pbBlock *iotextypes.Block) (*Block, error) { - b := Block{} - if err := b.Header.LoadFromBlockHeaderProto(pbBlock.GetHeader()); err != nil { + var ( + b = Block{} + err error + ) + if err = b.Header.LoadFromBlockHeaderProto(pbBlock.GetHeader()); err != nil { return nil, errors.Wrap(err, "failed to deserialize block header") } - if err := b.Body.LoadProto(pbBlock.GetBody(), bd.evmNetworkID); err != nil { + if b.Body, err = bd.fromBodyProto(pbBlock.GetBody()); err != nil { return nil, errors.Wrap(err, "failed to deserialize block body") } - if err := b.ConvertFromBlockFooterPb(pbBlock.GetFooter()); err != nil { + if err = b.ConvertFromBlockFooterPb(pbBlock.GetFooter()); err != nil { return nil, errors.Wrap(err, "failed to deserialize block footer") } return &b, nil @@ -62,13 +67,17 @@ func (bd *Deserializer) DeserializeBlock(buf []byte) (*Block, error) { return b, nil } -// FromBodyProto converts protobuf to body -func (bd *Deserializer) FromBodyProto(pbBody *iotextypes.BlockBody) (*Body, error) { +// fromBodyProto converts protobuf to body +func (bd *Deserializer) fromBodyProto(pbBody *iotextypes.BlockBody) (Body, error) { b := Body{} - if err := b.LoadProto(pbBody, bd.evmNetworkID); err != nil { - return nil, errors.Wrap(err, "failed to deserialize block body") + for _, actPb := range pbBody.Actions { + act, err := (&action.Deserializer{}).SetEvmNetworkID(bd.evmNetworkID).ActionToSealedEnvelope(actPb) + if err != nil { + return b, errors.Wrap(err, "failed to deserialize block body") + } + b.Actions = append(b.Actions, act) } - return &b, nil + return b, nil } // DeserializeBody de-serializes a block body @@ -77,5 +86,9 @@ func (bd *Deserializer) DeserializeBody(buf []byte) (*Body, error) { if err := proto.Unmarshal(buf, &pb); err != nil { return nil, errors.Wrap(err, "failed to unmarshal block body") } - return bd.FromBodyProto(&pb) + b, err := bd.fromBodyProto(&pb) + if err != nil { + return nil, err + } + return &b, nil } diff --git a/blockchain/block/block_deserializer_test.go b/blockchain/block/block_deserializer_test.go index 23eb7330df..6f3788ed45 100644 --- a/blockchain/block/block_deserializer_test.go +++ b/blockchain/block/block_deserializer_test.go @@ -9,7 +9,6 @@ package block import ( "testing" - "github.com/golang/protobuf/proto" "github.com/iotexproject/go-pkgs/hash" "github.com/stretchr/testify/require" ) @@ -19,16 +18,15 @@ func TestBlockDeserializer(t *testing.T) { bd := Deserializer{} blk, err := bd.FromBlockProto(&_pbBlock) r.NoError(err) - body, err := bd.FromBodyProto(_pbBlock.Body) + body, err := bd.fromBodyProto(_pbBlock.Body) r.NoError(err) - r.Equal(body, &blk.Body) + r.Equal(body, blk.Body) txHash, err := blk.CalculateTxRoot() r.NoError(err) blk.Header.txRoot = txHash blk.Header.receiptRoot = hash.Hash256b(([]byte)("test")) - pb := blk.ConvertToBlockPb() - raw, err := proto.Marshal(pb) + raw, err := blk.Serialize() r.NoError(err) newblk, err := (&Deserializer{}).DeserializeBlock(raw) diff --git a/blockchain/block/block_test.go b/blockchain/block/block_test.go index d5db8931ed..523d43c6ad 100644 --- a/blockchain/block/block_test.go +++ b/blockchain/block/block_test.go @@ -125,25 +125,6 @@ var ( } ) -func TestConvertFromBlockPb(t *testing.T) { - blk := Block{} - require.NoError(t, blk.ConvertFromBlockPb(&_pbBlock, 0)) - - txHash, err := blk.CalculateTxRoot() - require.NoError(t, err) - - blk.Header.txRoot = txHash - blk.Header.receiptRoot = hash.Hash256b(([]byte)("test")) - - raw, err := blk.Serialize() - require.NoError(t, err) - - var newblk Block - err = newblk.Deserialize(raw, 0) - require.NoError(t, err) - require.Equal(t, blk, newblk) -} - func TestBlockCompressionSize(t *testing.T) { for _, n := range []int{1, 10, 100, 1000, 10000} { blk := makeBlock(t, n) diff --git a/blockchain/block/body.go b/blockchain/block/body.go index 2b665abe1e..44cbb20a13 100644 --- a/blockchain/block/body.go +++ b/blockchain/block/body.go @@ -37,30 +37,6 @@ func (b *Body) Serialize() ([]byte, error) { return proto.Marshal(b.Proto()) } -// LoadProto loads body from proto -func (b *Body) LoadProto(pbBlock *iotextypes.BlockBody, id uint32) error { - b.Actions = []action.SealedEnvelope{} - for _, actPb := range pbBlock.Actions { - act, err := (&action.Deserializer{}).SetEvmNetworkID(id).ActionToSealedEnvelope(actPb) - if err != nil { - return err - } - b.Actions = append(b.Actions, act) - } - - return nil -} - -// Deserialize parses the byte stream into a Block -func (b *Body) Deserialize(buf []byte, id uint32) error { - pb := iotextypes.BlockBody{} - if err := proto.Unmarshal(buf, &pb); err != nil { - return err - } - - return b.LoadProto(&pb, id) -} - // CalculateTxRoot returns the Merkle root of all txs and actions in this block. func (b *Body) CalculateTxRoot() (hash.Hash256, error) { return calculateTxRoot(b.Actions) diff --git a/blockchain/block/body_test.go b/blockchain/block/body_test.go index 8ed624195f..6390d796a9 100644 --- a/blockchain/block/body_test.go +++ b/blockchain/block/body_test.go @@ -36,15 +36,18 @@ func TestSerDer(t *testing.T) { body := Body{} ser, err := body.Serialize() require.NoError(err) - require.NoError(body.Deserialize(ser, 0)) - require.Equal(0, len(body.Actions)) + body2, err := (&Deserializer{}).DeserializeBody(ser) + require.NoError(err) + require.Equal(0, len(body2.Actions)) body, err = makeBody() require.NoError(err) ser, err = body.Serialize() require.NoError(err) - require.NoError(body.Deserialize(ser, 0)) - require.Equal(1, len(body.Actions)) + body2, err = (&Deserializer{}).DeserializeBody(ser) + require.NoError(err) + require.Equal(1, len(body2.Actions)) + require.Equal(&body, body2) } func TestLoadProto(t *testing.T) { @@ -52,15 +55,18 @@ func TestLoadProto(t *testing.T) { body := Body{} blockBody := body.Proto() require.NotNil(blockBody) - require.NoError(body.LoadProto(blockBody, 0)) - require.Equal(0, len(body.Actions)) + body2, err := (&Deserializer{}).fromBodyProto(blockBody) + require.NoError(err) + require.Equal(0, len(body2.Actions)) - body, err := makeBody() + body, err = makeBody() require.NoError(err) blockBody = body.Proto() require.NotNil(blockBody) - require.NoError(body.LoadProto(blockBody, 0)) - require.Equal(1, len(body.Actions)) + body2, err = (&Deserializer{}).fromBodyProto(blockBody) + require.NoError(err) + require.Equal(1, len(body2.Actions)) + require.Equal(body, body2) } func TestCalculateTxRoot(t *testing.T) { diff --git a/consensus/scheme/rolldpos/subchain_test.go b/consensus/scheme/rolldpos/subchain_test.go deleted file mode 100644 index 0ba07279e1..0000000000 --- a/consensus/scheme/rolldpos/subchain_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2019 IoTeX Foundation -// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no -// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent -// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache -// License 2.0 that can be found in the LICENSE file. - -package rolldpos - -import ( - "testing" - - "github.com/golang/mock/gomock" - "github.com/iotexproject/iotex-proto/golang/iotextypes" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/timestamppb" - - "github.com/iotexproject/iotex-core/action" - "github.com/iotexproject/iotex-core/blockchain/block" - "github.com/iotexproject/iotex-core/pkg/version" - "github.com/iotexproject/iotex-core/test/identityset" -) - -func TestPutBlockToParentChain(t *testing.T) { - t.Parallel() - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - pubKey := identityset.PrivateKey(27).PublicKey() - blk := block.Block{} - blkpb := &iotextypes.Block{ - Header: &iotextypes.BlockHeader{ - Core: &iotextypes.BlockHeaderCore{ - Version: version.ProtocolVersion, - Height: 123456789, - Timestamp: timestamppb.Now(), - }, - ProducerPubkey: pubKey.Bytes(), - }, - Body: &iotextypes.BlockBody{ - Actions: []*iotextypes.Action{ - { - Core: &iotextypes.ActionCore{ - Action: &iotextypes.ActionCore_Transfer{ - Transfer: &iotextypes.Transfer{}, - }, - Version: version.ProtocolVersion, - Nonce: 101, - }, - SenderPubKey: pubKey.Bytes(), - Signature: action.ValidSig, - }, - { - Core: &iotextypes.ActionCore{ - Action: &iotextypes.ActionCore_Transfer{ - Transfer: &iotextypes.Transfer{}, - }, - Version: version.ProtocolVersion, - Nonce: 102, - }, - SenderPubKey: pubKey.Bytes(), - Signature: action.ValidSig, - }, - }, - }, - } - require.NoError(t, blk.ConvertFromBlockPb(blkpb, 0)) - txRoot, err := blk.CalculateTxRoot() - require.NoError(t, err) - blkpb.Header.Core.TxRoot = txRoot[:] - blk = block.Block{} - require.NoError(t, blk.ConvertFromBlockPb(blkpb, 0)) -} From a221d57727d01cef829cbde4af25adc4adea5789 Mon Sep 17 00:00:00 2001 From: millken Date: Fri, 17 Jun 2022 09:49:27 +0800 Subject: [PATCH 03/24] [gRPC]Added chainid metrics (#3438) --- api/coreservice.go | 4 +--- api/grpcserver.go | 40 ++++++++++++++++++++++++++++++++++++++++ api/types/types.go | 4 +++- go.sum | 9 --------- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 01c6e3cf9f..783d8a27c1 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -58,9 +58,7 @@ import ( "github.com/iotexproject/iotex-core/state/factory" ) -const ( - _workerNumbers = 5 -) +const _workerNumbers int = 5 type ( // CoreService provides api interface for user to interact with blockchain data diff --git a/api/grpcserver.go b/api/grpcserver.go index b2e50289c9..2c30ead8e0 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -25,6 +25,7 @@ import ( "github.com/iotexproject/iotex-proto/golang/iotexapi" "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel/attribute" "go.uber.org/zap" @@ -33,6 +34,7 @@ import ( "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/peer" "google.golang.org/grpc/reflection" "google.golang.org/grpc/status" @@ -61,8 +63,28 @@ var ( Time: 60 * time.Second, // Ping the client if it is idle for 60 seconds to ensure the connection is still active Timeout: 10 * time.Second, // Wait 10 seconds for the ping ack before assuming the connection is dead } + + _apiCallSourceWithChainIDMtc = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "iotex_apicallsource_chainid_metrics", + Help: "API call Source ChainID Statistics", + }, + []string{"chain_id"}, + ) + _apiCallSourceWithOutChainIDMtc = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "iotex_apicallsource_nochainid_metrics", + Help: "API call Source Without ChainID Statistics", + }, + []string{"client_ip", "sender", "recipient"}, + ) ) +func init() { + prometheus.MustRegister(_apiCallSourceWithChainIDMtc) + prometheus.MustRegister(_apiCallSourceWithOutChainIDMtc) +} + // NewGRPCServer creates a new grpc server func NewGRPCServer(core CoreService, grpcPort int) *GRPCServer { if grpcPort == 0 { @@ -296,6 +318,24 @@ func (svr *GRPCServer) SendAction(ctx context.Context, in *iotexapi.SendActionRe // tags output span.SetAttributes(attribute.String("actType", fmt.Sprintf("%T", in.GetAction().GetCore()))) defer span.End() + chainID := strconv.FormatUint(uint64(in.GetAction().GetCore().GetChainID()), 10) + if in.GetAction().GetCore().GetChainID() > 0 { + _apiCallSourceWithChainIDMtc.WithLabelValues(chainID).Inc() + } else { + var clientIP, sender, recipient string + selp, err := (&action.Deserializer{}).ActionToSealedEnvelope(in.GetAction()) + if err != nil { + return nil, err + } + if p, ok := peer.FromContext(ctx); ok { + clientIP, _, _ = net.SplitHostPort(p.Addr.String()) + } + if senderAddr, err := address.FromBytes(selp.SrcPubkey().Hash()); err == nil { + sender = senderAddr.String() + } + recipient, _ = selp.Destination() + _apiCallSourceWithOutChainIDMtc.WithLabelValues(clientIP, sender, recipient).Inc() + } actHash, err := svr.coreService.SendAction(ctx, in.GetAction()) if err != nil { return nil, err diff --git a/api/types/types.go b/api/types/types.go index eca39c1d7f..3d618b2d4e 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -1,6 +1,8 @@ package apitypes -import "github.com/iotexproject/iotex-core/blockchain/block" +import ( + "github.com/iotexproject/iotex-core/blockchain/block" +) type ( // Web3ResponseWriter is writer for web3 request diff --git a/go.sum b/go.sum index 08fc6e57af..eec36516bb 100644 --- a/go.sum +++ b/go.sum @@ -133,7 +133,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -446,12 +445,9 @@ github.com/iotexproject/go-p2p v0.3.3 h1:qDGwaHu1oYG93PIcJAnY5Hl2iK0GoeAQewB0Qtv github.com/iotexproject/go-p2p v0.3.3/go.mod h1:MjgwpexfBxhgq0cDoqHCxMQ1cLkv96p3xZJ02LLVGLA= github.com/iotexproject/go-pkgs v0.1.5-0.20210604060651-be5ee19f2575/go.mod h1:ttXhcwrtODyh7JozpJlCml09CjP0pcKqTe2B0MbTGc8= github.com/iotexproject/go-pkgs v0.1.5/go.mod h1:ttXhcwrtODyh7JozpJlCml09CjP0pcKqTe2B0MbTGc8= -github.com/iotexproject/go-pkgs v0.1.6/go.mod h1:E+Fl0XQZz56EzXFajFET2yFoRGsIbL6wQooVIkSim3o= github.com/iotexproject/go-pkgs v0.1.12-0.20220209063039-b876814568a0 h1:2afEg5WhExrhmuLbd6oObvMyhE72H0n3vRTdT8JNAgA= github.com/iotexproject/go-pkgs v0.1.12-0.20220209063039-b876814568a0/go.mod h1:wPM/LtoKhMvekRefuHe+oKPOBSpxmCPxlIuiQHeLrfQ= github.com/iotexproject/iotex-address v0.2.4/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= -github.com/iotexproject/iotex-address v0.2.5/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= -github.com/iotexproject/iotex-address v0.2.6/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= github.com/iotexproject/iotex-address v0.2.8 h1:jaTR5pZe/ljiYW4OqHl9NKPs0h1o91Gi6FILOTaBCXw= github.com/iotexproject/iotex-address v0.2.8/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= github.com/iotexproject/iotex-antenna-go/v2 v2.5.1-0.20210604061028-2c2056a5bfdb/go.mod h1:NqFzRL8RtA3xfXGpYbs0IY71HDiD6Dh2hD9iYngKLIU= @@ -460,7 +456,6 @@ github.com/iotexproject/iotex-antenna-go/v2 v2.5.1/go.mod h1:8pDZcM45M0gY6jm3PoM github.com/iotexproject/iotex-election v0.3.5-0.20210611041425-20ddf674363d h1:/j1xCAC9YiG/8UKqYvycS/v3ddVsb1G7AMyLXOjeYI0= github.com/iotexproject/iotex-election v0.3.5-0.20210611041425-20ddf674363d/go.mod h1:GRWevxtqQ4gPMrd7Qxhr29/7aTgvjiTp+rFI9KMMZEo= github.com/iotexproject/iotex-proto v0.5.0/go.mod h1:Xg6REkv+nTZN+OC22xXIQuqKdTWWHwOAJEXCoMpDwtI= -github.com/iotexproject/iotex-proto v0.5.2/go.mod h1:Xg6REkv+nTZN+OC22xXIQuqKdTWWHwOAJEXCoMpDwtI= github.com/iotexproject/iotex-proto v0.5.10-0.20220415042310-0d4bcef3febf h1:WYy4bBinJXJBqkgIVQk7rTwQzW0d/Ci6DKQL6CnveM4= github.com/iotexproject/iotex-proto v0.5.10-0.20220415042310-0d4bcef3febf/go.mod h1:OfmLvjBmy5EYeLxxDv6kesJq+Mm3Adn5GKgDJgF9G9U= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -554,7 +549,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -792,7 +786,6 @@ github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux/v2 v2.2.0 h1:RwtpYZ2/wVviZ5+3pjC8qdQ4TKnrak0/E01N1UWoAFU= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= @@ -1374,7 +1367,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1469,7 +1461,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= From 6f33246fb96a1bf40b77a8bf668fc7b8e0000690 Mon Sep 17 00:00:00 2001 From: Nick Pocock Date: Fri, 17 Jun 2022 21:00:06 +0200 Subject: [PATCH 04/24] [ioctl] build node command into new ioctl (#3455) * Add build node command --- ioctl/newcmd/node/node.go | 39 ++++++++++++++++++++++++ ioctl/newcmd/node/node_test.go | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 ioctl/newcmd/node/node.go create mode 100644 ioctl/newcmd/node/node_test.go diff --git a/ioctl/newcmd/node/node.go b/ioctl/newcmd/node/node.go new file mode 100644 index 0000000000..2edadda33b --- /dev/null +++ b/ioctl/newcmd/node/node.go @@ -0,0 +1,39 @@ +package node + +import ( + "github.com/spf13/cobra" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" +) + +// Multi-language support +var ( + _nodeCmdUses = map[config.Language]string{ + config.English: "node", + config.Chinese: "node", + } + _nodeCmdShorts = map[config.Language]string{ + config.English: "Deal with nodes of IoTeX blockchain", + config.Chinese: "处理IoTeX区块链的节点", + } +) + +// NewNodeCmd represents the new node command. +func NewNodeCmd(client ioctl.Client) *cobra.Command { + nodeUses, _ := client.SelectTranslation(_nodeCmdUses) + nodeShorts, _ := client.SelectTranslation(_nodeCmdShorts) + + nc := &cobra.Command{ + Use: nodeUses, + Short: nodeShorts, + } + + nc.AddCommand(NewNodeDelegateCmd(client)) + nc.AddCommand(NewNodeRewardCmd(client)) + + client.SetEndpointWithFlag(nc.PersistentFlags().StringVar) + client.SetInsecureWithFlag(nc.PersistentFlags().BoolVar) + + return nc +} diff --git a/ioctl/newcmd/node/node_test.go b/ioctl/newcmd/node/node_test.go new file mode 100644 index 0000000000..16613a2243 --- /dev/null +++ b/ioctl/newcmd/node/node_test.go @@ -0,0 +1,55 @@ +package node + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNewNodeCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + client := mock_ioctlclient.NewMockClient(ctrl) + client.EXPECT().SelectTranslation(gomock.Any()).Return("node delegate", config.English).AnyTimes() + + testData := []struct { + endpoint string + insecure bool + }{ + { + endpoint: "111:222:333:444:5678", + insecure: false, + }, + { + endpoint: "", + insecure: true, + }, + } + for _, test := range testData { + callbackEndpoint := func(cb func(*string, string, string, string)) { + cb(&test.endpoint, "endpoint", test.endpoint, "endpoint usage") + } + callbackInsecure := func(cb func(*bool, string, bool, string)) { + cb(&test.insecure, "insecure", !test.insecure, "insecure usage") + } + client.EXPECT().SetEndpointWithFlag(gomock.Any()).Do(callbackEndpoint) + client.EXPECT().SetInsecureWithFlag(gomock.Any()).Do(callbackInsecure) + + cmd := NewNodeCmd(client) + result, err := util.ExecuteCmd(cmd) + require.NoError(err) + require.Contains(result, "Available Commands") + + result, err = util.ExecuteCmd(cmd, "--endpoint", "0.0.0.0:1", "--insecure") + require.NoError(err) + require.Contains(result, "Available Commands") + require.Equal("0.0.0.0:1", test.endpoint) + require.True(test.insecure) + } +} From 61d189f9190274f22e23cad08e8e301d9ecbd0d7 Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Mon, 20 Jun 2022 10:56:31 +0800 Subject: [PATCH 05/24] [ioctl] Build hdwallet import command line into new ioctl (#3419) * [ioctl] build hdwallet import command line into new ioctl Co-authored-by: huofei <68298506@qq.com> --- ioctl/client.go | 52 ++++++++++-- ioctl/client_test.go | 14 ++++ ioctl/newcmd/hdwallet/hdwallet.go | 13 ++- ioctl/newcmd/hdwallet/hdwalletimport.go | 81 +++++++++++++++++++ ioctl/newcmd/hdwallet/hdwalletimport_test.go | 55 +++++++++++++ .../mock/mock_ioctlclient/mock_ioctlclient.go | 43 ++++++++++ 6 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 ioctl/newcmd/hdwallet/hdwalletimport.go create mode 100644 ioctl/newcmd/hdwallet/hdwalletimport_test.go diff --git a/ioctl/client.go b/ioctl/client.go index 018072d927..9f2ade15c8 100644 --- a/ioctl/client.go +++ b/ioctl/client.go @@ -7,6 +7,7 @@ package ioctl import ( + "bufio" "bytes" "context" "crypto/ecdsa" @@ -28,6 +29,7 @@ import ( "github.com/iotexproject/iotex-core/ioctl/config" "github.com/iotexproject/iotex-core/ioctl/util" "github.com/iotexproject/iotex-core/ioctl/validator" + "github.com/iotexproject/iotex-core/pkg/util/fileutil" ) type ( @@ -75,15 +77,22 @@ type ( IsCryptoSm2() bool // QueryAnalyser sends request to Analyser endpoint QueryAnalyser(interface{}) (*http.Response, error) + // ReadInput reads the input from stdin + ReadInput() (string, error) + // WriteHdWalletConfigFile write encrypting mnemonic into config file + WriteHdWalletConfigFile(string, string) error + // IsHdWalletConfigFileExist return true if config file is existed, false if not existed + IsHdWalletConfigFileExist() bool } client struct { - cfg config.Config - conn *grpc.ClientConn - cryptoSm2 bool - configFilePath string - endpoint string - insecure bool + cfg config.Config + conn *grpc.ClientConn + cryptoSm2 bool + configFilePath string + endpoint string + insecure bool + hdWalletConfigFile string } // Option sets client construction parameter @@ -106,8 +115,9 @@ func EnableCryptoSm2() Option { // NewClient creates a new ioctl client func NewClient(cfg config.Config, configFilePath string, opts ...Option) Client { c := &client{ - cfg: cfg, - configFilePath: configFilePath, + cfg: cfg, + configFilePath: configFilePath, + hdWalletConfigFile: cfg.Wallet + "/hdwallet", } for _, opt := range opts { opt(c) @@ -310,6 +320,32 @@ func (c *client) QueryAnalyser(reqData interface{}) (*http.Response, error) { return resp, nil } +func (c *client) ReadInput() (string, error) { // notest + in := bufio.NewReader(os.Stdin) + line, err := in.ReadString('\n') + if err != nil { + return "", err + } + return line, nil +} + +func (c *client) WriteHdWalletConfigFile(mnemonic string, password string) error { + enctxt := append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...) + enckey := util.HashSHA256([]byte(password)) + out, err := util.Encrypt(enctxt, enckey) + if err != nil { + return errors.Wrap(err, "failed to encrypting mnemonic") + } + if err := os.WriteFile(c.hdWalletConfigFile, out, 0600); err != nil { + return errors.Wrapf(err, "failed to write to config file %s", c.hdWalletConfigFile) + } + return nil +} + +func (c *client) IsHdWalletConfigFileExist() bool { // notest + return fileutil.FileExists(c.hdWalletConfigFile) +} + func (m *ConfirmationMessage) String() string { line := fmt.Sprintf("%s\nOptions:", m.Info) for _, option := range m.Options { diff --git a/ioctl/client_test.go b/ioctl/client_test.go index c124f9b097..e6958d0036 100644 --- a/ioctl/client_test.go +++ b/ioctl/client_test.go @@ -343,6 +343,20 @@ func TestDeleteAlias(t *testing.T) { } } +func TestWriteHdWalletConfigFile(t *testing.T) { + r := require.New(t) + testPathWallet, err := os.MkdirTemp(os.TempDir(), "cfgWallet") + r.NoError(err) + defer testutil.CleanupPath(testPathWallet) + + c := NewClient(config.Config{ + Wallet: testPathWallet, + }, testPathWallet+"/config.default") + mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" + password := "123" + r.NoError(c.WriteHdWalletConfigFile(mnemonic, password)) +} + func writeTempConfig(t *testing.T, cfg *config.Config) string { r := require.New(t) testPathd, err := os.MkdirTemp(os.TempDir(), "testConfig") diff --git a/ioctl/newcmd/hdwallet/hdwallet.go b/ioctl/newcmd/hdwallet/hdwallet.go index 13ef752821..64e7496f87 100644 --- a/ioctl/newcmd/hdwallet/hdwallet.go +++ b/ioctl/newcmd/hdwallet/hdwallet.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 IoTeX Foundation +// Copyright (c) 2022 IoTeX Foundation // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -6,6 +6,17 @@ package hdwallet +import ( + "github.com/pkg/errors" +) + +// Errors +var ( + ErrPasswdNotMatch = errors.New("password doesn't match") +) + // DefaultRootDerivationPath for iotex // https://github.com/satoshilabs/slips/blob/master/slip-0044.md const DefaultRootDerivationPath = "m/44'/304'" + +var _hdWalletConfigFile string diff --git a/ioctl/newcmd/hdwallet/hdwalletimport.go b/ioctl/newcmd/hdwallet/hdwalletimport.go new file mode 100644 index 0000000000..33ed1f08ee --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletimport.go @@ -0,0 +1,81 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "strings" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/tyler-smith/go-bip39" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" +) + +// Multi-language support +var ( + _importCmdShorts = map[config.Language]string{ + config.English: "import hdwallet using mnemonic", + config.Chinese: "通过助记词导入钱包", + } + _importCmdUses = map[config.Language]string{ + config.English: "import", + config.Chinese: "import 导入", + } +) + +// NewHdwalletImportCmd represents the hdwallet import command +func NewHdwalletImportCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_importCmdUses) + short, _ := client.SelectTranslation(_importCmdShorts) + + return &cobra.Command{ + Use: use, + Short: short, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + if client.IsHdWalletConfigFileExist() { + cmd.Println("Please run 'ioctl hdwallet delete' before import") + return nil + } + + cmd.Println("Enter 12 mnemonic words you saved, separated by space") + + line, err := client.ReadInput() + if err != nil { + return err + } + mnemonic := strings.TrimSpace(line) + if _, err = bip39.MnemonicToByteArray(mnemonic); err != nil { + return err + } + + cmd.Println("Set password") + password, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + cmd.Println("Enter password again") + passwordAgain, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + if password != passwordAgain { + return ErrPasswdNotMatch + } + + if err := client.WriteHdWalletConfigFile(mnemonic, password); err != nil { + return errors.Wrap(err, "failed to write to config file") + } + cmd.Printf("Mnemonic phrase: %s\n"+ + "It is used to recover your wallet in case you forgot the password. Write them down and store it in a safe place.\n", mnemonic) + return nil + }, + } +} diff --git a/ioctl/newcmd/hdwallet/hdwalletimport_test.go b/ioctl/newcmd/hdwallet/hdwalletimport_test.go new file mode 100644 index 0000000000..e6beeb1605 --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletimport_test.go @@ -0,0 +1,55 @@ +// Copyright (c) 2022 IoTeX +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNewHdwalletImportCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + + mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" + password := "123" + + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(6) + client.EXPECT().IsHdWalletConfigFileExist().Return(false).Times(2) + + t.Run("import hdwallet", func(t *testing.T) { + client.EXPECT().ReadInput().Return(mnemonic, nil) + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().WriteHdWalletConfigFile(gomock.Any(), gomock.Any()).Return(nil) + + cmd := NewHdwalletImportCmd(client) + result, err := util.ExecuteCmd(cmd) + require.NoError(err) + require.Contains(result, mnemonic) + }) + + t.Run("failed to write to config file", func(t *testing.T) { + expectErr := errors.New("failed to write to config file") + client.EXPECT().ReadInput().Return(mnemonic, nil) + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().WriteHdWalletConfigFile(gomock.Any(), gomock.Any()).Return(expectErr) + + cmd := NewHdwalletImportCmd(client) + _, err := util.ExecuteCmd(cmd) + require.Contains(err.Error(), expectErr.Error()) + }) +} diff --git a/test/mock/mock_ioctlclient/mock_ioctlclient.go b/test/mock/mock_ioctlclient/mock_ioctlclient.go index 4d6526f319..fe20c71849 100644 --- a/test/mock/mock_ioctlclient/mock_ioctlclient.go +++ b/test/mock/mock_ioctlclient/mock_ioctlclient.go @@ -183,6 +183,20 @@ func (mr *MockClientMockRecorder) IsCryptoSm2() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCryptoSm2", reflect.TypeOf((*MockClient)(nil).IsCryptoSm2)) } +// IsHdWalletConfigFileExist mocks base method. +func (m *MockClient) IsHdWalletConfigFileExist() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsHdWalletConfigFileExist") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsHdWalletConfigFileExist indicates an expected call of IsHdWalletConfigFileExist. +func (mr *MockClientMockRecorder) IsHdWalletConfigFileExist() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHdWalletConfigFileExist", reflect.TypeOf((*MockClient)(nil).IsHdWalletConfigFileExist)) +} + // NewKeyStore mocks base method. func (m *MockClient) NewKeyStore() *keystore.KeyStore { m.ctrl.T.Helper() @@ -212,6 +226,21 @@ func (mr *MockClientMockRecorder) QueryAnalyser(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryAnalyser", reflect.TypeOf((*MockClient)(nil).QueryAnalyser), arg0) } +// ReadInput mocks base method. +func (m *MockClient) ReadInput() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadInput") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadInput indicates an expected call of ReadInput. +func (mr *MockClientMockRecorder) ReadInput() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadInput", reflect.TypeOf((*MockClient)(nil).ReadInput)) +} + // ReadSecret mocks base method. func (m *MockClient) ReadSecret() (string, error) { m.ctrl.T.Helper() @@ -333,3 +362,17 @@ func (mr *MockClientMockRecorder) WriteConfig() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteConfig", reflect.TypeOf((*MockClient)(nil).WriteConfig)) } + +// WriteHdWalletConfigFile mocks base method. +func (m *MockClient) WriteHdWalletConfigFile(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteHdWalletConfigFile", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteHdWalletConfigFile indicates an expected call of WriteHdWalletConfigFile. +func (mr *MockClientMockRecorder) WriteHdWalletConfigFile(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteHdWalletConfigFile", reflect.TypeOf((*MockClient)(nil).WriteHdWalletConfigFile), arg0, arg1) +} From 9c24171753869932a4d0656e7d67467221bde8d8 Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Mon, 20 Jun 2022 16:43:56 +0800 Subject: [PATCH 06/24] [ioctl] Build block bucket command line into new ioctl (#3386) * [ioctl] build block bucket command line into new ioctl Co-authored-by: huofei <68298506@qq.com> --- ioctl/newcmd/bc/bcbucket.go | 238 +++++++++++++++++++++++++++++++ ioctl/newcmd/bc/bcbucket_test.go | 74 ++++++++++ 2 files changed, 312 insertions(+) create mode 100644 ioctl/newcmd/bc/bcbucket.go create mode 100644 ioctl/newcmd/bc/bcbucket_test.go diff --git a/ioctl/newcmd/bc/bcbucket.go b/ioctl/newcmd/bc/bcbucket.go new file mode 100644 index 0000000000..1a6ad997b0 --- /dev/null +++ b/ioctl/newcmd/bc/bcbucket.go @@ -0,0 +1,238 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package bc + +import ( + "context" + "fmt" + "math/big" + "strconv" + "strings" + "time" + + "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" +) + +const ( + _bcBucketOptMax = "max" + _bcBucketOptCount = "count" +) + +// Multi-language support +var ( + _bcBucketUses = map[config.Language]string{ + config.English: "bucket [OPTION|BUCKET_INDEX]", + config.Chinese: "bucket [选项|票索引]", + } + _bcBucketCmdShorts = map[config.Language]string{ + config.English: "Get bucket for given index on IoTeX blockchain", + config.Chinese: "在IoTeX区块链上根据索引读取投票", + } + _bcBucketCmdExample = map[config.Language]string{ + config.English: "ioctl bc bucket [BUCKET_INDEX], to read bucket information by bucket index\n" + + "ioctl bc bucket max, to query the max bucket index\n" + + "ioctl bc bucket count, to query total number of active buckets", + config.Chinese: "ioctl bc bucket [BUCKET_INDEX], 依票索引取得投票资讯\n" + + "ioctl bc bucket max, 查询最大票索引\n" + + "ioctl bc bucket count, 查询活跃总票数", + } +) + +type bucket struct { + Index uint64 `json:"index"` + Owner string `json:"owner"` + Candidate string `json:"candidate"` + StakedAmount string `json:"stakedAmount"` + StakedDuration uint32 `json:"stakedDuration"` + AutoStake bool `json:"autoStake"` + CreateTime string `json:"createTime"` + StakeStartTime string `json:"stakeStartTime"` + UnstakeStartTime string `json:"unstakeStartTime"` +} + +// NewBCBucketCmd represents the bc Bucket command +func NewBCBucketCmd(client ioctl.Client) *cobra.Command { + bcBucketUses, _ := client.SelectTranslation(_bcBlockCmdUses) + bcBucketCmdShorts, _ := client.SelectTranslation(_bcBlockCmdShorts) + bcBucketCmdExample, _ := client.SelectTranslation(_bcBucketCmdExample) + + return &cobra.Command{ + Use: bcBucketUses, + Short: bcBucketCmdShorts, + Args: cobra.ExactArgs(1), + Example: bcBucketCmdExample, + RunE: func(cmd *cobra.Command, args []string) (err error) { + cmd.SilenceUsage = true + switch args[0] { + case _bcBucketOptMax: + count, err := getBucketsCount(client) + if err != nil { + return err + } + cmd.Println(count.GetTotal()) + case _bcBucketOptCount: + count, err := getBucketsCount(client) + if err != nil { + return err + } + cmd.Println(count.GetActive()) + default: + bucketindex, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + bucketpb, err := getBucketByIndex(client, bucketindex) + if err != nil { + return err + } + if bucketpb == nil { + return errors.New("The bucket has been withdrawn") + } + bucket, err := newBucket(bucketpb) + if err != nil { + return err + } + cmd.Println(bucket.String()) + } + return nil + }, + } +} + +func newBucket(bucketpb *iotextypes.VoteBucket) (*bucket, error) { + amount, ok := new(big.Int).SetString(bucketpb.StakedAmount, 10) + if !ok { + return nil, errors.New("failed to convert amount into big int") + } + unstakeStartTimeFormat := "none" + if err := bucketpb.UnstakeStartTime.CheckValid(); err != nil { + return nil, err + } + unstakeTime := bucketpb.UnstakeStartTime.AsTime() + if unstakeTime != time.Unix(0, 0).UTC() { + unstakeStartTimeFormat = unstakeTime.Format(time.RFC3339Nano) + } + return &bucket{ + Index: bucketpb.Index, + Owner: bucketpb.Owner, + Candidate: bucketpb.CandidateAddress, + StakedAmount: util.RauToString(amount, util.IotxDecimalNum), + StakedDuration: bucketpb.StakedDuration, + AutoStake: bucketpb.AutoStake, + CreateTime: bucketpb.CreateTime.AsTime().Format(time.RFC3339Nano), + StakeStartTime: bucketpb.StakeStartTime.AsTime().Format(time.RFC3339Nano), + UnstakeStartTime: unstakeStartTimeFormat, + }, nil +} + +func (b *bucket) String() string { + var lines []string + lines = append(lines, "{") + lines = append(lines, fmt.Sprintf(" index: %d", b.Index)) + lines = append(lines, fmt.Sprintf(" owner: %s", b.Owner)) + lines = append(lines, fmt.Sprintf(" candidate: %s", b.Candidate)) + lines = append(lines, fmt.Sprintf(" stakedAmount: %s IOTX", b.StakedAmount)) + lines = append(lines, fmt.Sprintf(" stakedDuration: %d days", b.StakedDuration)) + lines = append(lines, fmt.Sprintf(" autoStake: %v", b.AutoStake)) + lines = append(lines, fmt.Sprintf(" createTime: %s", b.CreateTime)) + lines = append(lines, fmt.Sprintf(" stakeStartTime: %s", b.StakeStartTime)) + lines = append(lines, fmt.Sprintf(" unstakeStartTime: %s", b.UnstakeStartTime)) + lines = append(lines, "}") + return strings.Join(lines, "\n") +} + +func getBucketByIndex(client ioctl.Client, index uint64) (*iotextypes.VoteBucket, error) { + method := &iotexapi.ReadStakingDataMethod{ + Method: iotexapi.ReadStakingDataMethod_BUCKETS_BY_INDEXES, + } + readStakingdataRequest := &iotexapi.ReadStakingDataRequest{ + Request: &iotexapi.ReadStakingDataRequest_BucketsByIndexes{ + BucketsByIndexes: &iotexapi.ReadStakingDataRequest_VoteBucketsByIndexes{ + Index: []uint64{index}, + }, + }, + } + response, err := getBuckets(client, method, readStakingdataRequest) + if err != nil { + return nil, err + } + buckets := iotextypes.VoteBucketList{} + if err := proto.Unmarshal(response.Data, &buckets); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal response") + } + if len(buckets.GetBuckets()) == 0 { + return nil, errors.New("zero len response") + } + return buckets.GetBuckets()[0], nil +} + +func getBucketsCount(client ioctl.Client) (count *iotextypes.BucketsCount, err error) { + method := &iotexapi.ReadStakingDataMethod{ + Method: iotexapi.ReadStakingDataMethod_BUCKETS_COUNT, + } + readStakingdataRequest := &iotexapi.ReadStakingDataRequest{ + Request: &iotexapi.ReadStakingDataRequest_BucketsCount_{ + BucketsCount: &iotexapi.ReadStakingDataRequest_BucketsCount{}, + }, + } + response, err := getBuckets(client, method, readStakingdataRequest) + if err != nil { + return nil, err + } + count = &iotextypes.BucketsCount{} + if err := proto.Unmarshal(response.Data, count); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal response") + } + return count, nil +} + +func getBuckets(client ioctl.Client, method *iotexapi.ReadStakingDataMethod, readStakingdataRequest *iotexapi.ReadStakingDataRequest) (response *iotexapi.ReadStateResponse, err error) { + apiClient, err := client.APIServiceClient() + if err != nil { + return nil, errors.Wrap(err, "failed to connect to endpoint") + } + methodData, err := proto.Marshal(method) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal read staking data method") + } + requestData, err := proto.Marshal(readStakingdataRequest) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal read staking data request") + } + + request := &iotexapi.ReadStateRequest{ + ProtocolID: []byte("staking"), + MethodName: methodData, + Arguments: [][]byte{requestData}, + } + + ctx := context.Background() + jwtMD, err := util.JwtAuth() + if err == nil { + ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx) + } + + response, err = apiClient.ReadState(ctx, request) + if err != nil { + sta, ok := status.FromError(err) + if ok { + return nil, errors.New(sta.Message()) + } + return nil, errors.Wrap(err, "failed to invoke ReadState api") + } + return response, nil +} diff --git a/ioctl/newcmd/bc/bcbucket_test.go b/ioctl/newcmd/bc/bcbucket_test.go new file mode 100644 index 0000000000..fb7617edff --- /dev/null +++ b/ioctl/newcmd/bc/bcbucket_test.go @@ -0,0 +1,74 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package bc + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotexapi/mock_iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" + "github.com/iotexproject/iotex-core/testutil" +) + +func TestBCBucketCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) + client.EXPECT().SelectTranslation(gomock.Any()).Return("", config.English).Times(9) + + t.Run("get total blockchain bucket count", func(t *testing.T) { + client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(2) + apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.All()).Return(&iotexapi.ReadStateResponse{}, nil) + + cmd := NewBCBucketCmd(client) + result, err := util.ExecuteCmd(cmd, "max") + require.NoError(err) + require.Equal("0\n", result) + }) + + t.Run("get active blockchain bucket count", func(t *testing.T) { + client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(2) + apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.All()).Return(&iotexapi.ReadStateResponse{}, nil) + + cmd := NewBCBucketCmd(client) + result, err := util.ExecuteCmd(cmd, "count") + require.NoError(err) + require.Equal("0\n", result) + }) + + t.Run("get default blockchain bucket count", func(t *testing.T) { + cfg := config.Config{} + vb := &iotextypes.VoteBucket{ + Index: 1, + StakedAmount: "10", + UnstakeStartTime: timestamppb.New(testutil.TimestampNow()), + } + vblist, err := proto.Marshal(&iotextypes.VoteBucketList{ + Buckets: []*iotextypes.VoteBucket{vb}, + }) + require.NoError(err) + client.EXPECT().Config().Return(cfg).Times(1) + apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.All()).Return(&iotexapi.ReadStateResponse{ + Data: vblist, + }, nil) + + cmd := NewBCBucketCmd(client) + result, err := util.ExecuteCmd(cmd, "0") + require.NoError(err) + require.Contains(result, "index: 1") + }) +} From 1f10a0f7d975e8258e8bf3f3cce037ad680aa24a Mon Sep 17 00:00:00 2001 From: huofei <68298506@qq.com> Date: Thu, 23 Jun 2022 11:49:19 +0800 Subject: [PATCH 07/24] [ioctl] create main for ioctl/newcmd (#3296) * create main for ioctl/newcmd --- Makefile | 20 ++++ ioctl/newcmd/account/account.go | 2 + ioctl/newcmd/config/config.go | 165 ++++++++++++++++++++++++++++ ioctl/newcmd/config/config_get.go | 7 ++ ioctl/newcmd/config/config_reset.go | 7 ++ ioctl/newcmd/config/config_set.go | 7 ++ ioctl/newcmd/config/config_test.go | 33 ++++++ ioctl/newcmd/root.go | 79 +++++++++++++ ioctl/newcmd/root_test.go | 40 +++++++ tools/newioctl/ioctl.go | 27 +++++ tools/newxctl/xctl.go | 27 +++++ 11 files changed, 414 insertions(+) create mode 100644 ioctl/newcmd/config/config.go create mode 100644 ioctl/newcmd/config/config_get.go create mode 100644 ioctl/newcmd/config/config_reset.go create mode 100644 ioctl/newcmd/config/config_set.go create mode 100644 ioctl/newcmd/config/config_test.go create mode 100644 ioctl/newcmd/root.go create mode 100644 ioctl/newcmd/root_test.go create mode 100644 tools/newioctl/ioctl.go create mode 100644 tools/newxctl/xctl.go diff --git a/Makefile b/Makefile index 5ef054f531..69278533b6 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,9 @@ BUILD_TARGET_SERVER=server BUILD_TARGET_ACTINJV2=actioninjectorv2 BUILD_TARGET_ADDRGEN=addrgen BUILD_TARGET_IOCTL=ioctl +BUILD_TARGET_NEWIOCTL=newioctl BUILD_TARGET_XCTL=xctl +BUILD_TARGET_NEWXCTL=newxctl BUILD_TARGET_MINICLUSTER=minicluster BUILD_TARGET_RECOVER=recover BUILD_TARGET_IOMIGRATER=iomigrater @@ -218,6 +220,10 @@ recover: .PHONY: ioctl ioctl: $(GOBUILD) -ldflags "$(PackageFlags)" -o ./bin/$(BUILD_TARGET_IOCTL) -v ./tools/ioctl + +.PHONY: newioctl +newioctl: + $(GOBUILD) -ldflags "$(PackageFlags)" -o ./bin/$(BUILD_TARGET_NEWIOCTL) -v ./tools/newioctl .PHONY: ioctl-cross ioctl-cross: @@ -229,10 +235,24 @@ ioctl-cross: cd $(GOPATH)/src && $(GOPATH)/bin/xgo --targets=$(BUILD_TARGET_OS)/$(BUILD_TARGET_ARCH) . mkdir -p ./bin/$(BUILD_TARGET_IOCTL) && sudo mv $(GOPATH)/src/main-$(BUILD_TARGET_OS)-$(BUILD_TARGET_ARCH) ./bin/$(BUILD_TARGET_IOCTL)/ioctl-$(BUILD_TARGET_OS)-$(BUILD_TARGET_ARCH) +.PHONY: newioctl-cross +newioctl-cross: + $(DOCKERCMD) pull techknowlogick/xgo:latest + $(GOCMD) get src.techknowlogick.com/xgo + mkdir -p $(GOPATH)/src + sudo cp ./tools/newioctl/ioctl.go $(GOPATH)/src + cd $(GOPATH)/src && sudo rm -f go.mod && $(GOCMD) mod init main && $(GOCMD) mod tidy + cd $(GOPATH)/src && $(GOPATH)/bin/xgo --targets=$(BUILD_TARGET_OS)/$(BUILD_TARGET_ARCH) . + mkdir -p ./bin/$(BUILD_TARGET_NEWIOCTL) && sudo mv $(GOPATH)/src/main-$(BUILD_TARGET_OS)-$(BUILD_TARGET_ARCH) ./bin/$(BUILD_TARGET_NEWIOCTL)/ioctl-$(BUILD_TARGET_OS)-$(BUILD_TARGET_ARCH) + .PHONY: xctl xctl: $(GOBUILD) -ldflags "$(PackageFlags)" -o ./bin/$(BUILD_TARGET_XCTL) -v ./tools/xctl +.PHONY: newxctl +newxctl: + $(GOBUILD) -ldflags "$(PackageFlags)" -o ./bin/$(BUILD_TARGET_NEWXCTL) -v ./tools/newxctl + .PHONY: iomigrater iomigrater: $(GOBUILD) -ldflags "$(PackageFlags)" -o ./bin/$(BUILD_TARGET_IOMIGRATER) -v ./tools/iomigrater diff --git a/ioctl/newcmd/account/account.go b/ioctl/newcmd/account/account.go index 1e8eb35977..98b68915c3 100644 --- a/ioctl/newcmd/account/account.go +++ b/ioctl/newcmd/account/account.go @@ -62,6 +62,7 @@ func NewAccountCmd(client ioctl.Client) *cobra.Command { Short: accountShorts, } ac.AddCommand(NewAccountCreate(client)) + ac.AddCommand(NewAccountCreateAdd(client)) ac.AddCommand(NewAccountDelete(client)) ac.AddCommand(NewAccountNonce(client)) ac.AddCommand(NewAccountList(client)) @@ -73,6 +74,7 @@ func NewAccountCmd(client ioctl.Client) *cobra.Command { ac.AddCommand(NewAccountExportPublic(client)) ac.AddCommand(NewAccountExport(client)) ac.AddCommand(NewAccountImportCmd(client)) + ac.AddCommand(NewAccountBalance(client)) client.SetEndpointWithFlag(ac.PersistentFlags().StringVar) client.SetInsecureWithFlag(ac.PersistentFlags().BoolVar) diff --git a/ioctl/newcmd/config/config.go b/ioctl/newcmd/config/config.go new file mode 100644 index 0000000000..6b06359f56 --- /dev/null +++ b/ioctl/newcmd/config/config.go @@ -0,0 +1,165 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package config + +import ( + "fmt" + "os" + "path" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/pkg/errors" + "gopkg.in/yaml.v2" + + serverCfg "github.com/iotexproject/iotex-core/config" + "github.com/iotexproject/iotex-core/ioctl/config" +) + +// Regexp patterns +const ( + _ipPattern = `((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)` + _domainPattern = `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}` + _urlPattern = `[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)` + _localPattern = "localhost" + _endpointPattern = "(" + _ipPattern + "|(" + _domainPattern + ")" + "|(" + _localPattern + "))" + `(:\d{1,5})?` + _defaultAnalyserEndpoint = "https://iotex-analyser-api-mainnet.chainanalytics.org" + _defaultConfigFileName = "config.default" +) + +var ( + _supportedLanguage = []string{"English", "中文"} + _validArgs = []string{"endpoint", "wallet", "explorer", "defaultacc", "language", "nsv2height"} + _validGetArgs = []string{"endpoint", "wallet", "explorer", "defaultacc", "language", "nsv2height", "analyserEndpoint", "all"} + _validExpl = []string{"iotexscan", "iotxplorer"} + _endpointCompile = regexp.MustCompile("^" + _endpointPattern + "$") + _configDir = os.Getenv("HOME") + "/.config/ioctl/default" +) + +// info contains the information of config file +type info struct { + readConfig config.Config + defaultConfigFile string // Path to config file +} + +// InitConfig load config data from default config file +func InitConfig() (config.Config, string, error) { + info := &info{ + readConfig: config.Config{ + Aliases: make(map[string]string), + }, + } + + // Create path to config directory + err := os.MkdirAll(_configDir, 0700) + if err != nil { + return info.readConfig, info.defaultConfigFile, err + } + info.defaultConfigFile = filepath.Join(_configDir, _defaultConfigFileName) + + // Load or reset config file + err = info.loadConfig() + if os.IsNotExist(err) { + err = info.reset() // Config file doesn't exist + } else if err != nil { + return info.readConfig, info.defaultConfigFile, err + } + + // Check completeness of config file + completeness := true + if info.readConfig.Wallet == "" { + info.readConfig.Wallet = _configDir + completeness = false + } + if info.readConfig.Language == "" { + info.readConfig.Language = _supportedLanguage[0] + completeness = false + } + if info.readConfig.Nsv2height == 0 { + info.readConfig.Nsv2height = serverCfg.Default.Genesis.FairbankBlockHeight + } + if info.readConfig.AnalyserEndpoint == "" { + info.readConfig.AnalyserEndpoint = _defaultAnalyserEndpoint + completeness = false + } + if !completeness { + if err = info.writeConfig(); err != nil { + return info.readConfig, info.defaultConfigFile, err + } + } + // Set language for ioctl + if info.isSupportedLanguage(info.readConfig.Language) == -1 { + fmt.Printf("Warn: Language %s is not supported, English instead.\n", info.readConfig.Language) + } + return info.readConfig, info.defaultConfigFile, nil +} + +// newInfo create config info +func newInfo(readConfig config.Config, defaultConfigFile string) *info { + return &info{ + readConfig: readConfig, + defaultConfigFile: defaultConfigFile, + } +} + +// reset resets all values of config +func (c *info) reset() error { + c.readConfig.Wallet = path.Dir(c.defaultConfigFile) + c.readConfig.Endpoint = "" + c.readConfig.SecureConnect = true + c.readConfig.DefaultAccount = *new(config.Context) + c.readConfig.Explorer = _validExpl[0] + c.readConfig.Language = _supportedLanguage[0] + c.readConfig.AnalyserEndpoint = _defaultAnalyserEndpoint + + err := c.writeConfig() + if err != nil { + return err + } + + fmt.Println("Config set to default values") + return nil +} + +// isSupportedLanguage checks if the language is a supported option and returns index when supported +func (c *info) isSupportedLanguage(arg string) config.Language { + if index, err := strconv.Atoi(arg); err == nil && index >= 0 && index < len(_supportedLanguage) { + return config.Language(index) + } + for i, lang := range _supportedLanguage { + if strings.EqualFold(arg, lang) { + return config.Language(i) + } + } + return config.Language(-1) +} + +// writeConfig writes to config file +func (c *info) writeConfig() error { + out, err := yaml.Marshal(&c.readConfig) + if err != nil { + return errors.Wrap(err, "failed to marshal config") + } + if err := os.WriteFile(c.defaultConfigFile, out, 0600); err != nil { + return errors.Wrap(err, fmt.Sprintf("failed to write to config file %s", c.defaultConfigFile)) + } + return nil +} + +// loadConfig loads config file in yaml format +func (c *info) loadConfig() error { + in, err := os.ReadFile(c.defaultConfigFile) + if err != nil { + return err + } + if err = yaml.Unmarshal(in, &c.readConfig); err != nil { + return errors.Wrap(err, "failed to unmarshal config") + } + return nil +} diff --git a/ioctl/newcmd/config/config_get.go b/ioctl/newcmd/config/config_get.go new file mode 100644 index 0000000000..96afdd8d01 --- /dev/null +++ b/ioctl/newcmd/config/config_get.go @@ -0,0 +1,7 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package config diff --git a/ioctl/newcmd/config/config_reset.go b/ioctl/newcmd/config/config_reset.go new file mode 100644 index 0000000000..96afdd8d01 --- /dev/null +++ b/ioctl/newcmd/config/config_reset.go @@ -0,0 +1,7 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package config diff --git a/ioctl/newcmd/config/config_set.go b/ioctl/newcmd/config/config_set.go new file mode 100644 index 0000000000..96afdd8d01 --- /dev/null +++ b/ioctl/newcmd/config/config_set.go @@ -0,0 +1,7 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package config diff --git a/ioctl/newcmd/config/config_test.go b/ioctl/newcmd/config/config_test.go new file mode 100644 index 0000000000..a3bf3a2e22 --- /dev/null +++ b/ioctl/newcmd/config/config_test.go @@ -0,0 +1,33 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package config + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/testutil" +) + +func TestInitConfig(t *testing.T) { + require := require.New(t) + testPath, err := os.MkdirTemp(os.TempDir(), "testCfg") + require.NoError(err) + defer func() { + testutil.CleanupPath(testPath) + }() + _configDir = testPath + cfg, cfgFilePath, err := InitConfig() + require.NoError(err) + require.Equal(testPath, cfg.Wallet) + require.Equal(_validExpl[0], cfg.Explorer) + require.Equal(_supportedLanguage[0], cfg.Language) + require.Equal(filepath.Join(testPath, _defaultConfigFileName), cfgFilePath) +} diff --git a/ioctl/newcmd/root.go b/ioctl/newcmd/root.go new file mode 100644 index 0000000000..a3004b3167 --- /dev/null +++ b/ioctl/newcmd/root.go @@ -0,0 +1,79 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package newcmd + +import ( + "github.com/spf13/cobra" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/newcmd/account" +) + +// Multi-language support +var ( + _ioctlRootCmdShorts = map[config.Language]string{ + config.English: "Command-line interface for IoTeX blockchain", + config.Chinese: "IoTeX区块链命令行工具", + } + _ioctlRootCmdLongs = map[config.Language]string{ + config.English: `ioctl is a command-line interface for interacting with IoTeX blockchain.`, + config.Chinese: `ioctl 是用于与IoTeX区块链进行交互的命令行工具`, + } + _ioctlRootCmdUses = map[config.Language]string{ + config.English: "ioctl", + config.Chinese: "ioctl", + } + _xctlRootCmdShorts = map[config.Language]string{ + config.English: "Command-line interface for consortium blockchain", + config.Chinese: "联盟链命令行工具", + } + _xctlRootCmdLongs = map[config.Language]string{ + config.English: `xctl is a command-line interface for interacting with consortium blockchain.`, + config.Chinese: `xctl 是用于与联盟链进行交互的命令行工具`, + } + _xctlRootCmdUses = map[config.Language]string{ + config.English: "xctl", + config.Chinese: "xctl", + } +) + +// NewIoctl returns ioctl root cmd +func NewIoctl(client ioctl.Client) *cobra.Command { + rootUses, _ := client.SelectTranslation(_ioctlRootCmdUses) + rootShorts, _ := client.SelectTranslation(_ioctlRootCmdShorts) + rootLongs, _ := client.SelectTranslation(_ioctlRootCmdLongs) + + rootCmd := &cobra.Command{ + Use: rootUses, + Short: rootShorts, + Long: rootLongs, + } + + rootCmd.AddCommand(config.ConfigCmd) + rootCmd.AddCommand(account.NewAccountCmd(client)) + + return rootCmd +} + +// NewXctl returns xctl root cmd +func NewXctl(client ioctl.Client) *cobra.Command { + rootUses, _ := client.SelectTranslation(_xctlRootCmdUses) + rootShorts, _ := client.SelectTranslation(_xctlRootCmdShorts) + rootLongs, _ := client.SelectTranslation(_xctlRootCmdLongs) + + var rootCmd = &cobra.Command{ + Use: rootUses, + Short: rootShorts, + Long: rootLongs, + } + + rootCmd.AddCommand(config.ConfigCmd) + rootCmd.AddCommand(account.NewAccountCmd(client)) + + return rootCmd +} diff --git a/ioctl/newcmd/root_test.go b/ioctl/newcmd/root_test.go new file mode 100644 index 0000000000..0578f634ac --- /dev/null +++ b/ioctl/newcmd/root_test.go @@ -0,0 +1,40 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package newcmd + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNew(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + defer ctrl.Finish() + client := mock_ioctlclient.NewMockClient(ctrl) + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).AnyTimes() + client.EXPECT().SetEndpointWithFlag(gomock.Any()).Do(func(_ func(*string, string, string, string)) {}).AnyTimes() + client.EXPECT().SetInsecureWithFlag(gomock.Any()).Do(func(_ func(*bool, string, bool, string)) {}).AnyTimes() + + cmds := []*cobra.Command{ + NewIoctl(client), + NewXctl(client), + } + for _, cmd := range cmds { + result, err := util.ExecuteCmd(cmd) + require.NoError(err) + require.Contains(result, "Available Commands") + require.Contains(result, "Flags") + } +} diff --git a/tools/newioctl/ioctl.go b/tools/newioctl/ioctl.go new file mode 100644 index 0000000000..7964371275 --- /dev/null +++ b/tools/newioctl/ioctl.go @@ -0,0 +1,27 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package main + +import ( + "os" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/newcmd" + "github.com/iotexproject/iotex-core/ioctl/newcmd/config" + "github.com/iotexproject/iotex-core/pkg/log" +) + +func main() { + readConfig, defaultConfigFile, err := config.InitConfig() + if err != nil { + log.L().Panic(err.Error()) + } + client := ioctl.NewClient(readConfig, defaultConfigFile) + if err := newcmd.NewIoctl(client).Execute(); err != nil { + os.Exit(1) + } +} diff --git a/tools/newxctl/xctl.go b/tools/newxctl/xctl.go new file mode 100644 index 0000000000..c549583b89 --- /dev/null +++ b/tools/newxctl/xctl.go @@ -0,0 +1,27 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package main + +import ( + "os" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/newcmd" + "github.com/iotexproject/iotex-core/ioctl/newcmd/config" + "github.com/iotexproject/iotex-core/pkg/log" +) + +func main() { + readConfig, defaultConfigFile, err := config.InitConfig() + if err != nil { + log.L().Panic(err.Error()) + } + client := ioctl.NewClient(readConfig, defaultConfigFile, ioctl.EnableCryptoSm2()) + if err := newcmd.NewXctl(client).Execute(); err != nil { + os.Exit(1) + } +} From 6e3375385c2eca62adf0d460605f97fc99efb5c8 Mon Sep 17 00:00:00 2001 From: huofei <68298506@qq.com> Date: Fri, 24 Jun 2022 02:07:11 +0800 Subject: [PATCH 08/24] [action] add evm london test (#3402) --- action/protocol/execution/protocol_test.go | 113 +++- .../CVE-2021-39137-attack-replay.json | 36 ++ .../testdata-london/array-return.json | 45 ++ .../testdata-london/array-return.sol | 34 ++ .../testdata-london/basic-token.json | 57 ++ .../execution/testdata-london/basic-token.sol | 18 + .../testdata-london/call-dynamic.json | 36 ++ .../testdata-london/call-dynamic.sol | 16 + .../testdata-london/chainid-selfbalance.json | 66 ++ .../testdata-london/chainid-selfbalance.sol | 19 + .../testdata-london/changestate.json | 58 ++ .../execution/testdata-london/changestate.sol | 15 + .../execution/testdata-london/datacopy.json | 38 ++ .../execution/testdata-london/datacopy.sol | 34 ++ .../execution/testdata-london/f.value.json | 48 ++ .../execution/testdata-london/f.value.sol | 28 + .../execution/testdata-london/gas-test.json | 568 ++++++++++++++++++ .../execution/testdata-london/gas-test.sol | 33 + .../testdata-london/infiniteloop.json | 69 +++ .../testdata-london/infiniteloop.sol | 29 + .../testdata-london/mapping-delete.json | 33 + .../testdata-london/mapping-delete.sol | 18 + .../execution/testdata-london/maxtime.json | 136 +++++ .../execution/testdata-london/maxtime.sol | 56 ++ .../execution/testdata-london/modifiers.json | 55 ++ .../execution/testdata-london/modifiers.sol | 37 ++ .../execution/testdata-london/multisend.json | 139 +++++ .../execution/testdata-london/multisend.sol | 36 ++ .../no-variable-length-returns.json | 69 +++ .../no-variable-length-returns.sol | 31 + .../testdata-london/public-mapping.json | 70 +++ .../testdata-london/public-mapping.sol | 24 + .../testdata-london/reentry-attack.json | 79 +++ .../testdata-london/reentry-attack.sol | 42 ++ .../testdata-london/remove-from-array.json | 45 ++ .../testdata-london/remove-from-array.sol | 44 ++ .../testdata-london/self-destruct.json | 69 +++ .../testdata-london/self-destruct.sol | 24 + .../execution/testdata-london/send-eth.json | 38 ++ .../execution/testdata-london/send-eth.sol | 29 + .../execution/testdata-london/sha3.json | 190 ++++++ .../execution/testdata-london/sha3.sol | 76 +++ .../testdata-london/storage-test.json | 545 +++++++++++++++++ .../testdata-london/storage-test.sol | 13 + .../testdata-london/tail-recursion.json | 59 ++ .../testdata-london/tail-recursion.sol | 28 + .../execution/testdata-london/tuple.json | 35 ++ .../execution/testdata-london/tuple.sol | 15 + .../testdata-london/wireconnection.json | 47 ++ .../testdata-london/wireconnection.sol | 27 + 50 files changed, 3467 insertions(+), 2 deletions(-) create mode 100644 action/protocol/execution/testdata-london/CVE-2021-39137-attack-replay.json create mode 100644 action/protocol/execution/testdata-london/array-return.json create mode 100644 action/protocol/execution/testdata-london/array-return.sol create mode 100644 action/protocol/execution/testdata-london/basic-token.json create mode 100644 action/protocol/execution/testdata-london/basic-token.sol create mode 100644 action/protocol/execution/testdata-london/call-dynamic.json create mode 100644 action/protocol/execution/testdata-london/call-dynamic.sol create mode 100644 action/protocol/execution/testdata-london/chainid-selfbalance.json create mode 100644 action/protocol/execution/testdata-london/chainid-selfbalance.sol create mode 100644 action/protocol/execution/testdata-london/changestate.json create mode 100644 action/protocol/execution/testdata-london/changestate.sol create mode 100644 action/protocol/execution/testdata-london/datacopy.json create mode 100644 action/protocol/execution/testdata-london/datacopy.sol create mode 100644 action/protocol/execution/testdata-london/f.value.json create mode 100644 action/protocol/execution/testdata-london/f.value.sol create mode 100644 action/protocol/execution/testdata-london/gas-test.json create mode 100644 action/protocol/execution/testdata-london/gas-test.sol create mode 100644 action/protocol/execution/testdata-london/infiniteloop.json create mode 100644 action/protocol/execution/testdata-london/infiniteloop.sol create mode 100644 action/protocol/execution/testdata-london/mapping-delete.json create mode 100644 action/protocol/execution/testdata-london/mapping-delete.sol create mode 100644 action/protocol/execution/testdata-london/maxtime.json create mode 100644 action/protocol/execution/testdata-london/maxtime.sol create mode 100644 action/protocol/execution/testdata-london/modifiers.json create mode 100644 action/protocol/execution/testdata-london/modifiers.sol create mode 100644 action/protocol/execution/testdata-london/multisend.json create mode 100644 action/protocol/execution/testdata-london/multisend.sol create mode 100644 action/protocol/execution/testdata-london/no-variable-length-returns.json create mode 100644 action/protocol/execution/testdata-london/no-variable-length-returns.sol create mode 100644 action/protocol/execution/testdata-london/public-mapping.json create mode 100644 action/protocol/execution/testdata-london/public-mapping.sol create mode 100644 action/protocol/execution/testdata-london/reentry-attack.json create mode 100644 action/protocol/execution/testdata-london/reentry-attack.sol create mode 100644 action/protocol/execution/testdata-london/remove-from-array.json create mode 100644 action/protocol/execution/testdata-london/remove-from-array.sol create mode 100644 action/protocol/execution/testdata-london/self-destruct.json create mode 100644 action/protocol/execution/testdata-london/self-destruct.sol create mode 100644 action/protocol/execution/testdata-london/send-eth.json create mode 100644 action/protocol/execution/testdata-london/send-eth.sol create mode 100644 action/protocol/execution/testdata-london/sha3.json create mode 100644 action/protocol/execution/testdata-london/sha3.sol create mode 100644 action/protocol/execution/testdata-london/storage-test.json create mode 100644 action/protocol/execution/testdata-london/storage-test.sol create mode 100644 action/protocol/execution/testdata-london/tail-recursion.json create mode 100644 action/protocol/execution/testdata-london/tail-recursion.sol create mode 100644 action/protocol/execution/testdata-london/tuple.json create mode 100644 action/protocol/execution/testdata-london/tuple.sol create mode 100644 action/protocol/execution/testdata-london/wireconnection.json create mode 100644 action/protocol/execution/testdata-london/wireconnection.sol diff --git a/action/protocol/execution/protocol_test.go b/action/protocol/execution/protocol_test.go index e2f94721e4..40ba0e3a3d 100644 --- a/action/protocol/execution/protocol_test.go +++ b/action/protocol/execution/protocol_test.go @@ -17,6 +17,8 @@ import ( "os" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -64,6 +66,7 @@ type ( GenesisBlockHeight struct { IsBering bool `json:"isBering"` IsIceland bool `json:"isIceland"` + IsLondon bool `json:"isLondon"` } Log struct { @@ -71,6 +74,11 @@ type ( Data string `json:"data"` } + AccessTuple struct { + Address string `json:"address"` + StorageKeys []string `json:"storageKeys"` + } + ExecutionConfig struct { Comment string `json:"comment"` ContractIndex int `json:"contractIndex"` @@ -83,6 +91,7 @@ type ( RawAmount string `json:"rawAmount"` RawGasLimit uint `json:"rawGasLimit"` RawGasPrice string `json:"rawGasPrice"` + RawAccessList []AccessTuple `json:"rawAccessList"` Failed bool `json:"failed"` RawReturnValue string `json:"rawReturnValue"` RawExpectedGasConsumed uint `json:"rawExpectedGasConsumed"` @@ -188,6 +197,23 @@ func (cfg *ExecutionConfig) GasLimit() uint64 { return uint64(cfg.RawGasLimit) } +func (cfg *ExecutionConfig) AccessList() types.AccessList { + if len(cfg.RawAccessList) == 0 { + return nil + } + accessList := make(types.AccessList, len(cfg.RawAccessList)) + for i, rawAccessList := range cfg.RawAccessList { + accessList[i].Address = common.HexToAddress(rawAccessList.Address) + if numKey := len(rawAccessList.StorageKeys); numKey > 0 { + accessList[i].StorageKeys = make([]common.Hash, numKey) + for j, rawStorageKey := range rawAccessList.StorageKeys { + accessList[i].StorageKeys[j] = common.HexToHash(rawStorageKey) + } + } + } + return accessList +} + func (cfg *ExecutionConfig) ExpectedGasConsumed() uint64 { return uint64(cfg.RawExpectedGasConsumed) } @@ -237,13 +263,14 @@ func readExecution( if err != nil { return nil, nil, err } - exec, err := action.NewExecution( + exec, err := action.NewExecutionWithAccessList( contractAddr, state.Nonce+1, ecfg.Amount(), ecfg.GasLimit(), ecfg.GasPrice(), ecfg.ByteCode(), + ecfg.AccessList(), ) if err != nil { return nil, nil, err @@ -284,13 +311,14 @@ func runExecutions( } nonce = nonce + 1 nonces[executor.String()] = nonce - exec, err := action.NewExecution( + exec, err := action.NewExecutionWithAccessList( contractAddrs[i], nonce, ecfg.Amount(), ecfg.GasLimit(), ecfg.GasPrice(), ecfg.ByteCode(), + ecfg.AccessList(), ) if err != nil { return nil, nil, err @@ -372,6 +400,9 @@ func (sct *SmartContractTest) prepareBlockchain( cfg.Genesis.GreenlandBlockHeight = 0 cfg.Genesis.IcelandBlockHeight = 0 } + if sct.InitGenesis.IsLondon { + cfg.Genesis.Blockchain.ToBeEnabledBlockHeight = 0 + } for _, expectedBalance := range sct.InitBalances { cfg.Genesis.InitBalanceMap[expectedBalance.Account] = expectedBalance.Balance().String() } @@ -1002,6 +1033,84 @@ func TestIstanbulEVM(t *testing.T) { }) } +func TestLondonEVM(t *testing.T) { + t.Run("ArrayReturn", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/array-return.json") + }) + t.Run("BasicToken", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/basic-token.json") + }) + t.Run("CallDynamic", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/call-dynamic.json") + }) + t.Run("chainid-selfbalance", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/chainid-selfbalance.json") + }) + t.Run("ChangeState", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/changestate.json") + }) + t.Run("F.value", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/f.value.json") + }) + t.Run("Gas-test", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/gas-test.json") + }) + t.Run("InfiniteLoop", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/infiniteloop.json") + }) + t.Run("MappingDelete", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/mapping-delete.json") + }) + t.Run("max-time", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/maxtime.json") + }) + t.Run("Modifier", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/modifiers.json") + }) + t.Run("Multisend", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/multisend.json") + }) + t.Run("NoVariableLengthReturns", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/no-variable-length-returns.json") + }) + t.Run("PublicMapping", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/public-mapping.json") + }) + t.Run("reentry-attack", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/reentry-attack.json") + }) + t.Run("RemoveFromArray", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/remove-from-array.json") + }) + t.Run("SendEth", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/send-eth.json") + }) + t.Run("Sha3", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/sha3.json") + }) + t.Run("storage-test", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/storage-test.json") + }) + t.Run("TailRecursion", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/tail-recursion.json") + }) + t.Run("Tuple", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/tuple.json") + }) + t.Run("wireconnection", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/wireconnection.json") + }) + t.Run("self-destruct", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/self-destruct.json") + }) + t.Run("datacopy", func(t *testing.T) { + NewSmartContractTest(t, "testdata-london/datacopy.json") + }) + t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) { + NewSmartContractTest(t, "testdata/CVE-2021-39137-attack-replay.json") + }) +} + func benchmarkHotContractWithFactory(b *testing.B, async bool) { sct := SmartContractTest{ InitBalances: []ExpectedBalance{ diff --git a/action/protocol/execution/testdata-london/CVE-2021-39137-attack-replay.json b/action/protocol/execution/testdata-london/CVE-2021-39137-attack-replay.json new file mode 100644 index 0000000000..c2decebb1d --- /dev/null +++ b/action/protocol/execution/testdata-london/CVE-2021-39137-attack-replay.json @@ -0,0 +1,36 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "0000000000000000000000008eae784e072e961f76948a785b62c9a950fb17ae62c9a950fb17ae00000000000000000000000000000000000000000000000000", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 16400, + "expectedBalances": [], + "comment": "deploy attack contract(https://etherscan.io/address/0x8eae784e072e961f76948a785b62c9a950fb17ae)" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3034526020600760203460045afa602034343e604034f3", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 12300, + "comment": "launch attack(https://etherscan.io/tx/0x1cb6fb36633d270edefc04d048145b4298e67b8aa82a9e5ec4aa1435dd770ce4)", + "expectedBlockInfos" : { + "txRootHash" : "a59ead74a3870e9b5ca352c5f59108df402ca203ef2109799fe2d8e1da49c83d", + "stateRootHash" : "ed9bd589ee5ab5660a3d5d863bbeea13020a0aacab18e8655a626beaf9a54713", + "receiptRootHash" : "3285579efa8521fbf95829b868ff5d37632c4feac6167e9ab2dc4961004c9272" + } + }] +} diff --git a/action/protocol/execution/testdata-london/array-return.json b/action/protocol/execution/testdata-london/array-return.json new file mode 100644 index 0000000000..0ef88f839a --- /dev/null +++ b/action/protocol/execution/testdata-london/array-return.json @@ -0,0 +1,45 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610115806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b60336047565b604051603e9190609d565b60405180910390f35b60606000805480602002602001604051908101604052809291908181526020018280548015609357602002820191906000526020600020905b8154815260200190600101908083116080575b5050505050905090565b6020808252825182820181905260009190848201906040850190845b8181101560d35783518352928401929184019160010160b9565b5090969550505050505056fea2646970667358221220003153ac66045f6e4649a560a665c439bafefa3a32ad368e45a214ceeb75fdbe64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 96405, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy array-return contract A" + },{ + "rawByteCode": "608060405234801561001057600080fd5b50610212806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063febb0f7e14610030575b600080fd5b61003861004e565b60405161004591906100c4565b60405180910390f35b60008054604080516318530aaf60e31b815290516060936001600160a01b039093169263c298557892600480820193918290030181865afa158015610097573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526100bf919081019061011e565b905090565b6020808252825182820181905260009190848201906040850190845b818110156100fc578351835292840192918401916001016100e0565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561013157600080fd5b825167ffffffffffffffff8082111561014957600080fd5b818501915085601f83011261015d57600080fd5b81518181111561016f5761016f610108565b8060051b604051601f19603f8301168101818110858211171561019457610194610108565b6040529182528482019250838101850191888311156101b257600080fd5b938501935b828510156101d0578451845293850193928501926101b7565b9897505050505050505056fea2646970667358221220e2e424aa63507945438677689f578de59a4ff358c3b0332310e7341459ee099164736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 172353, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy array-return contract B" + }], + "executions": [{ + "readOnly": true, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "febb0f7e", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10504, + "expectedStatus": 106, + "failed": true, + "comment": "call bar" + }] +} diff --git a/action/protocol/execution/testdata-london/array-return.sol b/action/protocol/execution/testdata-london/array-return.sol new file mode 100644 index 0000000000..29b8eaea13 --- /dev/null +++ b/action/protocol/execution/testdata-london/array-return.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract A { + uint256[] xs; + + function Apush() internal { + xs.push(100); + xs.push(200); + xs.push(300); + } + + // can be called from web3 + function foo() public view returns (uint256[] memory) { + return xs; + } +} + +// trying to call foo from another contract does not work +contract B { + A a; + + function Bnew() internal { + a = new A(); + } + + // COMPILATION ERROR + // Return argument type inaccessible dynamic type is not implicitly convertible + // to expected type (type of first return variable) uint256[] memory. + function bar() public view returns (uint256[] memory) { + return a.foo(); + } +} diff --git a/action/protocol/execution/testdata-london/basic-token.json b/action/protocol/execution/testdata-london/basic-token.json new file mode 100644 index 0000000000..39ae2a2d1a --- /dev/null +++ b/action/protocol/execution/testdata-london/basic-token.json @@ -0,0 +1,57 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b506101da806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806370a082311461003b578063a9059cbb14610076575b600080fd5b610064610049366004610113565b6001600160a01b031660009081526020819052604090205490565b60405190815260200160405180910390f35b610089610084366004610135565b61008b565b005b3360009081526020819052604090205481116100c65733600090815260208190526040812080548392906100c0908490610175565b90915550505b6001600160a01b038216600090815260208190526040812080548392906100ee90849061018c565b90915550505050565b80356001600160a01b038116811461010e57600080fd5b919050565b60006020828403121561012557600080fd5b61012e826100f7565b9392505050565b6000806040838503121561014857600080fd5b610151836100f7565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156101875761018761015f565b500390565b6000821982111561019f5761019f61015f565b50019056fea2646970667358221220df940e6c929cec5606a2caf0706e2b729904e0a4d6887c561d2dd6c976bd05a464736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 155541, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy an basic token contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "a9059cbb0000000000000000000000003328358128832a260c76a4141e19e2a943cd4b6d0000000000000000000000000000000000000000000000000000000000002710", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "cd7bfe84e3fe161aeb958aa899cea602147a8edb25bcc4cc49f4753fa3410c17" + ] + }], + "rawExpectedGasConsumed": 43909, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "transfer 10000 tokens from producer" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "70a082310000000000000000000000003328358128832a260c76a4141e19e2a943cd4b6d", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "cd7bfe84e3fe161aeb958aa899cea602147a8edb25bcc4cc49f4753fa3410c17" + ] + }], + "rawExpectedGasConsumed": 18406, + "expectedStatus": 1, + "readOnly": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000002710", + "expectedBalances": [], + "comment": "read the balance" + }] +} diff --git a/action/protocol/execution/testdata-london/basic-token.sol b/action/protocol/execution/testdata-london/basic-token.sol new file mode 100644 index 0000000000..fd87e6fa20 --- /dev/null +++ b/action/protocol/execution/testdata-london/basic-token.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract BasicToken { + mapping(address => uint256) balances; + + function transfer(address recipient, uint256 value) public { + if (balances[msg.sender] >= value) { + balances[msg.sender] -= value; + } + balances[recipient] += value; + } + + function balanceOf(address account) public view returns (uint256) { + return balances[account]; + } +} diff --git a/action/protocol/execution/testdata-london/call-dynamic.json b/action/protocol/execution/testdata-london/call-dynamic.json new file mode 100644 index 0000000000..ff007d511c --- /dev/null +++ b/action/protocol/execution/testdata-london/call-dynamic.json @@ -0,0 +1,36 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "60806040526000805534801561001457600080fd5b506101bf806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632fbebd381461003b578063febb0f7e14610050575b600080fd5b61004e61004936600461010f565b61006a565b005b61005861007b565b60405190815260200160405180910390f35b61007581600a610128565b60005550565b60405160016024820152600090309060440160408051601f198184030181529181526020820180516001600160e01b03166305f7d7a760e31b179052516100c2919061014e565b6000604051808303816000865af19150503d80600081146100ff576040519150601f19603f3d011682016040523d82523d6000602084013e610104565b606091505b505050600054905090565b60006020828403121561012157600080fd5b5035919050565b6000821982111561014957634e487b7160e01b600052601160045260246000fd5b500190565b6000825160005b8181101561016f5760208186018101518583015201610155565b8181111561017e576000828501525b50919091019291505056fea2646970667358221220f7ceb6bf29142ffe30e8c56eb8bdf47f329f78e8870ef0295242ebe6f895847864736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 150041, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy call dynamic contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "febb0f7e", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 33679, + "expectedStatus": 1, + "readOnly": true, + "rawReturnValue": "000000000000000000000000000000000000000000000000000000000000000b", + "expectedBalances": [], + "comment": "return 11" + }] +} diff --git a/action/protocol/execution/testdata-london/call-dynamic.sol b/action/protocol/execution/testdata-london/call-dynamic.sol new file mode 100644 index 0000000000..3c19bae051 --- /dev/null +++ b/action/protocol/execution/testdata-london/call-dynamic.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MyContract { + uint256 x = 0; + + function foo(uint256 _x) public { + x = 10 + _x; + } + + function bar() public returns (uint256) { + address(this).call(abi.encodeWithSignature("foo(uint256)", 1)); + return x; // returns 11 + } +} diff --git a/action/protocol/execution/testdata-london/chainid-selfbalance.json b/action/protocol/execution/testdata-london/chainid-selfbalance.json new file mode 100644 index 0000000000..c0bb65245d --- /dev/null +++ b/action/protocol/execution/testdata-london/chainid-selfbalance.json @@ -0,0 +1,66 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "60806040526000805534801561001457600080fd5b5060d2806100236000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c8063048a5fed146041578063564b81ef146055578063d09de08a14605a575b600080fd5b475b60405190815260200160405180910390f35b466043565b60606062565b005b600080549080606f836076565b9190505550565b600060018201609557634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220de81d1f134e1b02a16ed79b75c1bd5dfab4be2e471e7dc9446b51da91e4cbb8f64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawExpectedGasConsumed": 78799, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "999999999999999999999863365" + }], + "comment": "deploy chainid contract" + }], + "executions": [{ + "readOnly": true, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "564b81ef", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10579, + "expectedStatus": 1, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000001251", + "comment": "call getChainID" + }, + { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "d09de08a", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 32752, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "999999999999999999999888449" + }], + "comment": "call increment" + }, + { + "readOnly": true, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "048a5fed", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10549, + "expectedStatus": 1, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000000", + "comment": "call getSelfBalance" + }] +} diff --git a/action/protocol/execution/testdata-london/chainid-selfbalance.sol b/action/protocol/execution/testdata-london/chainid-selfbalance.sol new file mode 100644 index 0000000000..a5a6a929e5 --- /dev/null +++ b/action/protocol/execution/testdata-london/chainid-selfbalance.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract ChainidAndSelfbalance { + uint256 counter = 0; + + function getChainID() public view returns (uint256) { + return block.chainid; + } + + function getSelfBalance() public view returns (uint256) { + return address(this).balance; + } + + function increment() public { + counter++; + } +} diff --git a/action/protocol/execution/testdata-london/changestate.json b/action/protocol/execution/testdata-london/changestate.json new file mode 100644 index 0000000000..f4bc16a1c7 --- /dev/null +++ b/action/protocol/execution/testdata-london/changestate.json @@ -0,0 +1,58 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "60806040526000805534801561001457600080fd5b5061012a806100246000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80632e52d60614603757806386b5e2fb146051575b600080fd5b603f60005481565b60405190815260200160405180910390f35b6060605c36600460b1565b6062565b005b806000808282546071919060df565b90915550506000546040519081527f909c57d5c6ac08245cf2a6de3900e2b868513fa59099b92b27d8db823d92df9c9060200160405180910390a1600080fd5b60006020828403121560c257600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111560ef5760ef60c9565b50019056fea264697066735822122036e1e8e2c54827484751bc06accc0bc58616042b8d342c6adf160d458a3dfa1864736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 105317, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy a changestate contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "2e52d606", + "rawAmount": "0", + "rawGasLimit": 120000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 12661, + "expectedStatus": 1, + "readOnly": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000000", + "comment": "query state" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "86b5e2fb000000000000000000000000000000000000000000000000000000000000000d", + "rawAmount": "0", + "rawGasLimit": 120000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 37173, + "expectedStatus": 106, + "failed":true, + "comment": "try changing state" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "2e52d606", + "rawAmount": "0", + "rawGasLimit": 120000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 12661, + "expectedStatus": 1, + "readOnly": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000000", + "comment": "query state" + }] +} diff --git a/action/protocol/execution/testdata-london/changestate.sol b/action/protocol/execution/testdata-london/changestate.sol new file mode 100644 index 0000000000..87a5de2530 --- /dev/null +++ b/action/protocol/execution/testdata-london/changestate.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract ChangeState { + uint256 public n = 0; + event Log(uint256 n); + + function ChangeStateWithLogFail(uint256 add) public { + n += add; + emit Log(n); + require(false); + n++; + } +} diff --git a/action/protocol/execution/testdata-london/datacopy.json b/action/protocol/execution/testdata-london/datacopy.json new file mode 100644 index 0000000000..8fd715248a --- /dev/null +++ b/action/protocol/execution/testdata-london/datacopy.json @@ -0,0 +1,38 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b5061026d806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063574c807814610030575b600080fd5b61003861003a565b005b604080516003808252818301909252600091602082018180368337019050509050601160f81b81600081518110610073576100736101e7565b60200101906001600160f81b031916908160001a905350602260f81b816001815181106100a2576100a26101e7565b60200101906001600160f81b031916908160001a905350603360f81b816002815181106100d1576100d16101e7565b60200101906001600160f81b031916908160001a9053508051604080516003808252818301909252600091602082018180368337019050509050600082602185018460208701600462010000fa9050826000602084013e61013182610137565b50505050565b805161014a90600090602084019061014e565b5050565b82805461015a906101fd565b90600052602060002090601f01602090048101928261017c57600085556101c2565b82601f1061019557805160ff19168380011785556101c2565b828001600101855582156101c2579182015b828111156101c25782518255916020019190600101906101a7565b506101ce9291506101d2565b5090565b5b808211156101ce57600081556001016101d3565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061021157607f821691505b60208210810361023157634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220cb76f887319bd2bf08ab8098cd53e02dcf9d2c8b311ffdae7d73f2c4b7e2442264736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 199671, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy datacopy contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "574c8078", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 33720, + "expectedStatus": 1, + "comment": "the data of return is [0x11, 0x22, 0x33]", + "expectedBlockInfos" : { + "txRootHash" : "3672945ca662bea4dd977e799374c5ce36c0c3e9ecbe98f1655f33439bbfe40c", + "stateRootHash" : "31d9f2c50c45877029ed9afa24e2052bfc36232e9b0d220adfb0f90ec941d86c", + "receiptRootHash" : "596f5fd6f5931b252cff495050859df5faffd86ca960d0222b907a31bc1f75ae" + } + }] +} diff --git a/action/protocol/execution/testdata-london/datacopy.sol b/action/protocol/execution/testdata-london/datacopy.sol new file mode 100644 index 0000000000..6c2d48c509 --- /dev/null +++ b/action/protocol/execution/testdata-london/datacopy.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract Datacopy { + bytes store; + + function dataCopy() public { + bytes memory arr = new bytes(3); + arr[0] = 0x11; + arr[1] = 0x22; + arr[2] = 0x33; + uint256 length = arr.length; + bytes memory result = new bytes(3); + bool ret; + assembly { + // Call precompiled contract to copy data + ret := staticcall( + 0x10000, + 0x04, + add(arr, 0x20), + length, + add(arr, 0x21), + length + ) + returndatacopy(add(result, 0x20), 0x00, length) + } + updateStore(result); + } + + function updateStore(bytes memory ret) internal { + store = ret; + } +} diff --git a/action/protocol/execution/testdata-london/f.value.json b/action/protocol/execution/testdata-london/f.value.json new file mode 100644 index 0000000000..2f69b730b9 --- /dev/null +++ b/action/protocol/execution/testdata-london/f.value.json @@ -0,0 +1,48 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610382806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632f64d38614610046578063b5fdeb2314610064578063c4784fd41461006c575b600080fd5b61004e610081565b60405161005b919061024b565b60405180910390f35b61004e61010f565b61007f61007a3660046102a0565b6101a1565b005b6000805461008e90610312565b80601f01602080910402602001604051908101604052809291908181526020018280546100ba90610312565b80156101075780601f106100dc57610100808354040283529160200191610107565b820191906000526020600020905b8154815290600101906020018083116100ea57829003601f168201915b505050505081565b60606000805461011e90610312565b80601f016020809104026020016040519081016040528092919081815260200182805461014a90610312565b80156101975780601f1061016c57610100808354040283529160200191610197565b820191906000526020600020905b81548152906001019060200180831161017a57829003601f168201915b5050505050905090565b6101ad600083836101b2565b505050565b8280546101be90610312565b90600052602060002090601f0160209004810192826101e05760008555610226565b82601f106101f95782800160ff19823516178555610226565b82800160010185558215610226579182015b8281111561022657823582559160200191906001019061020b565b50610232929150610236565b5090565b5b808211156102325760008155600101610237565b600060208083528351808285015260005b818110156102785785810183015185820160400152820161025c565b8181111561028a576000604083870101525b50601f01601f1916929092016040019392505050565b600080602083850312156102b357600080fd5b823567ffffffffffffffff808211156102cb57600080fd5b818501915085601f8301126102df57600080fd5b8135818111156102ee57600080fd5b86602082850101111561030057600080fd5b60209290920196919550909350505050565b600181811c9082168061032657607f821691505b60208210810361034657634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220ed238939b20c65084e7fbd119adbf80e7919e2794cf8a6f7284ebff8909a35b264736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 282826, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy f.value one contract" + },{ + "rawByteCode": "608060405234801561001057600080fd5b5060405161031738038061031783398101604081905261002f916100b8565b600080546001600160a01b0319166001600160a01b03831690811790915560405163311e13f560e21b815260206004808301919091526024820152631d195cdd60e21b604482015263c4784fd490606401600060405180830381600087803b15801561009a57600080fd5b505af11580156100ae573d6000803e3d6000fd5b50505050506100e8565b6000602082840312156100ca57600080fd5b81516001600160a01b03811681146100e157600080fd5b9392505050565b610220806100f76000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b5fdeb2314610030575b600080fd5b61003861004e565b60405161004591906100f4565b60405180910390f35b600080546040805163b5fdeb2360e01b815290516060936001600160a01b039093169263b5fdeb2392600480820193918290030181865afa158015610097573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526100bf919081019061013d565b905090565b60005b838110156100df5781810151838201526020016100c7565b838111156100ee576000848401525b50505050565b60208152600082518060208401526101138160408501602087016100c4565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561014f57600080fd5b815167ffffffffffffffff8082111561016757600080fd5b818401915084601f83011261017b57600080fd5b81518181111561018d5761018d610127565b604051601f8201601f19908116603f011681019083821181831017156101b5576101b5610127565b816040528281528760208487010111156101ce57600080fd5b6101df8360208301602088016100c4565b97965050505050505056fea264697066735822122010ff35e04bc24ece56ab696ee9691ac2f78932141df9c84f6bbb8bc22110623564736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "appendContractAddress": true, + "contractIndexToAppend": 0, + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 249395, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy f.value two contract" + }], + "executions": [{ + "contractIndex": 1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "b5fdeb23", + "rawAmount": "0", + "rawGasLimit": 1200000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 19522, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "comment": "get msg" + }] +} diff --git a/action/protocol/execution/testdata-london/f.value.sol b/action/protocol/execution/testdata-london/f.value.sol new file mode 100644 index 0000000000..092c9d5171 --- /dev/null +++ b/action/protocol/execution/testdata-london/f.value.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract One { + string public word; + + function setMsg(string calldata whatever) public { + word = whatever; + } + + function getMsg() public view returns (string memory) { + return word; + } +} + +contract Two { + One o; + + constructor(address one) { + o = One(one); + o.setMsg("test"); + } + + function getMsg() public view returns (string memory) { + return o.getMsg(); + } +} diff --git a/action/protocol/execution/testdata-london/gas-test.json b/action/protocol/execution/testdata-london/gas-test.json new file mode 100644 index 0000000000..361cd44673 --- /dev/null +++ b/action/protocol/execution/testdata-london/gas-test.json @@ -0,0 +1,568 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments":[{ + "rawByteCode": "608060405234801561001057600080fd5b50610510806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631bb8305d146100465780633f03c8891461005b578063f446c1d014610081575b600080fd5b6100596100543660046102e0565b610096565b005b61006e610069366004610391565b6100ad565b6040519081526020015b60405180910390f35b6100896101a3565b60405161007891906103c3565b80516100a9906000906020840190610231565b5050565b600760005b858110156100e9576305f5e1076100cb8361271761042e565b6100d5919061044d565b9150806100e18161046f565b9150506100b2565b5060005b8481101561010e57600781901b9150806101068161046f565b9150506100ed565b5060005b838110156101495761271761012b836305f5e109610488565b610135919061044d565b9150806101418161046f565b915050610112565b5060005b8281101561019a576040518181527f3a9d05cd2ccc32722d8227d12aba72f740e7ae88c2afc7c40220d2686fda55ac9060200160405180910390a1806101928161046f565b91505061014d565b50949350505050565b600080546101b0906104a0565b80601f01602080910402602001604051908101604052809291908181526020018280546101dc906104a0565b80156102295780601f106101fe57610100808354040283529160200191610229565b820191906000526020600020905b81548152906001019060200180831161020c57829003601f168201915b505050505081565b82805461023d906104a0565b90600052602060002090601f01602090048101928261025f57600085556102a5565b82601f1061027857805160ff19168380011785556102a5565b828001600101855582156102a5579182015b828111156102a557825182559160200191906001019061028a565b506102b19291506102b5565b5090565b5b808211156102b157600081556001016102b6565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156102f257600080fd5b813567ffffffffffffffff8082111561030a57600080fd5b818401915084601f83011261031e57600080fd5b813581811115610330576103306102ca565b604051601f8201601f19908116603f01168101908382118183101715610358576103586102ca565b8160405282815287602084870101111561037157600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080600080608085870312156103a757600080fd5b5050823594602084013594506040840135936060013592509050565b600060208083528351808285015260005b818110156103f0578581018301518582016040015282016103d4565b81811115610402576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561044857610448610418565b500290565b60008261046a57634e487b7160e01b600052601260045260246000fd5b500690565b60006001820161048157610481610418565b5060010190565b6000821982111561049b5761049b610418565b500190565b600181811c908216806104b457607f821691505b6020821081036104d457634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220b2eb868a280ea9852a255794a48c8caf777c3401e8236346940e3d4f6808a3ba64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 402300, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy gas test contract" + }] , + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000002198000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 2354272, + "expectedStatus": 1, + "comment": "call test multiply" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062b800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 3258488, + "expectedStatus": 1, + "comment": "call test shift" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022800000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 2222840, + "expectedStatus": 1, + "comment": "call test add" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e30", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 4244056, + "expectedStatus": 1, + "expectedLogs": [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}], + "comment": "call test log" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "1bb8305d000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000019c8303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e568", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e570", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e572", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e573", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e574", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e575", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e577", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e578", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e579", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e581", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e582", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e583", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e584", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e586", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e587", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e588", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e589", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e590", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e591", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e592", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e593", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e595", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e596", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e597", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e598", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e599", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5aa", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ab", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ac", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ad", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ae", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5af", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ba", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5be", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bf", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ca", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cf", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5da", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5db", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5dc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5dd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5de", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5df", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ea", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5eb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ec", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ed", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ee", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ef", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fa", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fe", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ff", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e600", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e601", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e602", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e603", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e604", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e605", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e606", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e607", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e608", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e609", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e610", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e611", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e612", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e613", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e614", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e615", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e616", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e617", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e618", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e619", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e620", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e621", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e622", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e623", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e624", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e625", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e626", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e627", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e628", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e629", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e630", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e631" + ] + }], + "rawExpectedGasConsumed": 5253882, + "expectedStatus": 1, + "comment": "call storeString" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000016f30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "comment": "call test multiply" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001117000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "comment": "call test shift" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177000000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "comment": "call test add" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "3f03c8890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002260", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "expectedLogs": [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}], + "comment": "call test log" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "1bb8305d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000003390303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738393031323300000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e568", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e570", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e572", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e573", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e574", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e575", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e577", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e578", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e579", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e581", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e582", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e583", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e584", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e586", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e587", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e588", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e589", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e590", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e591", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e592", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e593", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e595", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e596", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e597", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e598", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e599", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5aa", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ab", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ac", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ad", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ae", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5af", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ba", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5be", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bf", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ca", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cf", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5da", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5db", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5dc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5dd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5de", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5df", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ea", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5eb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ec", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ed", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ee", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ef", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f1", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f6", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f7", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fa", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fc", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fe", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ff", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e600", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e601", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e602", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e603", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e604", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e605", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e606", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e607", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e608", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e609", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e60f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e610", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e611", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e612", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e613", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e614", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e615", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e616", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e617", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e618", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e619", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e61f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e620", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e621", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e622", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e623", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e624", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e625", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e626", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e627", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e628", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e629", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e62f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e630", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e631", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e632", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e633", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e634", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e635", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e636", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e637", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e638", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e639", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e64f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e650", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e651" + ] + }], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "comment": "call storeString" + }] +} diff --git a/action/protocol/execution/testdata-london/gas-test.sol b/action/protocol/execution/testdata-london/gas-test.sol new file mode 100644 index 0000000000..4afc6087bf --- /dev/null +++ b/action/protocol/execution/testdata-london/gas-test.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract tester { + string public A; + event logTest(uint256 n); + + function test( + uint256 mul, + uint256 shift, + uint256 add, + uint256 log + ) public returns (uint256 a) { + a = 7; + for (uint256 i = 0; i < mul; i++) { + a = (a * 10007) % 100000007; + } + for (uint256 i = 0; i < shift; i++) { + a = i << 7; + } + for (uint256 i = 0; i < add; i++) { + a = (a + 100000009) % 10007; + } + for (uint256 i = 0; i < log; i++) { + emit logTest(i); + } + } + + function storeString(string memory a) public { + A = a; + } +} diff --git a/action/protocol/execution/testdata-london/infiniteloop.json b/action/protocol/execution/testdata-london/infiniteloop.json new file mode 100644 index 0000000000..34f7248ea7 --- /dev/null +++ b/action/protocol/execution/testdata-london/infiniteloop.json @@ -0,0 +1,69 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "10000000000000000000" + }], + "deployments":[{ + "rawByteCode": "608060405234801561001057600080fd5b506101e5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80635bec9e671461004657806360fe47b114610050578063c2bc2efc14610063575b600080fd5b61004e610088565b005b61004e61005e36600461013f565b6100a1565b610076610071366004610158565b6100dc565b60405190815260200160405180910390f35b60008054908061009783610188565b9190505550610088565b60008190556040518181527fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b9060200160405180910390a150565b60006001600160a01b0382166100f157600080fd5b600054604080516001600160a01b038516815260208101929092527fbde7a70c2261170a87678200113c8e12f82f63d0a1d1cfa45681cbac328e87e3910160405180910390a1505060005490565b60006020828403121561015157600080fd5b5035919050565b60006020828403121561016a57600080fd5b81356001600160a01b038116811461018157600080fd5b9392505050565b6000600182016101a857634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220568e9b0cfa6b1769dec0d8e8973b98156b61ceafd4f4bf667b252995a66b50a864736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawExpectedGasConsumed": 158847, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "9999999999999803029" + }], + "comment": "deploy infiniteloop contract" + }] , + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "60fe47b10000000000000000000000000000000000000000000000000000000000001f40", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 36989, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "9999999999999804164" + }], + "expectedLogs": [{}], + "comment": "set storedData = 0x1f40" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "c2bc2efc0000000000000000000000000000000000000000000000000000000000000001", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 17534, + "readOnly": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000001f40", + "expectedStatus": 1, + "expectedLogs": [{}], + "comment": "read and verify storedData = 0x1f40" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5bec9e67", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 5000000, + "failed": true, + "expectedStatus": 101, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "9999999999994804164" + }], + "comment": "calling infinite(), this will consume all provided gas, and exit with failure" + }] +} diff --git a/action/protocol/execution/testdata-london/infiniteloop.sol b/action/protocol/execution/testdata-london/infiniteloop.sol new file mode 100644 index 0000000000..c6d2632fba --- /dev/null +++ b/action/protocol/execution/testdata-london/infiniteloop.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract SimpleStorage { + uint256 storedData; + + event Set(uint256); + event Get(address, uint256); + event Deadlock(); + + function set(uint256 x) public { + storedData = x; + emit Set(x); + } + + function get(address _to) public returns (uint256) { + require(_to != address(0)); + emit Get(_to, storedData); + return storedData; + } + + function infinite() public { + while (true) { + storedData++; + } + emit Deadlock(); + } +} diff --git a/action/protocol/execution/testdata-london/mapping-delete.json b/action/protocol/execution/testdata-london/mapping-delete.json new file mode 100644 index 0000000000..7eeada4857 --- /dev/null +++ b/action/protocol/execution/testdata-london/mapping-delete.json @@ -0,0 +1,33 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments":[{ + "rawByteCode": "608060405234801561001057600080fd5b50604080518082018252600180825260026020808401828152600080805280835294517fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb555517fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb6558451808601865260038152600490820152845180860190955260058552600685820190815291845283905292517fabbb5caa7dda850e60932de0934eb1f9d0f59695050f761dc64e443e5030a5695591517fabbb5caa7dda850e60932de0934eb1f9d0f59695050f761dc64e443e5030a56a559081527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d8190557fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7e5560b8806101426000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063bfb231d214602d575b600080fd5b60516038366004606a565b6000602081905290815260409020805460019091015482565b6040805192835260208301919091520160405180910390f35b600060208284031215607b57600080fd5b503591905056fea26469706673582212204c81f123b824c90df02ffdb3edccc52378b91c090a88da4ae48f832df13ebdc364736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb6", + "abbb5caa7dda850e60932de0934eb1f9d0f59695050f761dc64e443e5030a569", + "abbb5caa7dda850e60932de0934eb1f9d0f59695050f761dc64e443e5030a56a", + "ada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d", + "ada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7e" + ] + }], + "rawExpectedGasConsumed": 191751, + "expectedStatus": 1, + "comment": "deploy mapping-delete contract" + }] , + "executions": [] +} diff --git a/action/protocol/execution/testdata-london/mapping-delete.sol b/action/protocol/execution/testdata-london/mapping-delete.sol new file mode 100644 index 0000000000..c9d27b46c7 --- /dev/null +++ b/action/protocol/execution/testdata-london/mapping-delete.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MyContract { + struct Data { + uint256 a; + uint256 b; + } + mapping(uint256 => Data) public items; + + constructor() { + items[0] = Data(1, 2); + items[1] = Data(3, 4); + items[2] = Data(5, 6); + delete items[1]; + } +} diff --git a/action/protocol/execution/testdata-london/maxtime.json b/action/protocol/execution/testdata-london/maxtime.json new file mode 100644 index 0000000000..c133254959 --- /dev/null +++ b/action/protocol/execution/testdata-london/maxtime.json @@ -0,0 +1,136 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "10000000000000000000" + }], + "deployments":[{ + "rawByteCode": "608060405234801561001057600080fd5b50610395806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806316f7ae7a1461005157806319ae89941461007657806360fe47b114610089578063caf446831461009e575b600080fd5b61006461005f3660046102a8565b6100b1565b60405190815260200160405180910390f35b6100646100843660046102a8565b610173565b61009c6100973660046102a8565b6101e3565b005b6100646100ac3660046102a8565b610246565b600080805b838110156101415760005b602081101561010e57600081602081106100dd576100dd6102c1565b01546100e990846102ed565b60081c92506100fa83610101610305565b92508061010681610324565b9150506100c1565b5081600061011d60208461033d565b6020811061012d5761012d6102c1565b01558061013981610324565b9150506100b6565b5060405181907fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b90600090a292915050565b600080805b838110156101415760005b60208110156101d0576000816020811061019f5761019f6102c1565b01546101ab90846102ed565b60081c92506101bc83610101610305565b9250806101c881610324565b915050610183565b50806101db81610324565b915050610178565b60005b6020811015610217578160008260208110610203576102036102c1565b01558061020f81610324565b9150506101e6565b5060405181907fdf7a95aebff315db1b7716215d602ab537373cdb769232aae6055c06e798425b90600090a250565b600080805b838110156101415760005b60208110156102955760008160208110610272576102726102c1565b015461027e90846102ed565b60081c92508061028d81610324565b915050610256565b50806102a081610324565b91505061024b565b6000602082840312156102ba57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115610300576103006102d7565b500190565b600081600019048311821515161561031f5761031f6102d7565b500290565b600060018201610336576103366102d7565b5060010190565b60008261035a57634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212205a1480dc8fd7b4f1e1c414b55d7b96e6655e3e3789b49d9fedb757e4bd4e5e2864736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawExpectedGasConsumed": 288526, + "expectedStatus": 1, + "comment": "deploy maxtime contract" + }] , + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "60fe47b100000000000000000000000000000000000000000000000000000000000001f4", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "1", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004", + "0000000000000000000000000000000000000000000000000000000000000005", + "0000000000000000000000000000000000000000000000000000000000000006", + "0000000000000000000000000000000000000000000000000000000000000007", + "0000000000000000000000000000000000000000000000000000000000000008", + "0000000000000000000000000000000000000000000000000000000000000009", + "000000000000000000000000000000000000000000000000000000000000000a", + "000000000000000000000000000000000000000000000000000000000000000b", + "000000000000000000000000000000000000000000000000000000000000000c", + "000000000000000000000000000000000000000000000000000000000000000d", + "000000000000000000000000000000000000000000000000000000000000000e", + "000000000000000000000000000000000000000000000000000000000000000f", + "0000000000000000000000000000000000000000000000000000000000000010", + "0000000000000000000000000000000000000000000000000000000000000011", + "0000000000000000000000000000000000000000000000000000000000000012", + "0000000000000000000000000000000000000000000000000000000000000013", + "0000000000000000000000000000000000000000000000000000000000000014", + "0000000000000000000000000000000000000000000000000000000000000015", + "0000000000000000000000000000000000000000000000000000000000000016", + "0000000000000000000000000000000000000000000000000000000000000017", + "0000000000000000000000000000000000000000000000000000000000000018", + "0000000000000000000000000000000000000000000000000000000000000019", + "000000000000000000000000000000000000000000000000000000000000001a", + "000000000000000000000000000000000000000000000000000000000000001b", + "000000000000000000000000000000000000000000000000000000000000001c", + "000000000000000000000000000000000000000000000000000000000000001d", + "000000000000000000000000000000000000000000000000000000000000001f" + ] + }], + "rawExpectedGasConsumed": 723098, + "expectedStatus": 1, + "expectedLogs": [{}], + "comment": "set storedData = 0x1f40" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "19ae89940000000000000000000000000000000000000000000000000000000000000069", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 1508638, + "expectedStatus": 1, + "expectedLogs": [{}], + "comment": "run test1" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "caf44683000000000000000000000000000000000000000000000000000000000000007e", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawAccessList": [], + "rawExpectedGasConsumed": 1403493, + "expectedStatus": 1, + "expectedLogs": [{}], + "comment": "run test2" + }, { + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "16f7ae7a0000000000000000000000000000000000000000000000000000000000000066", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "1", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002", + "0000000000000000000000000000000000000000000000000000000000000003", + "0000000000000000000000000000000000000000000000000000000000000004", + "0000000000000000000000000000000000000000000000000000000000000005", + "0000000000000000000000000000000000000000000000000000000000000006", + "0000000000000000000000000000000000000000000000000000000000000007", + "0000000000000000000000000000000000000000000000000000000000000008", + "0000000000000000000000000000000000000000000000000000000000000009", + "000000000000000000000000000000000000000000000000000000000000000a", + "000000000000000000000000000000000000000000000000000000000000000b", + "000000000000000000000000000000000000000000000000000000000000000c", + "000000000000000000000000000000000000000000000000000000000000000d", + "000000000000000000000000000000000000000000000000000000000000000e", + "000000000000000000000000000000000000000000000000000000000000000f", + "0000000000000000000000000000000000000000000000000000000000000010", + "0000000000000000000000000000000000000000000000000000000000000011", + "0000000000000000000000000000000000000000000000000000000000000012", + "0000000000000000000000000000000000000000000000000000000000000013", + "0000000000000000000000000000000000000000000000000000000000000014", + "0000000000000000000000000000000000000000000000000000000000000015", + "0000000000000000000000000000000000000000000000000000000000000016", + "0000000000000000000000000000000000000000000000000000000000000017", + "0000000000000000000000000000000000000000000000000000000000000018", + "0000000000000000000000000000000000000000000000000000000000000019", + "000000000000000000000000000000000000000000000000000000000000001a", + "000000000000000000000000000000000000000000000000000000000000001b", + "000000000000000000000000000000000000000000000000000000000000001c", + "000000000000000000000000000000000000000000000000000000000000001d", + "000000000000000000000000000000000000000000000000000000000000001f" + ] + }], + "rawExpectedGasConsumed": 1576255, + "expectedStatus": 1, + "expectedLogs": [{}], + "comment": "run store1" + }] +} diff --git a/action/protocol/execution/testdata-london/maxtime.sol b/action/protocol/execution/testdata-london/maxtime.sol new file mode 100644 index 0000000000..0bf0624265 --- /dev/null +++ b/action/protocol/execution/testdata-london/maxtime.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract SimpleStorage { + uint256[32] storedData; + + event Set(uint256 indexed); + event Get(address, uint256); + + function set(uint256 x) public { + for (uint256 i = 0; i < 32; i++) { + storedData[i] = x; + } + emit Set(x); + } + + function test1(uint256 loop) public returns (uint256) { + uint256 x = 0; + for (uint256 j = 0; j < loop; j++) { + for (uint256 i = 0; i < 32; i++) { + x += storedData[i]; + x = x >> 8; + x = x * 257; + } + } + emit Set(x); + return x; + } + + function store1(uint256 loop) public returns (uint256) { + uint256 x = 0; + for (uint256 j = 0; j < loop; j++) { + for (uint256 i = 0; i < 32; i++) { + x += storedData[i]; + x = x >> 8; + x = x * 257; + } + storedData[j % 32] = x; + } + emit Set(x); + return x; + } + + function test2(uint256 loop) public returns (uint256) { + uint256 x = 0; + for (uint256 j = 0; j < loop; j++) { + for (uint256 i = 0; i < 32; i++) { + x += storedData[i]; + x = x >> 8; + } + } + emit Set(x); + return x; + } +} diff --git a/action/protocol/execution/testdata-london/modifiers.json b/action/protocol/execution/testdata-london/modifiers.json new file mode 100644 index 0000000000..de719302e7 --- /dev/null +++ b/action/protocol/execution/testdata-london/modifiers.json @@ -0,0 +1,55 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "60806040526000805460ff1916905534801561001a57600080fd5b5061015b8061002a6000396000f3fe6080604052600436106100345760003560e01c8063590e1ae314610039578063e420264a14610043578063fc68521a14610063575b600080fd5b610041610083565b005b34801561004f57600080fd5b5061004161005e3660046100dc565b6100b0565b34801561006f57600080fd5b5061004161007e3660046100f5565b6100c4565b60405133906108fc9060009081818181818888f193505050501580156100ad573d6000803e3d6000fd5b50565b80600a8082116100bf57600080fd5b505050565b806001600160a01b0381166100d857600080fd5b5050565b6000602082840312156100ee57600080fd5b5035919050565b60006020828403121561010757600080fd5b81356001600160a01b038116811461011e57600080fd5b939250505056fea26469706673582212209640b8983c3c50dee60be4865271f520ba5ae96a496ab4d64f90b3f88e3cf02d64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 120635, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy modifiers contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "fc68521a0000000000000000000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 13923, + "expectedStatus": 106, + "failed": true, + "comment": "call validAddress" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "e420264a0000000000000000000000000000000000000000000000000000000000000009", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 13846, + "expectedStatus": 106, + "failed": true, + "comment": "call greaterThan" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "590e1ae3", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10678, + "expectedStatus": 1, + "comment": "call refund" + }] +} diff --git a/action/protocol/execution/testdata-london/modifiers.sol b/action/protocol/execution/testdata-london/modifiers.sol new file mode 100644 index 0000000000..ce710ea09a --- /dev/null +++ b/action/protocol/execution/testdata-london/modifiers.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MyContract { + bool locked = false; + + modifier validAddress(address account) { + if (account == address(0x0)) { + revert(); + } + _; + } + + modifier greaterThan(uint256 value, uint256 limit) { + if (value <= limit) { + revert(); + } + _; + } + + modifier lock() { + if (locked) { + locked = true; + _; + locked = false; + } + } + + function f(address account) public validAddress(account) {} + + function g(uint256 a) public greaterThan(a, 10) {} + + function refund() public payable { + payable(msg.sender).transfer(0); + } +} diff --git a/action/protocol/execution/testdata-london/multisend.json b/action/protocol/execution/testdata-london/multisend.json new file mode 100644 index 0000000000..f0091b8909 --- /dev/null +++ b/action/protocol/execution/testdata-london/multisend.json @@ -0,0 +1,139 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io10t2hrfgcv0j4g2urc0qvjsvsqfwgykvgvff9eg", + "rawBalance": "1000000000000000000000000000" + }, { + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "1000000000000000000000000000" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "0" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "0" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610668806100206000396000f3fe60806040526004361061001e5760003560e01c8063e3b48f4814610023575b600080fd5b610036610031366004610476565b610038565b005b61012c835111156100a05760405162461bcd60e51b815260206004820152602760248201527f6e756d626572206f6620726563697069656e7473206973206c61726765722074604482015266068616e203330360cc1b60648201526084015b60405180910390fd5b81518351146100e85760405162461bcd60e51b81526020600482015260146024820152730e0c2e4c2dacae8cae4e640dcdee840dac2e8c6d60631b6044820152606401610097565b6000805b845181101561012e5783818151811061010757610107610569565b60200260200101518261011a9190610595565b915080610126816105ad565b9150506100ec565b50803410156101725760405162461bcd60e51b815260206004820152601060248201526f3737ba1032b737bab3b4103a37b5b2b760811b6044820152606401610097565b600061017e82346105c6565b905060005b85518110156102895785818151811061019e5761019e610569565b60200260200101516001600160a01b03166108fc8683815181106101c4576101c4610569565b60200260200101519081150290604051600060405180830381858888f193505050501580156101f7573d6000803e3d6000fd5b507f69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de286828151811061022b5761022b610569565b602002602001015186838151811061024557610245610569565b602002602001015160405161026f9291906001600160a01b03929092168252602082015260400190565b60405180910390a180610281816105ad565b915050610183565b5080156102f257604051339082156108fc029083906000818181858888f193505050501580156102bd573d6000803e3d6000fd5b506040518181527f2e1897b0591d764356194f7a795238a87c1987c7a877568e50d829d547c92b979060200160405180910390a15b7f53a85291e316c24064ff2c7668d99f35ecbb40ef4e24794ff9d8abe901c7e62c8360405161032191906105dd565b60405180910390a15050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561036f5761036f610330565b604052919050565b600067ffffffffffffffff82111561039157610391610330565b5060051b60200190565b600082601f8301126103ac57600080fd5b813560206103c16103bc83610377565b610346565b82815260059290921b840181019181810190868411156103e057600080fd5b8286015b848110156103fb57803583529183019183016103e4565b509695505050505050565b600082601f83011261041757600080fd5b813567ffffffffffffffff81111561043157610431610330565b610444601f8201601f1916602001610346565b81815284602083860101111561045957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561048b57600080fd5b833567ffffffffffffffff808211156104a357600080fd5b818601915086601f8301126104b757600080fd5b813560206104c76103bc83610377565b82815260059290921b8401810191818101908a8411156104e657600080fd5b948201945b8386101561051a5785356001600160a01b038116811461050b5760008081fd5b825294820194908201906104eb565b9750508701359250508082111561053057600080fd5b61053c8783880161039b565b9350604086013591508082111561055257600080fd5b5061055f86828701610406565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156105a8576105a861057f565b500190565b6000600182016105bf576105bf61057f565b5060010190565b6000828210156105d8576105d861057f565b500390565b600060208083528351808285015260005b8181101561060a578581018301518582016040015282016105ee565b8181111561061c576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212206d0223a5db842371fc5fe7a4c18fa5824b40669109c50e8d235498c0ed7ffa1364736f6c634300080e0033", + "rawPrivateKey": "d3d89ecdb8342c9308b84e73db1149f222ac3b15a087657a579c370078b21e25", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 505568, + "expectedBalances": [], + "expectedStatus" : 1, + "comment": "deploy multisend contract" + }], + "executions": [{ + "rawPrivateKey": "cff7405126a8e16ea6fd09279836e52abdcae8e4008309effc6d09556535f637", + "rawByteCode": "e3b48f48000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "rawAmount": "721", + "rawGasLimit": 1200000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 130104, + "expectedBalances": [{ + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "999999999999999999999999556" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "123" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "321" + }], + "expectedLogs": [{},{},{},{}], + "expectedStatus" : 1, + "comment": "send to two accounts" + }, { + "rawPrivateKey": "cff7405126a8e16ea6fd09279836e52abdcae8e4008309effc6d09556535f637", + "rawByteCode": "e3b48f48000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "rawAmount": "1", + "rawGasLimit": 1200000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 48112, + "failed": true, + "expectedBalances": [{ + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "999999999999999999999999556" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "123" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "321" + }], + "expectedStatus" : 106, + "expectedErrorMsg" : "not enough token", + "comment": "not enough tokens" + }, { + "rawPrivateKey": "cff7405126a8e16ea6fd09279836e52abdcae8e4008309effc6d09556535f637", + "rawByteCode": "e3b48f480000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000abc00000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "rawAmount": "721", + "rawGasLimit": 1200000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 45692, + "failed": true, + "expectedBalances": [{ + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "999999999999999999999999556" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "123" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "321" + }], + "expectedStatus" : 106, + "comment": "broken bytecode" + }, { + "rawPrivateKey": "cff7405126a8e16ea6fd09279836e52abdcae8e4008309effc6d09556535f637", + "rawByteCode": "e3b48f48000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000004c20000000000000000000000000000000000000000000000000000000000000012e0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc100000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000009ac231543413a274b1691e30292f0c88ec38cc10000000000000000000000000000000000000000000000000000000000000012e000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "rawAmount": "100000000000", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 2024382, + "failed": true, + "expectedBalances": [{ + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "999999999999999999999999556" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "123" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "321" + }], + "expectedStatus" : 106, + "expectedErrorMsg" : "number of recipients is larger than 300", + "comment": "more than 300 recipients" + }, { + "rawPrivateKey": "cff7405126a8e16ea6fd09279836e52abdcae8e4008309effc6d09556535f637", + "rawByteCode": "e3b48f48000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000004ba0000000000000000000000000000000000000000000000000000000000000012c0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a0000000000000000000000003cbbf6a0583bbe44cc5dda3b0d289c8d9149ba8a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000", + "rawAmount": "9999999999999999", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 4675581, + "expectedBalances": [{ + "account": "io1757z4d53408usrx2nf2vr5jh0mc5f5qm8nkre2", + "rawBalance": "999999999999999999999962656" + }, { + "account": "io18jaldgzc8wlyfnzamgas62yu3kg5nw527czg37", + "rawBalance": "37023" + }, { + "account": "io1ntprz4p5zw38fvtfrcczjtcv3rkr3nqs6sm3pj", + "rawBalance": "321" + }], + "expectedStatus" : 1, + "expectedLogs": [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}], + "comment": "transfer to 300 recipients" + }] +} diff --git a/action/protocol/execution/testdata-london/multisend.sol b/action/protocol/execution/testdata-london/multisend.sol new file mode 100644 index 0000000000..f99fe85707 --- /dev/null +++ b/action/protocol/execution/testdata-london/multisend.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract Multisend { + event Transfer(address recipient, uint256 amount); + event Refund(uint256 refund); + event Payload(string payload); + + function multiSend( + address[] memory recipients, + uint256[] memory amounts, + string memory payload + ) public payable { + require( + recipients.length <= 300, + "number of recipients is larger than 300" + ); + require(recipients.length == amounts.length, "parameters not match"); + uint256 totalAmount = 0; + for (uint256 i = 0; i < recipients.length; i++) { + totalAmount += amounts[i]; + } + require(msg.value >= totalAmount, "not enough token"); + uint256 refund = msg.value - totalAmount; + for (uint256 i = 0; i < recipients.length; i++) { + payable(recipients[i]).transfer(amounts[i]); + emit Transfer(recipients[i], amounts[i]); + } + if (refund > 0) { + payable(msg.sender).transfer(refund); + emit Refund(refund); + } + emit Payload(payload); + } +} diff --git a/action/protocol/execution/testdata-london/no-variable-length-returns.json b/action/protocol/execution/testdata-london/no-variable-length-returns.json new file mode 100644 index 0000000000..97c0192daa --- /dev/null +++ b/action/protocol/execution/testdata-london/no-variable-length-returns.json @@ -0,0 +1,69 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610157806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80636d4ce63c14610030575b600080fd5b61003861004e565b60405161004591906100d3565b60405180910390f35b606060008054806020026020016040519081016040528092919081815260200182805480156100c957602002820191906000526020600020906000905b82829054906101000a900460c01b6001600160c01b0319168152602001906008019060208260070104928301926001038202915080841161008b5790505b5050505050905090565b6020808252825182820181905260009190848201906040850190845b818110156101155783516001600160c01b031916835292840192918401916001016100ef565b5090969550505050505056fea26469706673582212206ff706ed1b3f9e7cfb5fc73ab395d7ae834ddc42378c3ad226df5e93cbcc6d3d64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 116217, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy A contract" + },{ + "rawByteCode": "608060405234801561001057600080fd5b506103b3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80635b1a80421461004657806385aba27514610050578063988acb1d14610080575b600080fd5b61004e610088565b005b61004e61005e366004610255565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61004e610108565b60008060009054906101000a90046001600160a01b03166001600160a01b0316636d4ce63c6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156100dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261010491908101906102b8565b5050565b6000805460408051631b53398f60e21b815290516001600160a01b0390921692636d4ce63c926004808401938290030181865afa15801561014d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261017591908101906102b8565b80516101899160019160209091019061018c565b50565b828054828255906000526020600020906003016004900481019282156102305791602002820160005b838211156101fa57835183826101000a81548167ffffffffffffffff021916908360c01c021790555092602001926008016020816007010492830192600103026101b5565b801561022e5782816101000a81549067ffffffffffffffff02191690556008016020816007010492830192600103026101fa565b505b5061023c929150610240565b5090565b5b8082111561023c5760008155600101610241565b60006020828403121561026757600080fd5b81356001600160a01b038116811461027e57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b80516001600160c01b0319811681146102b357600080fd5b919050565b600060208083850312156102cb57600080fd5b825167ffffffffffffffff808211156102e357600080fd5b818501915085601f8301126102f757600080fd5b81518181111561030957610309610285565b8060051b604051601f19603f8301168101818110858211171561032e5761032e610285565b60405291825284820192508381018501918883111561034c57600080fd5b938501935b82851015610371576103628561029b565b84529385019392850192610351565b9897505050505050505056fea2646970667358221220be1f939fbd956f9b5e31ea77bf2ca7bdc9b1b5cae0a61790fb76b532f0dc44e464736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 297532, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy B contract" + }], + "executions": [{ + "contractIndex":1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "85aba275", + "appendContractAddress": true, + "contractIndexToAppend": 0, + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 36024, + "expectedStatus": 1, + "comment": "call assign(address)" + },{ + "contractIndex":1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5b1a8042", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 18487, + "expectedStatus": 1, + "comment": "call copyToMemory" + },{ + "contractIndex":1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "988acb1d", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 20936, + "expectedStatus": 1, + "comment": "call copyToStorage" + }] +} diff --git a/action/protocol/execution/testdata-london/no-variable-length-returns.sol b/action/protocol/execution/testdata-london/no-variable-length-returns.sol new file mode 100644 index 0000000000..c7991a84be --- /dev/null +++ b/action/protocol/execution/testdata-london/no-variable-length-returns.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract A { + bytes8[] stuff; + + function get() public view returns (bytes8[] memory) { + return stuff; + } +} + +contract B { + A a; + bytes8[] mystuff; + + function assign(address _a) public { + a = A(_a); + } + + function copyToMemory() public view { + // VM does not support variably-sized return types from external function calls + // (ERROR: Type inaccessible dynamic type is not implicitly convertible...) + bytes8[] memory stuff = a.get(); + } + + function copyToStorage() public { + // ERROR + mystuff = a.get(); + } +} diff --git a/action/protocol/execution/testdata-london/public-mapping.json b/action/protocol/execution/testdata-london/public-mapping.json new file mode 100644 index 0000000000..e86327d215 --- /dev/null +++ b/action/protocol/execution/testdata-london/public-mapping.json @@ -0,0 +1,70 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b5060e68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80632081e911146037578063ed175850146069575b600080fd5b60676000808052602052602a7fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb555565b005b608660743660046098565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60006020828403121560a957600080fd5b503591905056fea26469706673582212200dfaa61c6a328284784717790c3efe9f36b8174503b0824c042d0ecd2529ae3464736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 82199, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy A contract" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "608060405234801561001057600080fd5b50610179806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636d4ce63c1461003b57806375f890ab14610055575b600080fd5b610043610087565b60405190815260200160405180910390f35b6100856100633660046100fa565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b005b60008054604051630ed1758560e41b8152600481018390526001600160a01b039091169063ed17585090602401602060405180830381865afa1580156100d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f5919061012a565b905090565b60006020828403121561010c57600080fd5b81356001600160a01b038116811461012357600080fd5b9392505050565b60006020828403121561013c57600080fd5b505191905056fea2646970667358221220ad3c7e555e870ce385d56628a88cbcd3dcec1d985072f6df0036a506e509fd2a64736f6c634300080e0033", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 126423, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy B contract" + }], + "executions": [{ + "contractIndex": 1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "75f890ab", + "appendContractAddress": true, + "contractIndexToAppend": 0, + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 36024, + "expectedStatus": 1, + "comment": "call setContract" + }, { + "contractIndex": 0, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "2081e911", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 32634, + "expectedStatus": 1, + "comment": "call a.Set()" + }, { + "contractIndex": 1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "6d4ce63c", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 17978, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "000000000000000000000000000000000000000000000000000000000000002a", + "comment": "call get()" + }] +} diff --git a/action/protocol/execution/testdata-london/public-mapping.sol b/action/protocol/execution/testdata-london/public-mapping.sol new file mode 100644 index 0000000000..b6056da4d3 --- /dev/null +++ b/action/protocol/execution/testdata-london/public-mapping.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract AA { + mapping(uint256 => uint256) public objects; + + function Set() public { + objects[0] = 42; + } +} + +contract BB { + // insert address of deployed First here + AA a; + + function setContract(address addr) public { + a = AA(addr); + } + + function get() public view returns (uint256) { + return a.objects(0); + } +} diff --git a/action/protocol/execution/testdata-london/reentry-attack.json b/action/protocol/execution/testdata-london/reentry-attack.json new file mode 100644 index 0000000000..29adcc7324 --- /dev/null +++ b/action/protocol/execution/testdata-london/reentry-attack.json @@ -0,0 +1,79 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b5061020f806100206000396000f3fe6080604052600436106100295760003560e01c80632e1a7d4d1461002e578063d0e30db014610050575b600080fd5b34801561003a57600080fd5b5061004e610049366004610140565b610058565b005b61004e61011a565b3360009081526020819052604090205481111561007457600080fd5b60408051600481526024810182526020810180516001600160e01b031663192e68cb60e31b1790529051339183916100ac9190610159565b60006040518083038185875af1925050503d80600081146100e9576040519150601f19603f3d011682016040523d82523d6000602084013e6100ee565b606091505b505033600090815260208190526040812080548493509091906101129084906101aa565b909155505050565b33600090815260208190526040812080543492906101399084906101c1565b9091555050565b60006020828403121561015257600080fd5b5035919050565b6000825160005b8181101561017a5760208186018101518583015201610160565b81811115610189576000828501525b509190910192915050565b634e487b7160e01b600052601160045260246000fd5b6000828210156101bc576101bc610194565b500390565b600082198211156101d4576101d4610194565b50019056fea264697066735822122096a59ee60e2ca523261c43e031f863d9edbad9dcd9fcadedb43ce59b548c427c64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 171453, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy MiniDAO contract" + },{ + "rawByteCode": "60806040526000805560405161027b38038061027b833981016040819052610026916100b5565b600280546001600160a01b0319166001600160a01b03831617905561004c600a346100e5565b60015560025460408051630d0e30db60e41b815290516001600160a01b039092169163d0e30db0913491600480830192600092919082900301818588803b15801561009657600080fd5b505af11580156100aa573d6000803e3d6000fd5b505050505050610107565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b60008261010257634e487b7160e01b600052601260045260246000fd5b500490565b610165806101166000396000f3fe6080604052600436106100295760003560e01c80639e5faafc1461002e578063c973465814610045575b600080fd5b34801561003a57600080fd5b5061004361004d565b005b6100436100b6565b600254600154604051632e1a7d4d60e01b81526001600160a01b0390921691632e1a7d4d916100829160040190815260200190565b600060405180830381600087803b15801561009c57600080fd5b505af11580156100b0573d6000803e3d6000fd5b50505050565b60008054600391806100c783610108565b91905055101561010657600254600154604051632e1a7d4d60e01b81526001600160a01b0390921691632e1a7d4d916100829160040190815260200190565b565b60006001820161012857634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207811d30a16290f048991954a891003cbdcb7e0243026442539693f1989681b0764736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "appendContractAddress": true, + "contractIndexToAppend": 0, + "rawAmount": "5000000000000000000", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "67ec2fd251e5563c112b2534590ae74d23e6df19", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000001", + "0000000000000000000000000000000000000000000000000000000000000002" + ] + },{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "809fddd0e44ad4227f52c39fc29ccd10b3c1d7ca546bc63db1a7bdde63de0cee" + ] + }], + "rawExpectedGasConsumed": 228673, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy Attacker contract" + }], + "executions": [{ + "contractIndex":1, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "9e5faafc", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "67ec2fd251e5563c112b2534590ae74d23e6df19", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000" + ] + },{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "809fddd0e44ad4227f52c39fc29ccd10b3c1d7ca546bc63db1a7bdde63de0cee" + ] + }], + "rawExpectedGasConsumed": 81795, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "999999995000000000000000000" + },{ + "account": "", + "rawBalance": "2000000000000000000" + },{ + "account": "io1q64m9jsrsd9afa3vvyx2wcn78hgjmx5h0y0kh6", + "rawBalance": "3000000000000000000" + }], + "comment": "attack" + }] +} diff --git a/action/protocol/execution/testdata-london/reentry-attack.sol b/action/protocol/execution/testdata-london/reentry-attack.sol new file mode 100644 index 0000000000..a6869a3f6d --- /dev/null +++ b/action/protocol/execution/testdata-london/reentry-attack.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MiniDAO { + mapping(address => uint256) balances; + + function deposit() public payable { + balances[msg.sender] += msg.value; + } + + function withdraw(uint256 amount) public { + if (balances[msg.sender] < amount) revert(); + //msg.sender.send(amount); + msg.sender.call{value: amount}(abi.encodeWithSignature("recur()")); + balances[msg.sender] -= amount; + } +} + +contract Attacker { + // limit the recursive calls to prevent out-of-gas error + uint256 stack = 0; + uint256 constant stackLimit = 3; + uint256 amount; + MiniDAO dao; + + constructor(address daoAddress) payable { + dao = MiniDAO(daoAddress); + amount = msg.value / 10; + dao.deposit{value: msg.value}(); + } + + function attack() public { + dao.withdraw(amount); + } + + function recur() public payable { + if (stack++ < stackLimit) { + dao.withdraw(amount); + } + } +} diff --git a/action/protocol/execution/testdata-london/remove-from-array.json b/action/protocol/execution/testdata-london/remove-from-array.json new file mode 100644 index 0000000000..6ea867c6d1 --- /dev/null +++ b/action/protocol/execution/testdata-london/remove-from-array.json @@ -0,0 +1,45 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b506103ca806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80635e383d21146100515780638c6fd8ec14610077578063e60ee4111461008c578063f8a8fd6d1461009f575b600080fd5b61006461005f3660046102ad565b6100b4565b6040519081526020015b60405180910390f35b61008a6100853660046102ad565b6100d5565b005b61008a61009a3660046102ad565b61016e565b6100a7610188565b60405161006e91906102c6565b600081815481106100c457600080fd5b600091825260209091200154905081565b6000546100e490600190610320565b8110156101445760006100f8826001610337565b815481106101085761010861034f565b9060005260206000200154600082815481106101265761012661034f565b6000918252602090912001558061013c81610365565b9150506100d5565b60008054806101555761015561037e565b6001900381819060005260206000200160009055905550565b60006101798261026d565b9050610184816100d5565b5050565b6000805460018181018355828052600a7f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563928301558254808201845560149083015582548082018455601e90830181905583548083018555602890840155835491820190935560329101556060906101ff9061016e565b600061020b602861026d565b9050610216816100d5565b600080548060200260200160405190810160405280929190818152602001828054801561026257602002820191906000526020600020905b81548152602001906001019080831161024e575b505050505091505090565b6000805b82600082815481106102855761028561034f565b9060005260206000200154146102a7578061029f81610365565b915050610271565b92915050565b6000602082840312156102bf57600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156102fe578351835292840192918401916001016102e2565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156103325761033261030a565b500390565b6000821982111561034a5761034a61030a565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600182016103775761037761030a565b5060010190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212204711a54cdbdbf18badca80a29a9ad0e248382ba4aba9966ff6b0034f5972bfd764736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 304438, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy remove-from-array contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "f8a8fd6d", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567" + ] + }], + "rawExpectedGasConsumed": 154639, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000032", + "comment": "call test()" + }] +} diff --git a/action/protocol/execution/testdata-london/remove-from-array.sol b/action/protocol/execution/testdata-london/remove-from-array.sol new file mode 100644 index 0000000000..563f7c11d3 --- /dev/null +++ b/action/protocol/execution/testdata-london/remove-from-array.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract Contract { + uint256[] public values; + + function find(uint256 value) internal view returns (uint256) { + uint256 i = 0; + while (values[i] != value) { + i++; + } + return i; + } + + function removeByValue(uint256 value) public { + uint256 i = find(value); + removeByIndex(i); + } + + function removeByIndex(uint256 i) public { + while (i < values.length - 1) { + values[i] = values[i + 1]; + i++; + } + values.pop(); + } + + function getValues() internal view returns (uint256[] storage) { + return values; + } + + function test() public returns (uint256[] memory) { + values.push(10); + values.push(20); + values.push(30); + values.push(40); + values.push(50); + removeByValue(30); + uint256 i = find(40); + removeByIndex(i); + return getValues(); + } +} diff --git a/action/protocol/execution/testdata-london/self-destruct.json b/action/protocol/execution/testdata-london/self-destruct.json new file mode 100644 index 0000000000..621505b146 --- /dev/null +++ b/action/protocol/execution/testdata-london/self-destruct.json @@ -0,0 +1,69 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50600080546001600160a01b0319163317905560ca806100316000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80632e64cec114604157806343d726d61460565780636057361d14605e575b600080fd5b60015460405190815260200160405180910390f35b605c606e565b005b605c6069366004607c565b600155565b6000546001600160a01b0316ff5b600060208284031215608d57600080fd5b503591905056fea264697066735822122098bc5d8b70d15684ea7303282380aeb7ae56863ca02d3ce8aec3e624652d7b6164736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 97728, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy self-destruct contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "6057361d0000000000000000000000000000000000000000000000000000000000000014", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 35934, + "expectedStatus": 1, + "comment": "store 20" + },{ + "readOnly": true, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "2e64cec1", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 12646, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000014", + "comment": "retrieve" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "43d726d6", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 17656, + "expectedStatus": 1, + "comment": "self destruct" + },{ + "readOnly": true, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "2e64cec1", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10400, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "", + "comment": "return nil because contract is destoried" + }] +} \ No newline at end of file diff --git a/action/protocol/execution/testdata-london/self-destruct.sol b/action/protocol/execution/testdata-london/self-destruct.sol new file mode 100644 index 0000000000..2e2e71e27c --- /dev/null +++ b/action/protocol/execution/testdata-london/self-destruct.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract Storage { + address payable private owner; + uint256 number; + + constructor() { + owner = payable(msg.sender); + } + + function store(uint256 num) public { + number = num; + } + + function retrieve() public view returns (uint256) { + return number; + } + + function close() public { + selfdestruct(owner); + } +} diff --git a/action/protocol/execution/testdata-london/send-eth.json b/action/protocol/execution/testdata-london/send-eth.json new file mode 100644 index 0000000000..629716790f --- /dev/null +++ b/action/protocol/execution/testdata-london/send-eth.json @@ -0,0 +1,38 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "6080604052600080546001600160a01b031916731e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e179055610183806100396000396000f3fe6080604052600436106100295760003560e01c80631ab5d2601461002e578063c298557814610030575b600080fd5b005b34801561003c57600080fd5b5061002e600080546040516001600160a01b039091169190670de0b6b3a76400009082818181858883f1935050505015801561007c573d6000803e3d6000fd5b50600080546040516001600160a01b0390911691670de0b6b3a7640000919081818185875af1925050503d80600081146100d2576040519150601f19603f3d011682016040523d82523d6000602084013e6100d7565b606091505b5050600080546040519192506060916001600160a01b0390911690670de0b6b3a7640000908481818185875af1925050503d8060008114610134576040519150601f19603f3d011682016040523d82523d6000602084013e610139565b606091505b5090925090508161014957600080fd5b505056fea264697066735822122094ad05fcf58df830500a27b673fbea890c82dc362e7f7b72d29a32d19bf4d71f64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "10000000000000000000", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 154041, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy send-eth contract" + }], + "executions": [{ + "contractIndex":0, + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "c2985578", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 61113, + "expectedStatus": 1, + "expectedBalances": [{ + "account": "io1rc2d2de7rtuucalsqv4d9ng0h297t63w7wvlph", + "rawBalance": "3000000000000000000" + }], + "comment": "foo()" + }] +} diff --git a/action/protocol/execution/testdata-london/send-eth.sol b/action/protocol/execution/testdata-london/send-eth.sol new file mode 100644 index 0000000000..2232b560de --- /dev/null +++ b/action/protocol/execution/testdata-london/send-eth.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MyContract { + constructor() payable {} + + address a = 0x1e14d5373E1AF9Cc77F0032aD2cd0FBA8be5Ea2e; + + function transferTo() public payable {} + + function foo() public { + // send ether with default 21,000 gas + // likely causes OOG in callee + payable(a).transfer(1 ether); + + // send ether with all remaining gas + // but no success check! + payable(a).call{value: 1 ether}(""); + + // RECOMMENDED + // send all remaining gas + // explicitly handle callee throw + bool ok; + bytes memory ret; + (ok, ret) = a.call{value: 1 ether}(""); + if (!ok) revert(); + } +} diff --git a/action/protocol/execution/testdata-london/sha3.json b/action/protocol/execution/testdata-london/sha3.json new file mode 100644 index 0000000000..494a05fb71 --- /dev/null +++ b/action/protocol/execution/testdata-london/sha3.json @@ -0,0 +1,190 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610511806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80635985b6241161008c578063c8cf44bd11610066578063c8cf44bd146101ae578063d2f8cf241461021b578063e86783a714610223578063f74d8e321461022b57600080fd5b80635985b6241461019e5780635fdc7f65146101a65780637781deba146101a657600080fd5b806344d9385f116100c857806344d9385f1461017e5780634c9e7ca5146101865780635087821a1461018e578063511931021461019657600080fd5b806304d3c094146100ef578063114be5841461012457806311b405c71461012c575b600080fd5b7f3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb5b6040519081526020015b60405180910390f35b610111610233565b604080516242544360e81b6020808301919091526208aa8960eb1b6028830152624c544360e81b603083015263444f474560e01b60388301528251808303820181529183019092528051910120610111565b61011161025f565b610111610277565b6101116103af565b6101116103ce565b61011161040f565b610111610429565b61020b604051606160f81b6020820152603160f91b6021820152600090602201604051602081830303815290604052805190602001207f67fad3bfa1e0321bd021ca805ce14876e50acac8ca8532eda8cbf924da56516014905090565b604051901515815260200161011b565b61011161043d565b610111610451565b61011161046d565b604080516000196020820152600091015b60405160208183030381529060405280519060200120905090565b604051600160f81b6020820152600090602101610244565b60408051600480825260a08201909252600091829190602082016080803683370190505090506242544360e81b816000815181106102b7576102b7610485565b60200260200101906001600160c01b03191690816001600160c01b031916815250506208aa8960eb1b816001815181106102f3576102f3610485565b60200260200101906001600160c01b03191690816001600160c01b03191681525050624c544360e81b8160028151811061032f5761032f610485565b60200260200101906001600160c01b03191690816001600160c01b0319168152505063444f474560e01b8160038151811061036c5761036c610485565b6001600160c01b03199092166020928302919091018201526040516103939183910161049b565b6040516020818303038152906040528051906020012091505090565b604051606160f81b602082015260016021820152600090604101610244565b6040517319de644fa609a211d3dc42d1f870141b1772918d60621b6020820152600090736779913e982688474f710b47e1c0506c5dca463490603401610393565b604051600560f91b60208201819052600091602101610393565b604080516001602082015260009101610244565b604080516064602082015260009101610244565b6040805168056bc75e2d63100000602082015260009101610244565b604051600160e01b6020820152600090602401610244565b634e487b7160e01b600052603260045260246000fd5b815160009082906020808601845b838110156104cf5781516001600160c01b031916855293820193908201906001016104a9565b5092969550505050505056fea2646970667358221220d2158981ace89707299dda5b0dbdfa6f28c1df9e097ab4e08e3de364f9207f4064736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 402600, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy sha3 contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "4c9e7ca5", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 11869, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "374c0504f79c1d5e6e4ded17d488802b5656bd1d96b16a568d6c324e1c04c37b", + "comment": "call hashArray" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "11b405c7", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10850, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "e79a6745d2205095147fd735f329de58377b2f0b9f4b81ae23e010062127f2bc", + "comment": "call hashPackedArray" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "51193102", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10839, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "229327de236bd04ccac2efc445f1a2b63afddf438b35874b9f6fd1e6c38b0198", + "comment": "call hashAddress" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "c8cf44bd", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 10784, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000001", + "comment": "call testPackedArgs" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5985b624", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10773, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8", + "comment": "call hashHex" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5fdc7f65", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10781, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", + "comment": "call hashInt" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "114be584", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10774, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "a9c584056064687e149968cbab758a3376d22aedc6a55823d1b3ecbee81b8fb9", + "comment": "call hashNegative" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "44d9385f", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10765, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "5fe7f977e71dba2ea1a68e21057beebb9be2ac30c6410aa38d4f3fbe41dcffd2", + "comment": "call hash8" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "f74d8e32", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10830, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "51f81bcdfc324a0dff2b5bec9d92e21cbebc4d5e29d3a3d30de3e03fbeab8d7f", + "comment": "call hash32" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "7781deba", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10803, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", + "comment": "call hash256" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "e86783a7", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10802, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "c7cc234d21c9cfbd4632749fd77669e7ae72f5241ce5895e410c45185a469273", + "comment": "call hashEth" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "d2f8cf24", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10780, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "26700e13983fefbd9cf16da2ed70fa5c6798ac55062a4803121a869731e308d2", + "comment": "call hashWei" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5087821a", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10833, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "b5cafab5b83d18303877bb912b2d66ca18ab7390cfd9be8a2e66cc5096e0ea02", + "comment": "call hashMultipleArgs" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "04d3c094", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10594, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb", + "comment": "call hashString" + }] +} diff --git a/action/protocol/execution/testdata-london/sha3.sol b/action/protocol/execution/testdata-london/sha3.sol new file mode 100644 index 0000000000..edaab25bd4 --- /dev/null +++ b/action/protocol/execution/testdata-london/sha3.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract Sha3 { + function hashArray() public pure returns (bytes32) { + bytes8[] memory tickers = new bytes8[](4); + tickers[0] = bytes8("BTC"); + tickers[1] = bytes8("ETH"); + tickers[2] = bytes8("LTC"); + tickers[3] = bytes8("DOGE"); + return keccak256(abi.encodePacked(tickers)); + // 0x374c0504f79c1d5e6e4ded17d488802b5656bd1d96b16a568d6c324e1c04c37b + } + + function hashPackedArray() public pure returns (bytes32) { + bytes8 btc = bytes8("BTC"); + bytes8 eth = bytes8("ETH"); + bytes8 ltc = bytes8("LTC"); + bytes8 doge = bytes8("DOGE"); + return keccak256(abi.encodePacked(btc, eth, ltc, doge)); + // 0xe79a6745d2205095147fd735f329de58377b2f0b9f4b81ae23e010062127f2bc + } + + function hashAddress() public pure returns (bytes32) { + address account = 0x6779913e982688474F710B47E1c0506c5Dca4634; + return keccak256(abi.encodePacked(account)); + // 0x229327de236bd04ccac2efc445f1a2b63afddf438b35874b9f6fd1e6c38b0198 + } + + function testPackedArgs() public pure returns (bool) { + return keccak256("ab") == keccak256(abi.encodePacked("a", "b")); + } + + function hashHex() public pure returns (bytes32) { + bytes1 i = 0x0a; + return keccak256(abi.encodePacked(i)); + // 0x0ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8 + } + + function hashInt() public pure returns (bytes32) { + return keccak256(abi.encodePacked(int256(1))); + } + + function hashNegative() public pure returns (bytes32) { + return keccak256(abi.encodePacked(int256(-1))); + } + + function hash8() public pure returns (bytes32) { + return keccak256(abi.encodePacked(uint8(1))); + } + + function hash32() public pure returns (bytes32) { + return keccak256(abi.encodePacked(uint32(1))); + } + + function hash256() public pure returns (bytes32) { + return keccak256(abi.encodePacked(uint256(1))); + } + + function hashEth() public pure returns (bytes32) { + return keccak256(abi.encodePacked(uint256(100 ether))); + } + + function hashWei() public pure returns (bytes32) { + return keccak256(abi.encodePacked(uint256(100))); + } + + function hashMultipleArgs() public pure returns (bytes32) { + return keccak256(abi.encodePacked("a", uint256(1))); + } + + function hashString() public pure returns (bytes32) { + return keccak256("a"); + } +} diff --git a/action/protocol/execution/testdata-london/storage-test.json b/action/protocol/execution/testdata-london/storage-test.json new file mode 100644 index 0000000000..ad29218d18 --- /dev/null +++ b/action/protocol/execution/testdata-london/storage-test.json @@ -0,0 +1,545 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments":[{ + "rawByteCode": "608060405234801561001057600080fd5b506103f7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635b48eb131461003b578063a17a9e6614610050575b600080fd5b61004e610049366004610237565b610079565b005b61006361005e3660046102ec565b6100dc565b6040516100709190610305565b60405180910390f35b60005b818112156100d7576000805460018101825590805283516100c4917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301906020860190610188565b50806100cf8161035a565b91505061007c565b505050565b600081815481106100ec57600080fd5b90600052602060002001600091509050805461010790610387565b80601f016020809104026020016040519081016040528092919081815260200182805461013390610387565b80156101805780601f1061015557610100808354040283529160200191610180565b820191906000526020600020905b81548152906001019060200180831161016357829003601f168201915b505050505081565b82805461019490610387565b90600052602060002090601f0160209004810192826101b657600085556101fc565b82601f106101cf57805160ff19168380011785556101fc565b828001600101855582156101fc579182015b828111156101fc5782518255916020019190600101906101e1565b5061020892915061020c565b5090565b5b80821115610208576000815560010161020d565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561024a57600080fd5b823567ffffffffffffffff8082111561026257600080fd5b818501915085601f83011261027657600080fd5b81358181111561028857610288610221565b604051601f8201601f19908116603f011681019083821181831017156102b0576102b0610221565b816040528281528860208487010111156102c957600080fd5b826020860160208301376000602093820184015298969091013596505050505050565b6000602082840312156102fe57600080fd5b5035919050565b600060208083528351808285015260005b8181101561033257858101830151858201604001528201610316565b81811115610344576000604083870101525b50601f01601f1916929092016040019392505050565b60006001600160ff1b01820161038057634e487b7160e01b600052601160045260246000fd5b5060010190565b600181811c9082168061039b57607f821691505b6020821081036103bb57634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212207ac4bf911f6801b1155455c32e3151315fea9b0072600db0c6765078601335d264736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 317945, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy storage test contract" + }] , + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5b48eb130000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000c8303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61d9", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61da", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61db", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61dc", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61dd", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61de", + "510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61df", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979a", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979b", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979c", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979d", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979e", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f600979f", + "6c13d8c1c5df666ea9ca2a428504a3776c8ca01021c3a1524ca7d765f60097a0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f13", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f14", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f15", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f16", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f17", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f18", + "63d75db57ae45c3799740c3cd8dcee96a498324843d79ae390adc81d74b52f19", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8fa", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8fb", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8fc", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8fd", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8fe", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d8ff", + "68ebfc8da80bd809b12832608f406ef96007b3a567d97edcfc62f0f6f6a6d900", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07da", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07db", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07dc", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07dd", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07de", + "9c418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07df", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e568", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0a", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0b", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0c", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0d", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0e", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d0f", + "5306a7ea1091503364459f70885dc372117f70834621ea9300aa244571124d10", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1a", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1b", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1c", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1d", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1e", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1f", + "aaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f20", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56a", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe66", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe67", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe68", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe69", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe6a", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe6b", + "45991fce5fc3033a0031207ac65e4c413069a0cd6e6bc7664254f8c4341cfe6c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35eed", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35eee", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35eef", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35ef0", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35ef1", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35ef2", + "51bdce570797d7347ee2c632abdbe21de6c1cddf1026b9348df268225cf35ef3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047b", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047c", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047d", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047e", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047f", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d00480", + "7b5fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d00481", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c4909365721185", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c4909365721186", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c4909365721187", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c4909365721188", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c4909365721189", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c490936572118a", + "4a4dc7b36028fb3f9d05fc19190734f0a7ece2c30dc0173f06c490936572118b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee44476", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee44477", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee44478", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee44479", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee4447a", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee4447b", + "d31af96c2e2fdbf596eef2a4a31d65a68b1fce22049159bf1b39bba52ee4447c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56f", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc5271f", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52720", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52721", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52722", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52723", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52724", + "0ebdbfac0189e4edd3debec57a7ef885f95fab7ca11fa633dea73d7b5dc52725", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e570", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac938e", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac938f", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac9390", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac9391", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac9392", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac9393", + "2742666d31e526c8f5defceabdafd3105bf2b5743774dd0c47702499dbac9394", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5c", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5d", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5e", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5f", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c60", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c61", + "a06695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c62", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e572", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70e5", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70e6", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70e7", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70e8", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70e9", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70ea", + "2a3933fcb91ddbd61f0e382d4b94df84f60ad30eacf94376b4a47114691e70eb", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e573", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af2", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af3", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af4", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af5", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af6", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af7", + "ff48e101e1045535d929d495692c383c0f1b7e861d5176a028cb8373d1179af8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e574", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852af", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b0", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b1", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b2", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b3", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b4", + "cc44b221c546b5aea12103918e6268611bfbad5b8d74f4d27f32ffebe4f852b5", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e575", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb444", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb445", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb446", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb447", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb448", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb449", + "a31f1759074a3e9970ff8648c50ab806c4e6725b961b4e54e979ef08b53fb44a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0591", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0592", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0593", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0594", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0595", + "be257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0596", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e577", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d259", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25a", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25b", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25c", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25d", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25e", + "c69ecc0828d60b329e3b9668ff42457eb5483fa791f1c1776f7fc1972fd7d25f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e578", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725361", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725362", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725363", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725364", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725365", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725366", + "0d13094d6851bea1cb50cc64a4421ae536705ca2da0347ea1d27f42aeb725367", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e579", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f5389667", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f5389668", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f5389669", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f538966a", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f538966b", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f538966c", + "80f0598597d7a1012e2e0a89cab2b766e02a3a5e30768662751fe258f538966d", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57a", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9e9c", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9e9d", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9e9e", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9e9f", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9ea0", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9ea1", + "df495ae1d831b2618ceb965d36d4e632eea69c8bc7a7859ce77b49dfa22c9ea2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de01", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de02", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de03", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de04", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de05", + "904d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de06", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57c", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa2", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa3", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa4", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa5", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa6", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa7", + "f108693a29c48396a4afb41c780f4afff0ebecea40e9758ae41ff60e33e7daa8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57d", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816cd", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816ce", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816cf", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816d0", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816d1", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816d2", + "ec8eded089ebe06ee017735c27289ac7b8a08d0464a8b95a3962b219b42816d3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57e", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f34", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f35", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f36", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f37", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f38", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f39", + "c077c8e3f307132f5d5d428a347cbbe434ca00e21ccd39585fde62f273379f3a" + ] + }], + "rawExpectedGasConsumed": 5014361, + "expectedStatus": 1, + "comment": "call storage test" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "5b48eb130000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000c8303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a3031323334353637383930313233000000000000000000000000000000000000000000000000", + "rawAmount": "0", + "rawGasLimit": 6000000, + "rawGasPrice": "0", + "rawAccessList": [{ + "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "storageKeys": [ + "0000000000000000000000000000000000000000000000000000000000000000", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57f", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f74d", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f74e", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f74f", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f750", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f751", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f752", + "8ab6912a296f8f35b3ccbba94a7ef1a0438421ad2191086e6e11caa339c1f753", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711ce", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cf", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711d0", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711d1", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711d2", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711d3", + "232f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711d4", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e581", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b15f", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b160", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b161", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b162", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b163", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b164", + "ac5f33c1333d426ffde7017786a5ac11afe511fd27c6c0e8505a42b50fd5b165", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e582", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da5c", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da5d", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da5e", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da5f", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da60", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da61", + "9733365717be6fab11c626849dc25bfd611553ba58c9fa326862379441f9da62", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e583", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec680", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec681", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec682", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec683", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec684", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec685", + "8b76c2fa7d287229b6b699c74b5abee97d6e859007fcf0dab8353073d20ec686", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e584", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0dea", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0deb", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0dec", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0ded", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0dee", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0def", + "82983cf1d0e5ef1112485a4f56e94f1ddb52ca674371d2cb12cb0515ca4d0df0", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422c", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422d", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422e", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422f", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac44230", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac44231", + "7f7c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac44232", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e586", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba410", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba411", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba412", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba413", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba414", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba415", + "0d31a8c04285395909374f518fcf59c56e560a55846c887741a1c002358ba416", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e587", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c180c", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c180d", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c180e", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c180f", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c1810", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c1811", + "fb92070d6c4bf9091d51718d0b1bea6abd7f108c91f2c8594aa2ab699e7c1812", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e588", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a685d", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a685e", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a685f", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a6860", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a6861", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a6862", + "a80c87265c8f718e21ec868fb390a9a58423b5d397ad3c9f566870b73a7a6863", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e589", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb70", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb71", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb72", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb73", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb74", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb75", + "148ac0381d2a057b56dc816a8b8f6a28ffdcf3cc656eed374fa4ee000f8ffb76", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58a", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de35", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de36", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de37", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de38", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de39", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de3a", + "8ab6fad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de3b", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58b", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f4", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f5", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f6", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f7", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f8", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372f9", + "30d08b743747dbe649f33f03467478748e55b9af9ec2f15e126ce890353372fa", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58c", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe3", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe4", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe5", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe6", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe7", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe8", + "09483f473fe89bdee59608e37223fe3aa2a6d8e27a1aa12211b3dd437afefbe9", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58d", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff890e", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff890f", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff8910", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff8911", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff8912", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff8913", + "d3a47c3b2f439571c7230ea0128f566e8adb47517d573da993d8644382ff8914", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58e", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d2", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d3", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d4", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d5", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d6", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d7", + "09a03d0b8493603ecd39a1811a587b9eed2654cfeedc2fbe977629f0a49624d8", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca5", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca6", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca7", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca8", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca9", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1caa", + "f95143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1cab", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e590", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e852514b", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e852514c", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e852514d", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e852514e", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e852514f", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e8525150", + "aa6d8b060d599285ad3ad27727a83a1a8f4d4b356011589a57add160e8525151", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e591", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab94", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab95", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab96", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab97", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab98", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab99", + "ba03254231e164fed7d683af6f1be22cda88175566d319440abcfa73f74bab9a", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e592", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d2568", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d2569", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d256a", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d256b", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d256c", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d256d", + "0cb329bf3f2b427ed0915fd7178e2534f794e0c318e67e34a158264e127d256e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e593", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a8c", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a8d", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a8e", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a8f", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a90", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a91", + "c09d2a33e363d8af11399d1d3f4fe92634456a3a19746ae927ed86e927633a92", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d691", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d692", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d693", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d694", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d695", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d696", + "61f96013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d697", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e595", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbe9d", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbe9e", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbe9f", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbea0", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbea1", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbea2", + "a0bedb31e6d9a66c4c7c6b8c89af4144e0e7cad9aba4216236a403a92a2dbea3", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e596", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d70", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d71", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d72", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d73", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d74", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d75", + "fc7dcc6adae2a42c0668058769002e63e6c1b2887a5e2c2ef4673a4d29516d76", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e597", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018123", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018124", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018125", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018126", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018127", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018128", + "4331910852304e59a0d925cdcfec0b19600fdef46b52e274114f286a59018129", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e598", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e68", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e69", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e6a", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e6b", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e6c", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e6d", + "8a142947a8d1f5b84194d09f6afde86f14c8a0658aa6176c85f5d95eee429e6e", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e599", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acf9", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acfa", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acfb", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acfc", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acfd", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acfe", + "33f33a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acff", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59a", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dcc7", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dcc8", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dcc9", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dcca", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dccb", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dccc", + "f77f6cc460e30e98718b51b0601a502cc084cc302f96911eff4710e985e4dccd", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59b", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213f9c", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213f9d", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213f9e", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213f9f", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213fa0", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213fa1", + "19eeb23aedb4c2c8eb452e1f8cc44ca22595636986d7ecc92256fe3aa1213fa2", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59c", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f009", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00a", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00b", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00c", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00d", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00e", + "ef458ea0b5e54ffeb1103a039323822c4a85ffc4a3911b3cfb32eabb2e63f00f", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59d", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef3c", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef3d", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef3e", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef3f", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef40", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef41", + "90d389ea5a1c3669f9cac1af92b808bef113a70583f2faa9443f8ed497c6ef42", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b56", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b57", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b58", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b59", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b5a", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b5b", + "8a23044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b5c", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59f", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbac9", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbaca", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbacb", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbacc", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbacd", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbace", + "3fb2cc435d88ad5c56e3ce3c1f8c781ae644ee1710f73e014be9b079ecafbacf", + "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a0", + "4add691e919965e9bb30f8df19e77484684340577f2d581069884bb14cd9ef4c", + "4add691e919965e9bb30f8df19e77484684340577f2d581069884bb14cd9ef4d" + ] + }], + "rawExpectedGasConsumed": 6000000, + "expectedStatus": 101, + "failed": true, + "comment": "call storage test again" + }] +} diff --git a/action/protocol/execution/testdata-london/storage-test.sol b/action/protocol/execution/testdata-london/storage-test.sol new file mode 100644 index 0000000000..e984fb7906 --- /dev/null +++ b/action/protocol/execution/testdata-london/storage-test.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract tester { + string[] public A; + + function storeStrings(string memory a, int256 n) public { + for (int256 i = 0; i < n; i++) { + A.push(a); + } + } +} diff --git a/action/protocol/execution/testdata-london/tail-recursion.json b/action/protocol/execution/testdata-london/tail-recursion.json new file mode 100644 index 0000000000..8e60c3f9d6 --- /dev/null +++ b/action/protocol/execution/testdata-london/tail-recursion.json @@ -0,0 +1,59 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b506101de806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063188b85b414610046578063b23913981461006b578063d4d6bc771461007e575b600080fd5b610059610054366004610131565b610091565b60405190815260200160405180910390f35b610059610079366004610131565b6100bf565b61005961008c366004610131565b6100cc565b600081156100b6576100a7610054600184610160565b6100b19083610177565b6100b9565b60005b92915050565b60006100b98260006100fe565b60008060015b8381116100f7576100e38183610177565b9150806100ef8161018f565b9150506100d2565b5092915050565b6000821561012857610123610114600185610160565b61011e8585610177565b6100fe565b61012a565b815b9392505050565b60006020828403121561014357600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156101725761017261014a565b500390565b6000821982111561018a5761018a61014a565b500190565b6000600182016101a1576101a161014a565b506001019056fea2646970667358221220649d55d134b060e38c310603dcceb4265c3b712a5d42d2037b16071c774e642b64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 156741, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy tail-recursion contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "188b85b40000000000000000000000000000000000000000000000000000000000000010", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 17161, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000088", + "comment": "call sum" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "d4d6bc770000000000000000000000000000000000000000000000000000000000000010", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 16861, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000088", + "comment": "call sumloop" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "b23913980000000000000000000000000000000000000000000000000000000000000010", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 17260, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000088", + "comment": "call sumtail" + }] +} diff --git a/action/protocol/execution/testdata-london/tail-recursion.sol b/action/protocol/execution/testdata-london/tail-recursion.sol new file mode 100644 index 0000000000..3a94d14b39 --- /dev/null +++ b/action/protocol/execution/testdata-london/tail-recursion.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract MyContract { + // naive recursion + function sum(uint256 n) public returns (uint256) { + return n == 0 ? 0 : n + sum(n - 1); + } + + // loop + function sumloop(uint256 n) public pure returns (uint256) { + uint256 total = 0; + for (uint256 i = 1; i <= n; i++) { + total += i; + } + return total; + } + + // tail-recursion + function sumtailHelper(uint256 n, uint256 acc) private returns (uint256) { + return n == 0 ? acc : sumtailHelper(n - 1, acc + n); + } + + function sumtail(uint256 n) public returns (uint256) { + return sumtailHelper(n, 0); + } +} diff --git a/action/protocol/execution/testdata-london/tuple.json b/action/protocol/execution/testdata-london/tuple.json new file mode 100644 index 0000000000..dcb5a734bd --- /dev/null +++ b/action/protocol/execution/testdata-london/tuple.json @@ -0,0 +1,35 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b50610147806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633175aae21461003b578063ab5ed15014610073575b600080fd5b61005c604080518082019091526002815261486960f01b6020820152600191565b60405161006a9291906100b4565b60405180910390f35b61007b610089565b60405190815260200161006a565b6000806100ad604080518082019091526002815261486960f01b6020820152600191565b5092915050565b82815260006020604081840152835180604085015260005b818110156100e8578581018301518582016060015282016100cc565b818111156100fa576000606083870101525b50601f01601f19169290920160600194935050505056fea2646970667358221220b5da55e0a6368c1df216b7482d49b767c20ebb47496d1f5a076db1a6c3ed787d64736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 111417, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy array-return contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "ab5ed150", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10700, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "0000000000000000000000000000000000000000000000000000000000000001", + "comment": "call bar" + }] +} diff --git a/action/protocol/execution/testdata-london/tuple.sol b/action/protocol/execution/testdata-london/tuple.sol new file mode 100644 index 0000000000..ea63b9f026 --- /dev/null +++ b/action/protocol/execution/testdata-london/tuple.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +contract A { + function tuple() public pure returns (uint256, string memory) { + return (1, "Hi"); + } + + function getOne() public pure returns (uint256) { + uint256 a; + (a, ) = tuple(); + return a; + } +} diff --git a/action/protocol/execution/testdata-london/wireconnection.json b/action/protocol/execution/testdata-london/wireconnection.json new file mode 100644 index 0000000000..7b40789c3c --- /dev/null +++ b/action/protocol/execution/testdata-london/wireconnection.json @@ -0,0 +1,47 @@ +{ + "initGenesis": { + "isBering" : true, + "isIceland" : true, + "isLondon" : true + }, + "initBalances": [{ + "account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", + "rawBalance": "1000000000000000000000000000" + }], + "deployments": [{ + "rawByteCode": "608060405234801561001057600080fd5b5060ca8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c8063dba7ab6c146041578063df11c2ac14605d578063ebaa833714606f575b600080fd5b646d69616f7760d81b5b60405190815260200160405180910390f35b606d6068366004607c565b600055565b005b646d69616f7760d81b604b565b600060208284031215608d57600080fd5b503591905056fea2646970667358221220c064a12b90076472ef76304dee377a60987f8737847349e4cda6f48b073c488364736f6c634300080e0033", + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawAmount": "0", + "rawGasLimit": 5000000, + "rawGasPrice": "0", + "rawExpectedGasConsumed": 73793, + "expectedStatus": 1, + "expectedBalances": [], + "comment": "deploy proposal contract" + }], + "executions": [{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "dba7ab6c", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10553, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "miaow", + "comment": "call utterance()" + },{ + "rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", + "rawByteCode": "ebaa8337", + "rawAmount": "0", + "rawGasLimit": 1000000, + "rawGasPrice": "0", + "rawAccessList": [], + "rawExpectedGasConsumed": 10608, + "expectedStatus": 1, + "hasReturnValue": true, + "rawReturnValue": "miaow", + "comment": "call Utterance()" + }] +} diff --git a/action/protocol/execution/testdata-london/wireconnection.sol b/action/protocol/execution/testdata-london/wireconnection.sol new file mode 100644 index 0000000000..98b29befb0 --- /dev/null +++ b/action/protocol/execution/testdata-london/wireconnection.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.14; + +abstract contract Feline { + // This is how we write the abstract contract + bytes32 name; + + function setname(bytes32 _name) public { + name = _name; + } + + function utterance() public virtual returns (bytes32); + + function Utterance() public virtual returns (bytes32); +} + +// inherit the contract in cat and then override the function utterance with some full definition +contract Cat is Feline { + function utterance() public pure override returns (bytes32) { + return "miaow"; + } + + function Utterance() public pure override returns (bytes32) { + return utterance(); + } +} From 891d27149611da5bb763b60f4193c4adfbac21f6 Mon Sep 17 00:00:00 2001 From: Haaai <55118568+Liuhaai@users.noreply.github.com> Date: Fri, 24 Jun 2022 10:38:14 -0700 Subject: [PATCH 09/24] remove InMemDaoOption (#3464) --- blockchain/blockchain.go | 12 ------------ blockchain/integrity/integrity_test.go | 6 ++++-- blocksync/buffer_test.go | 9 +++++---- consensus/scheme/rolldpos/rolldpos_test.go | 5 +++-- ioctl/newcmd/node/node.go | 2 +- 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index 6e455d40c3..f2d77b288b 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -158,22 +158,10 @@ func BoltDBDaoOption(indexers ...blockdao.BlockIndexer) Option { } } -// InMemDaoOption sets blockchain's dao with MemKVStore -func InMemDaoOption(indexers ...blockdao.BlockIndexer) Option { - return func(bc *blockchain, cfg config.Config) error { - if bc.dao != nil { - return nil - } - bc.dao = blockdao.NewBlockDAOInMemForTest(indexers) - return nil - } -} - // ClockOption overrides the default clock func ClockOption(clk clock.Clock) Option { return func(bc *blockchain, conf config.Config) error { bc.clk = clk - return nil } } diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index 0191bda009..2b798d2e06 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -1453,7 +1453,8 @@ func TestBlockchain_AccountState(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(sf, cfg.ActPool) require.NoError(err) - bc := blockchain.NewBlockchain(cfg, nil, factory.NewMinter(sf, ap), blockchain.InMemDaoOption(sf)) + dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) require.NoError(bc.Start(context.Background())) require.NotNil(bc) s, err := accountutil.AccountState(sf, identityset.Address(0)) @@ -1624,7 +1625,8 @@ func TestBlockchain_AddRemoveSubscriber(t *testing.T) { req.NoError(err) ap, err := actpool.NewActPool(sf, cfg.ActPool) req.NoError(err) - bc := blockchain.NewBlockchain(cfg, nil, factory.NewMinter(sf, ap), blockchain.InMemDaoOption(sf)) + dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) + bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) // mock ctrl := gomock.NewController(t) mb := mock_blockcreationsubscriber.NewMockBlockCreationSubscriber(ctrl) diff --git a/blocksync/buffer_test.go b/blocksync/buffer_test.go index 7521c214b5..b9e159e1ac 100644 --- a/blocksync/buffer_test.go +++ b/blocksync/buffer_test.go @@ -23,6 +23,7 @@ import ( "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/state/factory" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/testutil" @@ -45,11 +46,11 @@ func TestBlockBufferFlush(t *testing.T) { require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) + dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) chain := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, ap), - blockchain.InMemDaoOption(sf), blockchain.BlockValidatorOption(block.NewValidator(sf, ap)), ) require.NoError(chain.Start(ctx)) @@ -135,11 +136,11 @@ func TestBlockBufferGetBlocksIntervalsToSync(t *testing.T) { ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) + dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) chain := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, ap), - blockchain.InMemDaoOption(sf), ) require.NotNil(chain) require.NoError(chain.Start(ctx)) diff --git a/consensus/scheme/rolldpos/rolldpos_test.go b/consensus/scheme/rolldpos/rolldpos_test.go index 7f1eca3a83..c0450e8363 100644 --- a/consensus/scheme/rolldpos/rolldpos_test.go +++ b/consensus/scheme/rolldpos/rolldpos_test.go @@ -34,6 +34,7 @@ import ( "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" cp "github.com/iotexproject/iotex-core/crypto" @@ -417,11 +418,11 @@ func TestRollDPoSConsensus(t *testing.T) { require.NoError(t, acc.Register(registry)) rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) require.NoError(t, rp.Register(registry)) + dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) chain := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, actPool), - blockchain.InMemDaoOption(sf), blockchain.BlockValidatorOption(block.NewValidator( sf, protocol.NewGenericValidator(sf, accountutil.AccountState), diff --git a/ioctl/newcmd/node/node.go b/ioctl/newcmd/node/node.go index 2edadda33b..a6fd4a46c9 100644 --- a/ioctl/newcmd/node/node.go +++ b/ioctl/newcmd/node/node.go @@ -2,7 +2,7 @@ package node import ( "github.com/spf13/cobra" - + "github.com/iotexproject/iotex-core/ioctl" "github.com/iotexproject/iotex-core/ioctl/config" ) From e3afa71afbf3b431a85a04b414cb7539752e3167 Mon Sep 17 00:00:00 2001 From: Haaai <55118568+Liuhaai@users.noreply.github.com> Date: Fri, 24 Jun 2022 15:09:27 -0700 Subject: [PATCH 10/24] [blockchain] Remove BoltDBDaoOption (#3465) * remove config.Chain.CompressBlock * remove BoltDBDaoOption --- blockchain/blockchain.go | 13 ------------ blockchain/integrity/benchmark_test.go | 1 - blockchain/integrity/integrity_test.go | 20 +++++++++++-------- chainservice/builder.go | 2 -- config/config.go | 3 --- .../scheme/rolldpos/roundcalculator_test.go | 7 +++++-- e2etest/local_test.go | 8 ++++---- e2etest/rewarding_test.go | 3 +-- tools/iomigrater/cmds/check-height.go | 1 - tools/iomigrater/cmds/migrate-db.go | 1 - tools/minicluster/minicluster.go | 2 +- 11 files changed, 23 insertions(+), 38 deletions(-) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index f2d77b288b..dd0791bb26 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -145,19 +145,6 @@ func BlockValidatorOption(blockValidator block.Validator) Option { } } -// BoltDBDaoOption sets blockchain's dao with BoltDB from config.Chain.ChainDBPath -func BoltDBDaoOption(indexers ...blockdao.BlockIndexer) Option { - return func(bc *blockchain, cfg config.Config) error { - if bc.dao != nil { - return nil - } - cfg.DB.DbPath = cfg.Chain.ChainDBPath // TODO: remove this after moving TrieDBPath from cfg.Chain to cfg.DB - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock - bc.dao = blockdao.NewBlockDAO(indexers, cfg.DB) - return nil - } -} - // ClockOption overrides the default clock func ClockOption(clk clock.Clock) Option { return func(bc *blockchain, conf config.Config) error { diff --git a/blockchain/integrity/benchmark_test.go b/blockchain/integrity/benchmark_test.go index 8c7894910c..781d8c2cae 100644 --- a/blockchain/integrity/benchmark_test.go +++ b/blockchain/integrity/benchmark_test.go @@ -258,7 +258,6 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(1000000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao := blockdao.NewBlockDAO(indexers, cfg.DB) if dao == nil { return nil, nil, errors.New("pointer is nil") diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index 2b798d2e06..c5d843a8f2 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -866,7 +866,6 @@ func TestConstantinople(t *testing.T) { require.NoError(err) // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf, indexer}, cfg.DB) require.NotNil(dao) bc := blockchain.NewBlockchain( @@ -1112,7 +1111,6 @@ func TestLoadBlockchainfromDB(t *testing.T) { cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao := blockdao.NewBlockDAO(indexers, cfg.DB) require.NotNil(dao) bc := blockchain.NewBlockchain( @@ -1409,11 +1407,13 @@ func TestBlockchainInitialCandidate(t *testing.T) { require.NoError(err) accountProtocol := account.NewProtocol(rewarding.DepositGas) require.NoError(accountProtocol.Register(registry)) + dbcfg := cfg.DB + dbcfg.DbPath = cfg.Chain.ChainDBPath + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) bc := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, ap), - blockchain.BoltDBDaoOption(sf), blockchain.BlockValidatorOption(sf), ) rolldposProtocol := rolldpos.NewProtocol( @@ -1496,9 +1496,12 @@ func TestBlocks(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(sf, cfg.ActPool) require.NoError(err) + dbcfg := cfg.DB + dbcfg.DbPath = cfg.Chain.ChainDBPath + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) // Create a blockchain from scratch - bc := blockchain.NewBlockchain(cfg, nil, factory.NewMinter(sf, ap), blockchain.BoltDBDaoOption(sf)) + bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) require.NoError(bc.Start(context.Background())) defer func() { require.NoError(bc.Stop(context.Background())) @@ -1565,12 +1568,14 @@ func TestActions(t *testing.T) { require.NoError(err) ap, err := actpool.NewActPool(sf, cfg.ActPool) require.NoError(err) + dbcfg := cfg.DB + dbcfg.DbPath = cfg.Chain.ChainDBPath + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) // Create a blockchain from scratch bc := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, ap), - blockchain.BoltDBDaoOption(sf), blockchain.BlockValidatorOption(block.NewValidator( sf, protocol.NewGenericValidator(sf, accountutil.AccountState), @@ -1850,7 +1855,6 @@ func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factor cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao := blockdao.NewBlockDAO(indexers, cfg.DB) require.NotNil(dao) bc := blockchain.NewBlockchain( diff --git a/chainservice/builder.go b/chainservice/builder.go index ebe2586301..d3e6be6bd9 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -250,8 +250,6 @@ func (builder *Builder) buildBlockDAO(forTest bool) error { } else { dbConfig := builder.cfg.DB dbConfig.DbPath = builder.cfg.Chain.ChainDBPath - dbConfig.CompressLegacy = builder.cfg.Chain.CompressBlock - builder.cs.blockdao = blockdao.NewBlockDAO(indexers, dbConfig) } diff --git a/config/config.go b/config/config.go index a04b9efbdb..270db27b5c 100644 --- a/config/config.go +++ b/config/config.go @@ -101,7 +101,6 @@ var ( EnableSystemLogIndexer: false, EnableStakingProtocol: true, EnableStakingIndexer: false, - CompressBlock: false, AllowedBlockGasResidue: 10000, MaxCacheSize: 0, PollInitialCandidatesInterval: 10 * time.Second, @@ -239,8 +238,6 @@ type ( EnableStakingProtocol bool `yaml:"enableStakingProtocol"` // EnableStakingIndexer enables staking indexer EnableStakingIndexer bool `yaml:"enableStakingIndexer"` - // deprecated by DB.CompressBlock - CompressBlock bool `yaml:"compressBlock"` // AllowedBlockGasResidue is the amount of gas remained when block producer could stop processing more actions AllowedBlockGasResidue uint64 `yaml:"allowedBlockGasResidue"` // MaxCacheSize is the max number of blocks that will be put into an LRU cache. 0 means disabled diff --git a/consensus/scheme/rolldpos/roundcalculator_test.go b/consensus/scheme/rolldpos/roundcalculator_test.go index c46b832e31..930811d214 100644 --- a/consensus/scheme/rolldpos/roundcalculator_test.go +++ b/consensus/scheme/rolldpos/roundcalculator_test.go @@ -25,6 +25,7 @@ import ( "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/pkg/unit" @@ -183,11 +184,13 @@ func makeChain(t *testing.T) (blockchain.Blockchain, factory.Factory, actpool.Ac require.NoError(err) ap, err := actpool.NewActPool(sf, cfg.ActPool) require.NoError(err) + dbcfg := cfg.DB + dbcfg.DbPath = cfg.Chain.ChainDBPath + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) chain := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf, ap), - blockchain.BoltDBDaoOption(sf), blockchain.BlockValidatorOption(block.NewValidator( sf, protocol.NewGenericValidator(sf, accountutil.AccountState), diff --git a/e2etest/local_test.go b/e2etest/local_test.go index ad7f68696a..0c2bfbf85f 100644 --- a/e2etest/local_test.go +++ b/e2etest/local_test.go @@ -159,11 +159,13 @@ func TestLocalCommit(t *testing.T) { require.NoError(err) ap2, err := actpool.NewActPool(sf2, cfg.ActPool) require.NoError(err) + dbcfg := cfg.DB + dbcfg.DbPath = cfg.Chain.ChainDBPath + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf2}, dbcfg) chain := blockchain.NewBlockchain( cfg, - nil, + dao, factory.NewMinter(sf2, ap2), - blockchain.BoltDBDaoOption(sf2), blockchain.BlockValidatorOption(block.NewValidator( sf2, protocol.NewGenericValidator(sf2, accountutil.AccountState), @@ -474,7 +476,6 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 3 from empty state DB cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao := blockdao.NewBlockDAO(nil, cfg.DB) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), @@ -497,7 +498,6 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 2 from an existing state DB with Height 3 require.NoError(svr.Stop(ctx)) cfg.DB.DbPath = cfg.Chain.ChainDBPath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock dao = blockdao.NewBlockDAO(nil, cfg.DB) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), diff --git a/e2etest/rewarding_test.go b/e2etest/rewarding_test.go index d05a63c1ca..9154a1808e 100644 --- a/e2etest/rewarding_test.go +++ b/e2etest/rewarding_test.go @@ -585,7 +585,6 @@ func newConfig( cfg.Chain.ChainDBPath = chainDBPath cfg.Chain.TrieDBPath = trieDBPath cfg.Chain.IndexDBPath = indexDBPath - cfg.Chain.CompressBlock = true cfg.Chain.ProducerPrivKey = producerPriKey.HexString() cfg.Chain.EnableAsyncIndexWrite = false @@ -607,9 +606,9 @@ func newConfig( cfg.Genesis.Blockchain.NumDelegates = numNodes cfg.Genesis.Blockchain.TimeBasedRotation = true cfg.Genesis.Delegates = cfg.Genesis.Delegates[0:numNodes] - cfg.Genesis.BlockInterval = 500 * time.Millisecond cfg.Genesis.EnableGravityChainVoting = true cfg.Genesis.Rewarding.FoundationBonusLastEpoch = 2 + return cfg } diff --git a/tools/iomigrater/cmds/check-height.go b/tools/iomigrater/cmds/check-height.go index 102e4f87ce..660e33db65 100644 --- a/tools/iomigrater/cmds/check-height.go +++ b/tools/iomigrater/cmds/check-height.go @@ -53,7 +53,6 @@ func checkDbFileHeight(filePath string) (uint64, error) { } cfg.DB.DbPath = filePath - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock blockDao := blockdao.NewBlockDAO(nil, cfg.DB) // Load height value. diff --git a/tools/iomigrater/cmds/migrate-db.go b/tools/iomigrater/cmds/migrate-db.go index 95d317d176..7a4c170372 100644 --- a/tools/iomigrater/cmds/migrate-db.go +++ b/tools/iomigrater/cmds/migrate-db.go @@ -113,7 +113,6 @@ func migrateDbFile() error { } cfg.DB.DbPath = oldFile - cfg.DB.CompressLegacy = cfg.Chain.CompressBlock oldDAO := blockdao.NewBlockDAO(nil, cfg.DB) cfg.DB.DbPath = newFile diff --git a/tools/minicluster/minicluster.go b/tools/minicluster/minicluster.go index 8ab942ee96..ce6b6be714 100644 --- a/tools/minicluster/minicluster.go +++ b/tools/minicluster/minicluster.go @@ -412,7 +412,6 @@ func newConfig( cfg.Network.BootstrapNodes = []string{"/ip4/127.0.0.1/tcp/4689/ipfs/12D3KooWJwW6pUpTkxPTMv84RPLPMQVEAjZ6fvJuX4oZrvW5DAGQ"} cfg.Chain.ID = 1 - cfg.Chain.CompressBlock = true cfg.Chain.ProducerPrivKey = producerPriKey.HexString() cfg.ActPool.MinGasPriceStr = big.NewInt(0).String() @@ -438,5 +437,6 @@ func newConfig( cfg.Genesis.Delegates = cfg.Genesis.Delegates[3 : _numNodes+3] cfg.Genesis.EnableGravityChainVoting = false cfg.Genesis.PollMode = "lifeLong" + return cfg } From bd7662c09fc9f0bf3635359c2d12411c48d8880c Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Sat, 25 Jun 2022 08:39:31 +0800 Subject: [PATCH 11/24] [ioctl] Cleanup TestNewNodeDelegateCmd (#3421) * [ioctl] cleanup TestNewNodeDelegateCmd * check false active block * check false active delegate * delete useless err * add subfunc to replace map design * replace map with if...else statement * remove ConfigMap Co-authored-by: huofei <68298506@qq.com> Co-authored-by: CoderZhi --- ioctl/newcmd/node/nodedelegate.go | 29 +++---- ioctl/newcmd/node/nodedelegate_test.go | 114 +++++++++++++------------ 2 files changed, 73 insertions(+), 70 deletions(-) diff --git a/ioctl/newcmd/node/nodedelegate.go b/ioctl/newcmd/node/nodedelegate.go index a01889db50..6daad566a9 100644 --- a/ioctl/newcmd/node/nodedelegate.go +++ b/ioctl/newcmd/node/nodedelegate.go @@ -48,11 +48,6 @@ var ( } ) -var ( - _nodeStatus map[bool]string - _probatedStatus map[bool]string -) - type nextDelegatesMessage struct { Epoch int `json:"epoch"` Determined bool `json:"determined"` @@ -94,7 +89,6 @@ func NewNodeDelegateCmd(client ioctl.Client) *cobra.Command { Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - var err error if nextEpoch { //nextDelegates @@ -229,9 +223,6 @@ func NewNodeDelegateCmd(client ioctl.Client) *cobra.Command { } cmd.Println(message.String()) } - if err != nil { - cmd.Println(err) - } return nil }, } @@ -239,8 +230,6 @@ func NewNodeDelegateCmd(client ioctl.Client) *cobra.Command { flagEpochNumUsage) cmd.Flags().BoolVarP(&nextEpoch, "next-epoch", "n", false, flagNextEpochUsage) - _nodeStatus = map[bool]string{true: "active", false: ""} - _probatedStatus = map[bool]string{true: "probated", false: ""} return cmd } @@ -259,8 +248,13 @@ func (m *nextDelegatesMessage) String(epochNum uint64) string { formatDataString := "%-41s %4d %-" + strconv.Itoa(aliasLen) + "s %-6s %s" lines = append(lines, fmt.Sprintf(formatTitleString, "Address", "Rank", "Alias", "Status", "Votes")) for _, bp := range m.Delegates { - lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, - bp.Alias, _nodeStatus[bp.Active], bp.Votes)) + if bp.Active { + lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, + bp.Alias, "active", bp.Votes)) + } else { + lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, + bp.Alias, "false", bp.Votes)) + } } return strings.Join(lines, "\n") } @@ -279,8 +273,13 @@ func (m *delegatesMessage) String() string { lines = append(lines, fmt.Sprintf(formatTitleString, "Address", "Rank", "Alias", "Status", "Blocks", "ProbatedStatus", "Votes")) for _, bp := range m.Delegates { - lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, - bp.Alias, _nodeStatus[bp.Active], bp.Production, _probatedStatus[bp.ProbatedStatus], bp.Votes)) + if bp.Active { + lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, + bp.Alias, "active", bp.Production, "probated", bp.Votes)) + } else { + lines = append(lines, fmt.Sprintf(formatDataString, bp.Address, bp.Rank, + bp.Alias, "false", bp.Production, "", bp.Votes)) + } } return strings.Join(lines, "\n") } diff --git a/ioctl/newcmd/node/nodedelegate_test.go b/ioctl/newcmd/node/nodedelegate_test.go index 33032eeca7..c4ae78d9ff 100644 --- a/ioctl/newcmd/node/nodedelegate_test.go +++ b/ioctl/newcmd/node/nodedelegate_test.go @@ -1,6 +1,12 @@ +// Copyright (c) 2022 IoTeX +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. package node import ( + "strings" "testing" "github.com/golang/mock/gomock" @@ -17,67 +23,23 @@ import ( func TestNewNodeDelegateCmd(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - client := mock_ioctlclient.NewMockClient(ctrl) - client.EXPECT().SelectTranslation(gomock.Any()).Return( - "mockTranslationString", config.English).AnyTimes() - client.EXPECT().Config().Return(config.ReadConfig).AnyTimes() + apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) + + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(8) client.EXPECT().AliasMap().Return(map[string]string{ "a": "io1uwnr55vqmhf3xeg5phgurlyl702af6eju542sx", "b": "io1uwnr55vqmhf3xeg5phgurlyl702af6eju542sx", "c": "io1uwnr55vqmhf3xeg5phgurlyl702af6eju542s1", "io1uwnr55vqmhf3xeg5phgurlyl702af6eju542sx": "io1uwnr55vqmhf3xeg5phgurlyl702af6eju542sx", - }).AnyTimes() - - apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) - client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).AnyTimes() + }).Times(2) + client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(5) chainMetaResponse := &iotexapi.GetChainMetaResponse{ChainMeta: &iotextypes.ChainMeta{Epoch: &iotextypes.EpochData{Num: 7000}}} - apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(chainMetaResponse, nil).AnyTimes() - - var testBlockProducersInfo = []*iotexapi.BlockProducerInfo{ - {Address: "io1kr8c6krd7dhxaaqwdkr6erqgu4z0scug3drgja", Votes: "109510794521770016955545668", Active: true, Production: 30}, - {Address: "io1456knehzn9qup8unxlf4q06empz8lqxtp6v5vh", Votes: "102571143552077397264727139", Active: true, Production: 30}, - {Address: "io1ddjluttkzljqfgdtcz9eu3r3s832umy7ylx0ts", Votes: "98090078890392421668851404", Active: true, Production: 30}, - {Address: "io1hgxksz37qtqq9n5n6lkkc9qhaajdklhvkh5969", Votes: "88872577987265387615824262", Active: true, Production: 30}, - {Address: "io14u5d66rt465ykm7t2847qllj0reml27q30kr75", Votes: "84052361753868321848541599", Active: true, Production: 30}, - {Address: "io108h7sa5sap44e244hz649zyk5y4rqzsvnpzxh5", Votes: "83017661686050993422089061", Active: true, Production: 30}, - {Address: "io13q2am9nedrd3n746lsj6qan4pymcpgm94vvx2c", Votes: "81497052527306018062463878", Active: false, Production: 0}, - {Address: "io1gfq9el2gnguus64ex3hu8ajd6e4yzk3f9cz5vx", Votes: "73054892390468670695397385", Active: true, Production: 30}, - {Address: "io1qnec80ark9shjc6uzk45dhm8s50dpc27sjuver", Votes: "72800827559311526331738530", Active: false, Production: 0}, - {Address: "io18tnk59jqdjgpdzz4hq4dl0dwwjkv7gg20fygqn", Votes: "63843185329531983507188064", Active: false, Production: 0}, - {Address: "io1qqaswtu7rcevahucpfxc0zxx088pylwtxnkrrl", Votes: "63494040672622657908022915", Active: true, Production: 30}, - {Address: "io1puxw08ze2jnv5x4943ly273tkyth56p9k6ssv9", Votes: "61309224009653017648938445", Active: true, Production: 30}, - {Address: "io1e5vwdmpkf2hpu2266hx9syu0ursqgqwv0kzrxm", Votes: "58398677997892390932401775", Active: true, Production: 30}, - {Address: "io1et7zkzc76m9twa4gn5xht3urt9mwj05qvdtj66", Votes: "57884530935762751497295107", Active: false, Production: 0}, - {Address: "io1fra0fx6akacny9asewt7vyvggqq4rtq3eznccr", Votes: "57699934366242359064327183", Active: false, Production: 0}, - {Address: "io1mcyk4aqmwgn7zjx0n9ggdtpm9x6y9pkdze3u39", Votes: "56936017082584646690083786", Active: true, Production: 30}, - {Address: "io1tf7tu2xt6mpk8s70ahugsx20jqgu9eg6v48qlk", Votes: "54356930593139259174591454", Active: true, Production: 30}, - {Address: "io10reczcaelglh5xmkay65h9vw3e5dp82e8vw0rz", Votes: "54142015787191991384650558", Active: true, Production: 30}, - {Address: "io195mh6ftwz5vnagw984fj4hj8awty3ue2gh457f", Votes: "53438501418406316391702941", Active: false, Production: 0}, - {Address: "io1vl0wnuwtjv46deah8qny82g5d9rr45cl0fcsg3", Votes: "50439414145173805775719477", Active: true, Production: 30}, - {Address: "io12fa96hxh9ata23gwp5pfxztzaawvwl2sk5xmdg", Votes: "47616018438106266407182199", Active: true, Production: 30}, - {Address: "io1tfke5nfwryte6nultpmqefadgm0dsahm2gm63k", Votes: "47547651449309094613905900", Active: true, Production: 30}, - {Address: "io1cw8x7ruxeqqcklmlxc5yxqfu2txd2hgv8rt6j7", Votes: "45296383525563818835234318", Active: false, Production: 0}, - {Address: "io1zhefl8l5e9sw93kf3f7jz7an9zqqnvkvyxd4f0", Votes: "44753889793475843962376641", Active: true, Production: 30}, - {Address: "io13672hgsdr7d8nu5jndyageygel3r5nwyzqwlhl", Votes: "43351538438466056259112950", Active: false, Production: 0}, - {Address: "io1lcpdct3sr7lg53x23aylungmmdrn5jq0vlnclu", Votes: "42277928969095512626332913", Active: false, Production: 0}, - {Address: "io1z4sxtefurklkyrfmmdtjmw4h8csnxlv9747hyd", Votes: "41525283055065104346674271", Active: true, Production: 30}, - {Address: "io1ckvhh2nym5ejehklmn3ql6c52f6nfdnguspj5n", Votes: "41346686489279940040900234", Active: true, Production: 30}, - {Address: "io13xdhg9du56khumz3sg6a3ma5q5kjx7vdlx48x8", Votes: "40446200570810948673568854", Active: true, Production: 30}, - {Address: "io1ztqalgh0zl9309a48k7wjwyump6agq24cf4zdq", Votes: "39737835497414451631412012", Active: false, Production: 0}, - {Address: "io1n3llm0zzlles6pvpzugzajyzyjehztztxf2rff", Votes: "39619838039171064163081805", Active: true, Production: 32}, - {Address: "io1ug4qkvsyapznevum0sdj9tl37qdhcwz9cxy6ks", Votes: "38699057276054350901849107", Active: true, Production: 28}, - {Address: "io1zy9q4myp3jezxdsv82z3f865ruamhqm7a6mggh", Votes: "38006759895576284703944491", Active: true, Production: 30}, - {Address: "io1y5yafr6y48ck234hudvnslszutma9vhdy4l2au", Votes: "37923375250314530385988502", Active: false, Production: 0}, - {Address: "io1u4pev9u5as7ujpk29wpsrc95m8kuhec3pmuk72", Votes: "37259902890070294856582714", Active: true, Production: 30}, - {Address: "io1hczkhdcpf2a7dxhydspxqp0ycmu9ejyud6v43d", Votes: "36504518325780350328469428", Active: false, Production: 0}, - } - epochMetaResponse := &iotexapi.GetEpochMetaResponse{EpochData: &iotextypes.EpochData{Num: 7000, Height: 3223081}, TotalBlocks: 720, BlockProducersInfo: testBlockProducersInfo} - apiServiceClient.EXPECT().GetEpochMeta(gomock.Any(), gomock.Any()).Return(epochMetaResponse, nil).AnyTimes() - probationList := &iotexapi.ReadStateResponse{} - apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.Any()).Return(probationList, nil).AnyTimes() + + apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(chainMetaResponse, nil).Times(2) + apiServiceClient.EXPECT().ReadState(gomock.Any(), gomock.Any()).Return(probationList, nil).Times(3) t.Run("next epoch", func(t *testing.T) { cmd := NewNodeDelegateCmd(client) @@ -87,11 +49,53 @@ func TestNewNodeDelegateCmd(t *testing.T) { }) t.Run("get zero delegate epoch", func(t *testing.T) { + var testBlockProducersInfo = []*iotexapi.BlockProducerInfo{ + {Address: "io1kr8c6krd7dhxaaqwdkr6erqgu4z0scug3drgja", Votes: "109510794521770016955545668", Active: true, Production: 30}, + {Address: "io1456knehzn9qup8unxlf4q06empz8lqxtp6v5vh", Votes: "102571143552077397264727139", Active: true, Production: 30}, + {Address: "io1ddjluttkzljqfgdtcz9eu3r3s832umy7ylx0ts", Votes: "98090078890392421668851404", Active: true, Production: 30}, + {Address: "io1hgxksz37qtqq9n5n6lkkc9qhaajdklhvkh5969", Votes: "88872577987265387615824262", Active: true, Production: 30}, + {Address: "io14u5d66rt465ykm7t2847qllj0reml27q30kr75", Votes: "84052361753868321848541599", Active: true, Production: 30}, + {Address: "io108h7sa5sap44e244hz649zyk5y4rqzsvnpzxh5", Votes: "83017661686050993422089061", Active: true, Production: 30}, + {Address: "io13q2am9nedrd3n746lsj6qan4pymcpgm94vvx2c", Votes: "81497052527306018062463878", Active: false, Production: 0}, + {Address: "io1gfq9el2gnguus64ex3hu8ajd6e4yzk3f9cz5vx", Votes: "73054892390468670695397385", Active: true, Production: 30}, + {Address: "io1qnec80ark9shjc6uzk45dhm8s50dpc27sjuver", Votes: "72800827559311526331738530", Active: false, Production: 0}, + {Address: "io18tnk59jqdjgpdzz4hq4dl0dwwjkv7gg20fygqn", Votes: "63843185329531983507188064", Active: false, Production: 0}, + {Address: "io1qqaswtu7rcevahucpfxc0zxx088pylwtxnkrrl", Votes: "63494040672622657908022915", Active: true, Production: 30}, + {Address: "io1puxw08ze2jnv5x4943ly273tkyth56p9k6ssv9", Votes: "61309224009653017648938445", Active: true, Production: 30}, + {Address: "io1e5vwdmpkf2hpu2266hx9syu0ursqgqwv0kzrxm", Votes: "58398677997892390932401775", Active: true, Production: 30}, + {Address: "io1et7zkzc76m9twa4gn5xht3urt9mwj05qvdtj66", Votes: "57884530935762751497295107", Active: false, Production: 0}, + {Address: "io1fra0fx6akacny9asewt7vyvggqq4rtq3eznccr", Votes: "57699934366242359064327183", Active: false, Production: 0}, + {Address: "io1mcyk4aqmwgn7zjx0n9ggdtpm9x6y9pkdze3u39", Votes: "56936017082584646690083786", Active: true, Production: 30}, + {Address: "io1tf7tu2xt6mpk8s70ahugsx20jqgu9eg6v48qlk", Votes: "54356930593139259174591454", Active: true, Production: 30}, + {Address: "io10reczcaelglh5xmkay65h9vw3e5dp82e8vw0rz", Votes: "54142015787191991384650558", Active: true, Production: 30}, + {Address: "io195mh6ftwz5vnagw984fj4hj8awty3ue2gh457f", Votes: "53438501418406316391702941", Active: false, Production: 0}, + {Address: "io1vl0wnuwtjv46deah8qny82g5d9rr45cl0fcsg3", Votes: "50439414145173805775719477", Active: true, Production: 30}, + {Address: "io12fa96hxh9ata23gwp5pfxztzaawvwl2sk5xmdg", Votes: "47616018438106266407182199", Active: true, Production: 30}, + {Address: "io1tfke5nfwryte6nultpmqefadgm0dsahm2gm63k", Votes: "47547651449309094613905900", Active: true, Production: 30}, + {Address: "io1cw8x7ruxeqqcklmlxc5yxqfu2txd2hgv8rt6j7", Votes: "45296383525563818835234318", Active: false, Production: 0}, + {Address: "io1zhefl8l5e9sw93kf3f7jz7an9zqqnvkvyxd4f0", Votes: "44753889793475843962376641", Active: true, Production: 30}, + {Address: "io13672hgsdr7d8nu5jndyageygel3r5nwyzqwlhl", Votes: "43351538438466056259112950", Active: false, Production: 0}, + {Address: "io1lcpdct3sr7lg53x23aylungmmdrn5jq0vlnclu", Votes: "42277928969095512626332913", Active: false, Production: 0}, + {Address: "io1z4sxtefurklkyrfmmdtjmw4h8csnxlv9747hyd", Votes: "41525283055065104346674271", Active: true, Production: 30}, + {Address: "io1ckvhh2nym5ejehklmn3ql6c52f6nfdnguspj5n", Votes: "41346686489279940040900234", Active: true, Production: 30}, + {Address: "io13xdhg9du56khumz3sg6a3ma5q5kjx7vdlx48x8", Votes: "40446200570810948673568854", Active: true, Production: 30}, + {Address: "io1ztqalgh0zl9309a48k7wjwyump6agq24cf4zdq", Votes: "39737835497414451631412012", Active: false, Production: 0}, + {Address: "io1n3llm0zzlles6pvpzugzajyzyjehztztxf2rff", Votes: "39619838039171064163081805", Active: true, Production: 32}, + {Address: "io1ug4qkvsyapznevum0sdj9tl37qdhcwz9cxy6ks", Votes: "38699057276054350901849107", Active: true, Production: 28}, + {Address: "io1zy9q4myp3jezxdsv82z3f865ruamhqm7a6mggh", Votes: "38006759895576284703944491", Active: true, Production: 30}, + {Address: "io1y5yafr6y48ck234hudvnslszutma9vhdy4l2au", Votes: "37923375250314530385988502", Active: false, Production: 0}, + {Address: "io1u4pev9u5as7ujpk29wpsrc95m8kuhec3pmuk72", Votes: "37259902890070294856582714", Active: true, Production: 30}, + {Address: "io1hczkhdcpf2a7dxhydspxqp0ycmu9ejyud6v43d", Votes: "36504518325780350328469428", Active: false, Production: 0}, + } + epochMetaResponse := &iotexapi.GetEpochMetaResponse{EpochData: &iotextypes.EpochData{Num: 7000, Height: 3223081}, TotalBlocks: 720, BlockProducersInfo: testBlockProducersInfo} + + apiServiceClient.EXPECT().GetEpochMeta(gomock.Any(), gomock.Any()).Return(epochMetaResponse, nil) + cmd := NewNodeDelegateCmd(client) result, err := util.ExecuteCmd(cmd) require.NoError(err) - require.Contains(result, "io1kr8c6krd7dhxaaqwdkr6erqgu4z0scug3drgja") - require.Contains(result, "109510794.521770016955545668") - + require.Contains(result, "io13q2am9nedrd3n746lsj6qan4pymcpgm94vvx2c") + require.Contains(result, "81497052.527306018062463878") + require.Equal(12, len(strings.Split(result, "false"))-1) }) } From 612495da6df02ec63bdf0ae384f3a243538ffa05 Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Sat, 25 Jun 2022 14:38:24 +0800 Subject: [PATCH 12/24] [ioctl] Refactor nodereward command in new ioctl (#3416) * [ioctl] refactor nodereward command in new ioctl * refactor unit test to cover the modification * refactor new nodereward as ioctl/cmd/nodereward structure * refactor unit test to cover the modification * delete useless message * fix client.APIServiceClient() Co-authored-by: huofei <68298506@qq.com> Co-authored-by: CoderZhi --- ioctl/newcmd/node/nodereward.go | 239 ++++++++++++++------------- ioctl/newcmd/node/nodereward_test.go | 164 +++++++++++++----- 2 files changed, 247 insertions(+), 156 deletions(-) diff --git a/ioctl/newcmd/node/nodereward.go b/ioctl/newcmd/node/nodereward.go index 19d0e493f6..3ab44fc421 100644 --- a/ioctl/newcmd/node/nodereward.go +++ b/ioctl/newcmd/node/nodereward.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 IoTeX Foundation +// Copyright (c) 2022 IoTeX Foundation // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -8,165 +8,166 @@ package node import ( "context" - "fmt" "math/big" + "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/pkg/errors" "github.com/spf13/cobra" "google.golang.org/grpc/status" - "github.com/iotexproject/iotex-proto/golang/iotexapi" - "github.com/iotexproject/iotex-core/ioctl" "github.com/iotexproject/iotex-core/ioctl/config" - "github.com/iotexproject/iotex-core/ioctl/output" "github.com/iotexproject/iotex-core/ioctl/util" ) // Multi-language support var ( - _rewardUses = map[config.Language]string{ - config.English: "reward [ALIAS|DELEGATE_ADDRESS]", - config.Chinese: "reward [别名|委托地址]", + _rewardCmdUses = map[config.Language]string{ + config.English: "reward unclaimed|pool [ALIAS|DELEGATE_ADDRESS]", + config.Chinese: "reward 未支取|奖金池 [别名|委托地址]", } - _rewardShorts = map[config.Language]string{ + _rewardCmdShorts = map[config.Language]string{ config.English: "Query rewards", config.Chinese: "查询奖励", } - _rewardPoolMessageTranslations = map[config.Language]string{ - config.English: "Available Reward: %s IOTX Total Reward: %s IOTX", - config.Chinese: "可用奖金: %s IOTX 总奖金: %s IOTX", + _rewardPoolLong = map[config.Language]string{ + config.English: "ioctl node reward pool returns unclaimed and available Rewards in fund pool.\nTotalUnclaimed is the amount of all delegates that have been issued but are not claimed;\nTotalAvailable is the amount of balance that has not been issued to anyone.\n\nioctl node reward unclaimed [ALIAS|DELEGATE_ADDRESS] returns unclaimed rewards of a specific delegate.", + config.Chinese: "ioctl node reward 返回奖金池中的未支取奖励和可获取的奖励. TotalUnclaimed是所有代表已被发放但未支取的奖励的总和; TotalAvailable 是奖金池中未被发放的奖励的总和.\n\nioctl node [ALIAS|DELEGATE_ADDRESS] 返回特定代表的已被发放但未支取的奖励.", } ) // NewNodeRewardCmd represents the node reward command -func NewNodeRewardCmd(c ioctl.Client) *cobra.Command { - use, _ := c.SelectTranslation(_rewardUses) - short, _ := c.SelectTranslation(_rewardShorts) - rewardPoolMessageTranslation, _ := c.SelectTranslation(_rewardPoolMessageTranslations) - nc := &cobra.Command{ +func NewNodeRewardCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_rewardCmdUses) + short, _ := client.SelectTranslation(_rewardCmdShorts) + long, _ := client.SelectTranslation(_rewardPoolLong) + + return &cobra.Command{ Use: use, Short: short, - Args: cobra.MaximumNArgs(1), + Args: cobra.RangeArgs(1, 2), + Long: long, RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - var err error - if len(args) == 0 { - - apiClient, err := c.APIServiceClient() - if err != nil { - return err - } - - response, err := apiClient.ReadState( - context.Background(), - &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("AvailableBalance"), - }, - ) - - if err != nil { - sta, ok := status.FromError(err) - if ok { - return output.NewError(output.APIError, sta.Message(), nil) - } - return output.NewError(output.NetworkError, "failed to invoke ReadState api", err) - } - - availableRewardRau, ok := new(big.Int).SetString(string(response.Data), 10) - if !ok { - return output.NewError(output.ConvertError, "failed to convert string into big int", err) + switch args[0] { + case "pool": + if len(args) != 1 { + return errors.New("wrong number of arg(s) for ioctl node reward pool command. \nRun 'ioctl node reward --help' for usage") } - - response, err = apiClient.ReadState( - context.Background(), - &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("TotalBalance"), - }, - ) + totalUnclaimed, totalAvailable, totalBalance, err := rewardPool(client) if err != nil { - sta, ok := status.FromError(err) - if ok { - return output.NewError(output.APIError, sta.Message(), nil) - } - return output.NewError(output.NetworkError, "failed to invoke ReadState api", err) - } - totalRewardRau, ok := new(big.Int).SetString(string(response.Data), 10) - if !ok { - return output.NewError(output.ConvertError, "failed to convert string into big int", err) - } - - message := rewardPoolMessage{ - AvailableReward: util.RauToString(availableRewardRau, util.IotxDecimalNum), - TotalReward: util.RauToString(totalRewardRau, util.IotxDecimalNum), + return err } - fmt.Println(message.String(rewardPoolMessageTranslation)) - - } else { - arg := args[0] - address, err := c.Address(arg) - if err != nil { - return output.NewError(output.AddressError, "failed to get address", err) + cmd.Printf("Total Unclaimed:\t %s IOTX\nTotal Available:\t %s IOTX\nTotal Balance:\t\t %s IOTX\n", + totalUnclaimed, totalAvailable, totalBalance) + case "unclaimed": + if len(args) != 2 { + return errors.New("wrong number of arg(s) for ioctl node reward unclaimed [ALIAS|DELEGATE_ADDRESS] command. \nRun 'ioctl node reward --help' for usage") } - apiClient, err := c.APIServiceClient() + address, reward, err := reward(client, args[1]) if err != nil { return err } - - response, err := apiClient.ReadState( - context.Background(), - &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("UnclaimedBalance"), - Arguments: [][]byte{[]byte(address)}, - }, - ) - if err != nil { - sta, ok := status.FromError(err) - if ok { - return output.NewError(output.APIError, sta.Message(), nil) - } - return output.NewError(output.NetworkError, "failed to get version from server", err) - } - rewardRau, ok := new(big.Int).SetString(string(response.Data), 10) - if !ok { - return output.NewError(output.ConvertError, "failed to convert string into big int", err) - } - message := rewardMessage{Address: address, Reward: util.RauToString(rewardRau, util.IotxDecimalNum)} - fmt.Println(message.String()) - + cmd.Printf("%s: %s IOTX\n", address, reward) + default: + return errors.New("unknown command. \nRun 'ioctl node reward --help' for usage") } - return output.PrintError(err) + return nil }, } - return nc } -type rewardPoolMessage struct { - AvailableReward string `json:"availableReward"` - TotalReward string `json:"totalReward"` -} +func rewardPool(client ioctl.Client) (string, string, string, error) { + apiClient, err := client.APIServiceClient() + if err != nil { + return "", "", "", err + } + ctx := context.Background() + jwtMD, err := util.JwtAuth() + if err == nil { + ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx) + } + response, err := apiClient.ReadState( + ctx, + &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("AvailableBalance"), + }, + ) + if err != nil { + sta, ok := status.FromError(err) + if ok { + return "", "", "", errors.New(sta.Message()) + } + return "", "", "", errors.Wrap(err, "failed to invoke ReadState api") + } -func (m *rewardPoolMessage) String(trans ...string) string { + availableRewardRau, ok := new(big.Int).SetString(string(response.Data), 10) + if !ok { + return "", "", "", errors.New("failed to convert string into big int") + } - if output.Format == "" { - message := fmt.Sprintf(trans[0], - m.AvailableReward, m.TotalReward) - return message + response, err = apiClient.ReadState( + context.Background(), + &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("TotalBalance"), + }, + ) + if err != nil { + sta, ok := status.FromError(err) + if ok { + return "", "", "", errors.New(sta.Message()) + } + return "", "", "", errors.Wrap(err, "failed to invoke ReadState api") } - return output.FormatStringWithTrans(output.Result, m) -} + totalRewardRau, ok := new(big.Int).SetString(string(response.Data), 10) + if !ok { + return "", "", "", errors.New("failed to convert string into big int") + } + + totalUnclaimedRewardRau := big.NewInt(0) + totalUnclaimedRewardRau.Sub(totalRewardRau, availableRewardRau) -type rewardMessage struct { - Address string `json:"address"` - Reward string `json:"reward"` + return util.RauToString(totalUnclaimedRewardRau, util.IotxDecimalNum), + util.RauToString(availableRewardRau, util.IotxDecimalNum), + util.RauToString(totalRewardRau, util.IotxDecimalNum), + err } -func (m *rewardMessage) String(trans ...string) string { - if output.Format == "" { - message := fmt.Sprintf("%s: %s IOTX", m.Address, m.Reward) - return message +func reward(client ioctl.Client, arg string) (string, string, error) { + address, err := client.Address(arg) + if err != nil { + return "", "", errors.Wrap(err, "failed to get address") + } + apiClient, err := client.APIServiceClient() + if err != nil { + return "", "", errors.Wrap(err, "failed to connect to endpoint") + } + ctx := context.Background() + jwtMD, err := util.JwtAuth() + if err == nil { + ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx) + } + response, err := apiClient.ReadState( + ctx, + &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("UnclaimedBalance"), + Arguments: [][]byte{[]byte(address)}, + }, + ) + if err != nil { + sta, ok := status.FromError(err) + if ok { + return "", "", errors.New(sta.Message()) + } + return "", "", errors.Wrap(err, "failed to get version from server") + } + rewardRau, ok := new(big.Int).SetString(string(response.Data), 10) + if !ok { + return "", "", errors.New("failed to convert string into big int") } - return output.FormatStringWithTrans(output.Result, m) + return address, util.RauToString(rewardRau, util.IotxDecimalNum), err } diff --git a/ioctl/newcmd/node/nodereward_test.go b/ioctl/newcmd/node/nodereward_test.go index 51fd347c43..eed0d3c6b0 100644 --- a/ioctl/newcmd/node/nodereward_test.go +++ b/ioctl/newcmd/node/nodereward_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 IoTeX Foundation +// Copyright (c) 2022 IoTeX Foundation // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -12,6 +12,7 @@ import ( "github.com/golang/mock/gomock" "github.com/iotexproject/iotex-proto/golang/iotexapi" "github.com/iotexproject/iotex-proto/golang/iotexapi/mock_iotexapi" + "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/iotexproject/iotex-core/ioctl/config" @@ -20,46 +21,135 @@ import ( ) func TestNewNodeRewardCmd(t *testing.T) { + require := require.New(t) ctrl := gomock.NewController(t) - client := mock_ioctlclient.NewMockClient(ctrl) - client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).AnyTimes() + apiClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) - client.EXPECT().Address(gomock.Any()).Return("test_address", nil).Times(1) + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(24) + client.EXPECT().APIServiceClient().Return(apiClient, nil).Times(7) - apiClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) + t.Run("get node reward pool", func(t *testing.T) { + t.Run("get available reward & total reward", func(t *testing.T) { + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("AvailableBalance"), + }).Return(&iotexapi.ReadStateResponse{ + Data: []byte("24361490367906930338205776")}, + nil) + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("TotalBalance"), + }).Return(&iotexapi.ReadStateResponse{ + Data: []byte("52331682309272536203174665")}, + nil) + + cmd := NewNodeRewardCmd(client) + result, err := util.ExecuteCmd(cmd, "pool") + require.NoError(err) + require.Contains(result, "24361490.367906930338205776") + require.Contains(result, "52331682.309272536203174665") + }) + + t.Run("failed to invoke AvailableBalance api", func(t *testing.T) { + expectedErr := errors.New("failed to invoke ReadState api") + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("AvailableBalance"), + }).Return(nil, expectedErr) + + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "pool") + require.Contains(err.Error(), expectedErr.Error()) + }) + + t.Run("failed to convert string into big int", func(t *testing.T) { + expectedErr := errors.New("failed to convert string into big int") + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("AvailableBalance"), + }).Return(&iotexapi.ReadStateResponse{ + Data: []byte("0x24361490367906930338205776")}, + nil) + + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "pool") + require.Contains(err.Error(), expectedErr.Error()) + }) + + t.Run("failed to invoke TotalBalance api", func(t *testing.T) { + expectedErr := errors.New("failed to invoke ReadState api") + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("AvailableBalance"), + }).Return(&iotexapi.ReadStateResponse{ + Data: []byte("24361490367906930338205776")}, + nil) + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("TotalBalance"), + }).Return(nil, expectedErr) + + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "pool") + require.Contains(err.Error(), expectedErr.Error()) + }) + }) + + t.Run("get unclaimed node reward", func(t *testing.T) { + t.Run("get balance by address", func(t *testing.T) { + client.EXPECT().Address(gomock.Any()).Return("test_address", nil).Times(1) + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("UnclaimedBalance"), + Arguments: [][]byte{[]byte("test_address")}, + }).Return(&iotexapi.ReadStateResponse{ + Data: []byte("0"), + }, nil) + + cmd := NewNodeRewardCmd(client) + result, err := util.ExecuteCmd(cmd, "unclaimed", "test") + require.NoError(err) + require.Contains(result, "test_address: 0 IOTX") + }) + + t.Run("failed to get address", func(t *testing.T) { + expectedErr := errors.New("failed to get address") + client.EXPECT().Address(gomock.Any()).Return("", expectedErr) + + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "unclaimed", "test") + require.Contains(err.Error(), expectedErr.Error()) + }) + + t.Run("failed to get version from server", func(t *testing.T) { + expectedErr := errors.New("failed to get version from server") + + client.EXPECT().Address(gomock.Any()).Return("test_address", nil).Times(1) + + apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ + ProtocolID: []byte("rewarding"), + MethodName: []byte("UnclaimedBalance"), + Arguments: [][]byte{[]byte("test_address")}, + }).Return(nil, expectedErr) + + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "unclaimed", "test") + require.Contains(err.Error(), expectedErr.Error()) + }) + }) - apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("UnclaimedBalance"), - Arguments: [][]byte{[]byte("test_address")}, - }).Return(&iotexapi.ReadStateResponse{ - Data: []byte("0")}, - nil) - - apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("AvailableBalance"), - }).Return(&iotexapi.ReadStateResponse{ - Data: []byte("24361490367906930338205776")}, - nil) - - apiClient.EXPECT().ReadState(gomock.Any(), &iotexapi.ReadStateRequest{ - ProtocolID: []byte("rewarding"), - MethodName: []byte("TotalBalance"), - }).Return(&iotexapi.ReadStateResponse{ - Data: []byte("52331682309272536203174665")}, - nil) - - client.EXPECT().APIServiceClient().Return(apiClient, nil).AnyTimes() - cmd := NewNodeRewardCmd(client) - - result, err := util.ExecuteCmd(cmd, "test") - require.NotNil(t, result) - require.NoError(t, err) - - result, err = util.ExecuteCmd(cmd) - require.NotNil(t, result) - require.NoError(t, err) + t.Run("unknown command", func(t *testing.T) { + expectedErr := errors.New("unknown command. \nRun 'ioctl node reward --help' for usage") + cmd := NewNodeRewardCmd(client) + _, err := util.ExecuteCmd(cmd, "") + require.Contains(err.Error(), expectedErr.Error()) + }) } From ae9b4fd98ab44c8e73d84dbe809bd37609d03364 Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Sat, 25 Jun 2022 16:30:28 +0800 Subject: [PATCH 13/24] [ioctl] Build hdwallet export command line into new ioctl (#3423) * [ioctl] build hdwallet export command line into new ioctl * Update command description * fix commit * create ExportHdwallet client interface combine hdwalletderive & hdwalletexport code and create ExportHdwallet client interface * fix commit * fix commit * add unittest for ExportHdwallet * add unit test * delete useless gomock func in test * change return type of HdwalletMnemonic * fix commit * keep format consistent Co-authored-by: huofei <68298506@qq.com> Co-authored-by: CoderZhi --- ioctl/client.go | 29 ++++++++++ ioctl/client_test.go | 16 ++++++ ioctl/newcmd/hdwallet/hdwalletexport.go | 56 +++++++++++++++++++ ioctl/newcmd/hdwallet/hdwalletexport_test.go | 48 ++++++++++++++++ .../mock/mock_ioctlclient/mock_ioctlclient.go | 15 +++++ 5 files changed, 164 insertions(+) create mode 100644 ioctl/newcmd/hdwallet/hdwalletexport.go create mode 100644 ioctl/newcmd/hdwallet/hdwalletexport_test.go diff --git a/ioctl/client.go b/ioctl/client.go index 9f2ade15c8..01f6e690d2 100644 --- a/ioctl/client.go +++ b/ioctl/client.go @@ -79,6 +79,8 @@ type ( QueryAnalyser(interface{}) (*http.Response, error) // ReadInput reads the input from stdin ReadInput() (string, error) + // HdwalletMnemonic returns the mnemonic of hdwallet + HdwalletMnemonic(string) (string, error) // WriteHdWalletConfigFile write encrypting mnemonic into config file WriteHdWalletConfigFile(string, string) error // IsHdWalletConfigFileExist return true if config file is existed, false if not existed @@ -329,6 +331,33 @@ func (c *client) ReadInput() (string, error) { // notest return line, nil } +func (c *client) HdwalletMnemonic(password string) (string, error) { + // derive key as "m/44'/304'/account'/change/index" + if !c.IsHdWalletConfigFileExist() { + return "", errors.New("run 'ioctl hdwallet create' to create your HDWallet first") + } + enctxt, err := os.ReadFile(c.hdWalletConfigFile) + if err != nil { + return "", errors.Wrapf(err, "failed to read config file %s", c.hdWalletConfigFile) + } + + enckey := util.HashSHA256([]byte(password)) + dectxt, err := util.Decrypt(enctxt, enckey) + if err != nil { + return "", errors.Wrap(err, "failed to decrypt") + } + + dectxtLen := len(dectxt) + if dectxtLen <= 32 { + return "", errors.Errorf("incorrect data dectxtLen %d", dectxtLen) + } + mnemonic, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:] + if !bytes.Equal(hash, util.HashSHA256(mnemonic)) { + return "", errors.New("password error") + } + return string(mnemonic), nil +} + func (c *client) WriteHdWalletConfigFile(mnemonic string, password string) error { enctxt := append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...) enckey := util.HashSHA256([]byte(password)) diff --git a/ioctl/client_test.go b/ioctl/client_test.go index e6958d0036..27212b5fd1 100644 --- a/ioctl/client_test.go +++ b/ioctl/client_test.go @@ -343,6 +343,22 @@ func TestDeleteAlias(t *testing.T) { } } +func TestHdwalletMnemonic(t *testing.T) { + r := require.New(t) + testPathWallet, err := os.MkdirTemp(os.TempDir(), "cfgWallet") + r.NoError(err) + defer testutil.CleanupPath(testPathWallet) + c := NewClient(config.Config{ + Wallet: testPathWallet, + }, testPathWallet+"/config.default") + mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" + password := "123" + r.NoError(c.WriteHdWalletConfigFile(mnemonic, password)) + result, err := c.HdwalletMnemonic(password) + r.NoError(err) + r.Equal(mnemonic, result) +} + func TestWriteHdWalletConfigFile(t *testing.T) { r := require.New(t) testPathWallet, err := os.MkdirTemp(os.TempDir(), "cfgWallet") diff --git a/ioctl/newcmd/hdwallet/hdwalletexport.go b/ioctl/newcmd/hdwallet/hdwalletexport.go new file mode 100644 index 0000000000..2fd6c22b8a --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletexport.go @@ -0,0 +1,56 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" +) + +// Multi-language support +var ( + _hdwalletExportCmdShorts = map[config.Language]string{ + config.English: "export hdwallet mnemonic using password", + config.Chinese: "通过密码导出钱包助记词", + } + _hdwalletExportCmdUses = map[config.Language]string{ + config.English: "export", + config.Chinese: "export 导出", + } +) + +// NewHdwalletExportCmd represents the hdwallet export command +func NewHdwalletExportCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_hdwalletExportCmdUses) + short, _ := client.SelectTranslation(_hdwalletExportCmdShorts) + + return &cobra.Command{ + Use: use, + Short: short, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + + cmd.Println("Enter password") + password, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + + mnemonic, err := client.HdwalletMnemonic(password) + if err != nil { + return errors.Wrap(err, "failed to export mnemonic") + } + cmd.Printf("Mnemonic phrase: %s"+ + "It is used to recover your wallet in case you forgot the password. Write them down and store it in a safe place.\n", mnemonic) + return nil + }, + } +} diff --git a/ioctl/newcmd/hdwallet/hdwalletexport_test.go b/ioctl/newcmd/hdwallet/hdwalletexport_test.go new file mode 100644 index 0000000000..95d421b316 --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletexport_test.go @@ -0,0 +1,48 @@ +// Copyright (c) 2022 IoTeX +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNewHdwalletExportCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(4) + mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" + password := "123" + + t.Run("export hdwallet", func(t *testing.T) { + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().HdwalletMnemonic(gomock.Any()).Return(mnemonic, nil) + + cmd := NewHdwalletExportCmd(client) + result, err := util.ExecuteCmd(cmd) + require.NoError(err) + require.Contains(result, mnemonic) + }) + + t.Run("failed to export mnemonic", func(t *testing.T) { + expectedErr := errors.New("failed to export mnemonic") + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().HdwalletMnemonic(gomock.Any()).Return("", expectedErr) + + cmd := NewHdwalletExportCmd(client) + _, err := util.ExecuteCmd(cmd) + require.Contains(err.Error(), expectedErr.Error()) + }) +} diff --git a/test/mock/mock_ioctlclient/mock_ioctlclient.go b/test/mock/mock_ioctlclient/mock_ioctlclient.go index fe20c71849..90ca0efe67 100644 --- a/test/mock/mock_ioctlclient/mock_ioctlclient.go +++ b/test/mock/mock_ioctlclient/mock_ioctlclient.go @@ -169,6 +169,21 @@ func (mr *MockClientMockRecorder) Execute(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockClient)(nil).Execute), arg0) } +// HdwalletMnemonic mocks base method. +func (m *MockClient) HdwalletMnemonic(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HdwalletMnemonic", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HdwalletMnemonic indicates an expected call of HdwalletMnemonic. +func (mr *MockClientMockRecorder) HdwalletMnemonic(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HdwalletMnemonic", reflect.TypeOf((*MockClient)(nil).HdwalletMnemonic), arg0) +} + // IsCryptoSm2 mocks base method. func (m *MockClient) IsCryptoSm2() bool { m.ctrl.T.Helper() From fd6561a3415f4eab19b7f90d7c919474ffd793ce Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Mon, 27 Jun 2022 11:29:46 +0800 Subject: [PATCH 14/24] [ioctl] Build action hash command line into new ioctl (#3425) * [ioctl] build action hash command line into new ioctl * replace ConnectToEndpoint with APIServiceClient * use client interface * move Match to client interface * revert Match client interface * fix panic in unit test * refactor unit test to cover the modification * fix client.APIServiceClient() * add func alias * add client.Alias(address) * delete useless ErrNoAliasFound Co-authored-by: huof6890 <68298506@qq.com> Co-authored-by: CoderZhi --- ioctl/client.go | 14 + ioctl/client_test.go | 22 ++ ioctl/newcmd/action/actionhash.go | 307 ++++++++++++++++++ ioctl/newcmd/action/actionhash_test.go | 120 +++++++ .../mock/mock_ioctlclient/mock_ioctlclient.go | 15 + 5 files changed, 478 insertions(+) create mode 100644 ioctl/newcmd/action/actionhash.go create mode 100644 ioctl/newcmd/action/actionhash_test.go diff --git a/ioctl/client.go b/ioctl/client.go index 01f6e690d2..b6375b03a4 100644 --- a/ioctl/client.go +++ b/ioctl/client.go @@ -65,6 +65,8 @@ type ( DecryptPrivateKey(string, string) (*ecdsa.PrivateKey, error) // AliasMap returns the alias map: accountAddr-aliasName AliasMap() map[string]string + // Alias returns the alias corresponding to address + Alias(string) (string, error) // SetAlias updates aliasname and account address and not write them into the default config file SetAlias(string, string) // SetAliasAndSave updates aliasname and account address and write them into the default config file @@ -275,6 +277,18 @@ func (c *client) AliasMap() map[string]string { return aliases } +func (c *client) Alias(address string) (string, error) { + if err := validator.ValidateAddress(address); err != nil { + return "", err + } + for aliasName, addr := range c.cfg.Aliases { + if addr == address { + return aliasName, nil + } + } + return "", errors.New("no alias is found") +} + func (c *client) SetAlias(aliasName string, addr string) { for k, v := range c.cfg.Aliases { if v == addr { diff --git a/ioctl/client_test.go b/ioctl/client_test.go index 27212b5fd1..671b61b132 100644 --- a/ioctl/client_test.go +++ b/ioctl/client_test.go @@ -193,6 +193,28 @@ func TestAliasMap(t *testing.T) { r.Equal(exprAliases, result) } +func TestAlias(t *testing.T) { + r := require.New(t) + cfg := config.Config{ + Aliases: map[string]string{ + "aaa": "io1cjh35tq9k8fu0gqcsat4px7yr8trh75c95hc5r", + "bbb": "io187evpmjdankjh0g5dfz83w2z3p23ljhn4s9jw7", + }, + } + configFilePath := writeTempConfig(t, &cfg) + defer testutil.CleanupPath(path.Dir(configFilePath)) + cfgload := loadTempConfig(t, configFilePath) + r.Equal(cfg, cfgload) + + c := NewClient(cfgload, configFilePath) + defer c.Stop(context.Background()) + for alias, addr := range cfg.Aliases { + result, err := c.Alias(addr) + r.NoError(err) + r.Equal(alias, result) + } +} + func TestSetAlias(t *testing.T) { type Data struct { cfg config.Config diff --git a/ioctl/newcmd/action/actionhash.go b/ioctl/newcmd/action/actionhash.go new file mode 100644 index 0000000000..46ed90ca4c --- /dev/null +++ b/ioctl/newcmd/action/actionhash.go @@ -0,0 +1,307 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package action + +import ( + "context" + "encoding/hex" + "fmt" + "log" + "math/big" + "strconv" + + protoV1 "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" + "github.com/iotexproject/go-pkgs/crypto" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/iotexproject/iotex-core/action/protocol/staking" + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" +) + +type actionState int + +const ( + // Pending action is in the action pool but not executed by blockchain + Pending actionState = iota + // Executed action has been run and recorded on blockchain + Executed +) + +// Multi-language support +var ( + _hashCmdShorts = map[config.Language]string{ + config.English: "Get action by hash", + config.Chinese: "依据哈希值,获取交易", + } + _hashCmdUses = map[config.Language]string{ + config.English: "hash ACTION_HASH", + config.Chinese: "hash 交易哈希", + } +) + +// NewActionHashCmd represents the action hash command +func NewActionHashCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_hashCmdUses) + short, _ := client.SelectTranslation(_hashCmdShorts) + + return &cobra.Command{ + Use: use, + Short: short, + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + hash := args[0] + apiServiceClient, err := client.APIServiceClient() + if err != nil { + return err + } + ctx := context.Background() + + jwtMD, err := util.JwtAuth() + if err == nil { + ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx) + } + + // search action on blockchain + requestGetAction := &iotexapi.GetActionsRequest{ + Lookup: &iotexapi.GetActionsRequest_ByHash{ + ByHash: &iotexapi.GetActionByHashRequest{ + ActionHash: hash, + CheckPending: false, + }, + }, + } + response, err := apiServiceClient.GetActions(ctx, requestGetAction) + if err != nil { + sta, ok := status.FromError(err) + if ok { + return errors.New(sta.Message()) + } + return errors.Wrap(err, "failed to invoke GetActions api") + } + if len(response.ActionInfo) == 0 { + return errors.New("no action info returned") + } + message := actionMessage{Proto: response.ActionInfo[0]} + + requestGetReceipt := &iotexapi.GetReceiptByActionRequest{ActionHash: hash} + responseReceipt, err := apiServiceClient.GetReceiptByAction(ctx, requestGetReceipt) + if err != nil { + sta, ok := status.FromError(err) + if ok && sta.Code() == codes.NotFound { + message.State = Pending + } else if ok { + return errors.New(sta.Message()) + } + return errors.Wrap(err, "failed to invoke GetReceiptByAction api") + } + message.State = Executed + message.Receipt = responseReceipt.ReceiptInfo.Receipt + cmd.Println(message.String(client)) + return nil + }, + } +} + +type actionMessage struct { + State actionState `json:"state"` + Proto *iotexapi.ActionInfo `json:"proto"` + Receipt *iotextypes.Receipt `json:"receipt"` +} + +func (m *actionMessage) String(client ioctl.Client) string { + message, err := printAction(client, m.Proto) + if err != nil { + log.Panic(err.Error()) + } + if m.State == Pending { + message += "\n#This action is pending" + } else { + message += "\n#This action has been written on blockchain\n\n" + printReceiptProto(client, m.Receipt) + } + return message +} + +func printAction(client ioctl.Client, actionInfo *iotexapi.ActionInfo) (string, error) { + result, err := printActionProto(client, actionInfo.Action) + if err != nil { + return "", err + } + if actionInfo.Timestamp != nil { + if err := actionInfo.Timestamp.CheckValid(); err != nil { + return "", err + } + ts := actionInfo.Timestamp.AsTime() + result += fmt.Sprintf("timeStamp: %d\n", ts.Unix()) + result += fmt.Sprintf("blkHash: %s\n", actionInfo.BlkHash) + } + result += fmt.Sprintf("actHash: %s\n", actionInfo.ActHash) + return result, nil +} + +func printActionProto(client ioctl.Client, action *iotextypes.Action) (string, error) { + pubKey, err := crypto.BytesToPublicKey(action.SenderPubKey) + if err != nil { + return "", errors.Wrap(err, "failed to convert public key from bytes") + } + senderAddress := pubKey.Address() + if senderAddress == nil { + return "", errors.New("failed to convert bytes into address") + } + //ioctl action should display IOTX unit instead Raul + core := action.Core + gasPriceUnitIOTX, err := util.StringToIOTX(core.GasPrice) + if err != nil { + return "", errors.Wrap(err, "failed to convert string to IOTX") + } + result := fmt.Sprintf("\nversion: %d ", core.GetVersion()) + + fmt.Sprintf("nonce: %d ", core.GetNonce()) + + fmt.Sprintf("gasLimit: %d ", core.GasLimit) + + fmt.Sprintf("gasPrice: %s IOTX ", gasPriceUnitIOTX) + + fmt.Sprintf("chainID: %d ", core.GetChainID()) + + fmt.Sprintf("encoding: %d\n", action.GetEncoding()) + + fmt.Sprintf("senderAddress: %s %s\n", senderAddress.String(), + Match(client, senderAddress.String(), "address")) + switch { + case core.GetTransfer() != nil: + transfer := core.GetTransfer() + amount, err := util.StringToIOTX(transfer.Amount) + if err != nil { + return "", errors.Wrap(err, "failed to convert string into IOTX amount") + } + result += "transfer: <\n" + + fmt.Sprintf(" recipient: %s %s\n", transfer.Recipient, + Match(client, transfer.Recipient, "address")) + + fmt.Sprintf(" amount: %s IOTX\n", amount) + if len(transfer.Payload) != 0 { + result += fmt.Sprintf(" payload: %s\n", transfer.Payload) + } + result += ">\n" + case core.GetExecution() != nil: + execution := core.GetExecution() + result += "execution: <\n" + + fmt.Sprintf(" contract: %s %s\n", execution.Contract, + Match(client, execution.Contract, "address")) + if execution.Amount != "0" { + amount, err := util.StringToIOTX(execution.Amount) + if err != nil { + return "", errors.Wrap(err, "failed to convert string into IOTX amount") + } + result += fmt.Sprintf(" amount: %s IOTX\n", amount) + } + result += fmt.Sprintf(" data: %x\n", execution.Data) + ">\n" + case core.GetPutPollResult() != nil: + putPollResult := core.GetPutPollResult() + result += "putPollResult: <\n" + + fmt.Sprintf(" height: %d\n", putPollResult.Height) + + " candidates: <\n" + for _, candidate := range putPollResult.Candidates.Candidates { + result += " candidate: <\n" + + fmt.Sprintf(" address: %s\n", candidate.Address) + votes := big.NewInt(0).SetBytes(candidate.Votes) + result += fmt.Sprintf(" votes: %s\n", votes.String()) + + fmt.Sprintf(" rewardAdress: %s\n", candidate.RewardAddress) + + " >\n" + } + result += " >\n" + + ">\n" + default: + result += protoV1.MarshalTextString(core) + } + result += fmt.Sprintf("senderPubKey: %x\n", action.SenderPubKey) + + fmt.Sprintf("signature: %x\n", action.Signature) + + return result, nil +} + +func printReceiptProto(client ioctl.Client, receipt *iotextypes.Receipt) string { + result := fmt.Sprintf("status: %d %s\n", receipt.Status, + Match(client, strconv.Itoa(int(receipt.Status)), "status")) + + fmt.Sprintf("actHash: %x\n", receipt.ActHash) + + fmt.Sprintf("blkHeight: %d\n", receipt.BlkHeight) + + fmt.Sprintf("gasConsumed: %d\n", receipt.GasConsumed) + + printLogs(receipt.Logs) + if len(receipt.ContractAddress) != 0 { + result += fmt.Sprintf("\ncontractAddress: %s %s", receipt.ContractAddress, + Match(client, receipt.ContractAddress, "address")) + } + if len(receipt.Logs) > 0 { + if index, ok := staking.BucketIndexFromReceiptLog(receipt.Logs[0]); ok { + result += fmt.Sprintf("\nbucket index: %d", index) + } + } + if receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) { + result += fmt.Sprintf("\nexecution revert reason: %s", receipt.ExecutionRevertMsg) + } + return result +} + +func printLogs(logs []*iotextypes.Log) string { + result := "logs:<\n" + for _, l := range logs { + result += " <\n" + + fmt.Sprintf(" contractAddress: %s\n", l.ContractAddress) + + " topics:<\n" + for _, topic := range l.Topics { + result += fmt.Sprintf(" %s\n", hex.EncodeToString(topic)) + } + result += " >\n" + if len(l.Data) > 0 { + result += fmt.Sprintf(" data: %s\n", hex.EncodeToString(l.Data)) + } + result += " >\n" + + } + result += ">\n" + return result +} + +// Match returns human readable expression +func Match(client ioctl.Client, in string, matchType string) string { + switch matchType { + case "address": + alias, err := client.Alias(in) + if err != nil { + return "" + } + return "(" + alias + ")" + case "status": + switch in { + case "0": + return "(Failure)" + case "1": + return "(Success)" + case "100": + return "(Failure : Unknown)" + case "101": + return "(Failure : Execution out of gas)" + case "102": + return "(Failure : Deployment out of gas - not enough gas to store code)" + case "103": + return "(Failure : Max call depth exceeded)" + case "104": + return "(Failure : Contract address collision)" + case "105": + return "(Failure : No compatible interpreter)" + case "106": + return "(Failure : Execution reverted)" + case "107": + return "(Failure : Max code size exceeded)" + case "108": + return "(Failure : Write protection)" + } + } + return "" +} diff --git a/ioctl/newcmd/action/actionhash_test.go b/ioctl/newcmd/action/actionhash_test.go new file mode 100644 index 0000000000..5965c6b27b --- /dev/null +++ b/ioctl/newcmd/action/actionhash_test.go @@ -0,0 +1,120 @@ +package action + +import ( + "context" + "encoding/hex" + "testing" + + "github.com/golang/mock/gomock" + "github.com/iotexproject/iotex-proto/golang/iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotexapi/mock_iotexapi" + "github.com/iotexproject/iotex-proto/golang/iotextypes" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/action" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/pkg/unit" + "github.com/iotexproject/iotex-core/test/identityset" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +var ( + _signByte = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9} + _pubKeyString = "04403d3c0dbd3270ddfc248c3df1f9aafd60f1d8e7456961c9ef262" + "92262cc68f0ea9690263bef9e197a38f06026814fc70912c2b98d2e90a68f8ddc5328180a01" +) + +func TestNewActionHashCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl) + + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(6) + client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(2) + client.EXPECT().Alias(gomock.Any()).Return("producer", nil).Times(3) + + _pubKeyByte, err := hex.DecodeString(_pubKeyString) + require.NoError(err) + + t.Run("get action receipt", func(t *testing.T) { + getActionResponse := &iotexapi.GetActionsResponse{ + ActionInfo: []*iotexapi.ActionInfo{ + { + Index: 0, + ActHash: "test", + Action: &iotextypes.Action{ + SenderPubKey: _pubKeyByte, + Signature: _signByte, + Core: createEnvelope(0).Proto(), + }, + }, + }, + } + getReceiptResponse := &iotexapi.GetReceiptByActionResponse{ + ReceiptInfo: &iotexapi.ReceiptInfo{ + Receipt: &iotextypes.Receipt{ + Status: 1, + BlkHeight: 12, + ActHash: []byte("9b1d77d8b8902e8d4e662e7cd07d8a74179e032f030d92441ca7fba1ca68e0f4"), + GasConsumed: 123, + ContractAddress: "test", + TxIndex: 1, + ExecutionRevertMsg: "balance not enough", + }, + }, + } + apiServiceClient.EXPECT().GetActions(context.Background(), gomock.Any()).Return(getActionResponse, nil) + apiServiceClient.EXPECT().GetReceiptByAction(context.Background(), gomock.Any()).Return(getReceiptResponse, nil) + + cmd := NewActionHashCmd(client) + result, err := util.ExecuteCmd(cmd, "test") + require.NoError(err) + require.Contains(result, "status: 1 (Success)\n") + require.Contains(result, "blkHeight: 12\n") + require.Contains(result, "gasConsumed: 123\n") + require.Contains(result, "senderPubKey: "+_pubKeyString+"\n") + require.Contains(result, "signature: 010203040506070809\n") + }) + + t.Run("no action info returned", func(t *testing.T) { + getActionResponse := &iotexapi.GetActionsResponse{ + ActionInfo: []*iotexapi.ActionInfo{}, + } + expectedErr := errors.New("no action info returned") + apiServiceClient.EXPECT().GetActions(context.Background(), gomock.Any()).Return(getActionResponse, nil) + + cmd := NewActionHashCmd(client) + _, err := util.ExecuteCmd(cmd, "test") + require.Equal(expectedErr.Error(), err.Error()) + }) + + t.Run("failed to dial grpc connection", func(t *testing.T) { + expectedErr := errors.New("failed to dial grpc connection") + client.EXPECT().APIServiceClient().Return(nil, expectedErr).Times(1) + + cmd := NewActionHashCmd(client) + _, err := util.ExecuteCmd(cmd, "test") + require.Equal(expectedErr, err) + }) +} + +func createEnvelope(chainID uint32) action.Envelope { + tsf, _ := action.NewTransfer( + uint64(10), + unit.ConvertIotxToRau(1000+int64(10)), + identityset.Address(10%identityset.Size()).String(), + nil, + 20000+uint64(10), + unit.ConvertIotxToRau(1+int64(10)), + ) + eb := action.EnvelopeBuilder{} + return eb. + SetAction(tsf). + SetGasLimit(tsf.GasLimit()). + SetGasPrice(tsf.GasPrice()). + SetNonce(tsf.Nonce()). + SetVersion(1). + SetChainID(chainID).Build() +} diff --git a/test/mock/mock_ioctlclient/mock_ioctlclient.go b/test/mock/mock_ioctlclient/mock_ioctlclient.go index 90ca0efe67..03eecf0d98 100644 --- a/test/mock/mock_ioctlclient/mock_ioctlclient.go +++ b/test/mock/mock_ioctlclient/mock_ioctlclient.go @@ -84,6 +84,21 @@ func (mr *MockClientMockRecorder) AddressWithDefaultIfNotExist(in interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressWithDefaultIfNotExist", reflect.TypeOf((*MockClient)(nil).AddressWithDefaultIfNotExist), in) } +// Alias mocks base method. +func (m *MockClient) Alias(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Alias", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Alias indicates an expected call of Alias. +func (mr *MockClientMockRecorder) Alias(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Alias", reflect.TypeOf((*MockClient)(nil).Alias), arg0) +} + // AliasMap mocks base method. func (m *MockClient) AliasMap() map[string]string { m.ctrl.T.Helper() From 40667e512927da029dcb9b610ad1048780f9f96a Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Mon, 27 Jun 2022 13:42:26 +0800 Subject: [PATCH 15/24] [api] Move generateBlockMeta to grpcserver.go (#3303) --- api/coreservice.go | 44 ++++---------------------------------------- api/grpcserver.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 783d8a27c1..815ec411d4 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -1039,7 +1039,10 @@ func (core *coreService) BlockByHash(blkHash string) (*block.Store, error) { if err != nil { return nil, errors.Wrap(ErrNotFound, err.Error()) } - return &block.Store{blk, receipts}, nil + return &block.Store{ + Block: blk, + Receipts: receipts, + }, nil } // BlockMetas returns blockmetas response within the height range @@ -1101,45 +1104,6 @@ func (core *coreService) getBlockMetaByHeight(height uint64) (*iotextypes.BlockM return generateBlockMeta(blk), nil } -// generateBlockMeta generates BlockMeta from block -func generateBlockMeta(blk *block.Block) *iotextypes.BlockMeta { - header := blk.Header - height := header.Height() - ts := timestamppb.New(header.Timestamp()) - var ( - producerAddress string - h hash.Hash256 - ) - if blk.Height() > 0 { - producerAddress = header.ProducerAddress() - h = header.HashBlock() - } else { - h = block.GenesisHash() - } - txRoot := header.TxRoot() - receiptRoot := header.ReceiptRoot() - deltaStateDigest := header.DeltaStateDigest() - prevHash := header.PrevHash() - - blockMeta := iotextypes.BlockMeta{ - Hash: hex.EncodeToString(h[:]), - Height: height, - Timestamp: ts, - ProducerAddress: producerAddress, - TxRoot: hex.EncodeToString(txRoot[:]), - ReceiptRoot: hex.EncodeToString(receiptRoot[:]), - DeltaStateDigest: hex.EncodeToString(deltaStateDigest[:]), - PreviousBlockHash: hex.EncodeToString(prevHash[:]), - } - if logsBloom := header.LogsBloomfilter(); logsBloom != nil { - blockMeta.LogsBloom = hex.EncodeToString(logsBloom.Bytes()) - } - blockMeta.NumActions = int64(len(blk.Actions)) - blockMeta.TransferAmount = blk.CalculateTransferAmount().String() - blockMeta.GasLimit, blockMeta.GasUsed = gasLimitAndUsed(blk) - return &blockMeta -} - // GasLimitAndUsed returns the gas limit and used in a block func gasLimitAndUsed(b *block.Block) (uint64, uint64) { var gasLimit, gasUsed uint64 diff --git a/api/grpcserver.go b/api/grpcserver.go index 2c30ead8e0..d289692a89 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -37,6 +37,7 @@ import ( "google.golang.org/grpc/peer" "google.golang.org/grpc/reflection" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/action/protocol" @@ -721,3 +722,42 @@ func (svr *GRPCServer) TraceTransactionStructLogs(ctx context.Context, in *iotex StructLogs: structLogs, }, nil } + +// generateBlockMeta generates BlockMeta from block +func generateBlockMeta(blk *block.Block) *iotextypes.BlockMeta { + header := blk.Header + height := header.Height() + ts := timestamppb.New(header.Timestamp()) + var ( + producerAddress string + h hash.Hash256 + ) + if blk.Height() > 0 { + producerAddress = header.ProducerAddress() + h = header.HashBlock() + } else { + h = block.GenesisHash() + } + txRoot := header.TxRoot() + receiptRoot := header.ReceiptRoot() + deltaStateDigest := header.DeltaStateDigest() + prevHash := header.PrevHash() + + blockMeta := iotextypes.BlockMeta{ + Hash: hex.EncodeToString(h[:]), + Height: height, + Timestamp: ts, + ProducerAddress: producerAddress, + TxRoot: hex.EncodeToString(txRoot[:]), + ReceiptRoot: hex.EncodeToString(receiptRoot[:]), + DeltaStateDigest: hex.EncodeToString(deltaStateDigest[:]), + PreviousBlockHash: hex.EncodeToString(prevHash[:]), + } + if logsBloom := header.LogsBloomfilter(); logsBloom != nil { + blockMeta.LogsBloom = hex.EncodeToString(logsBloom.Bytes()) + } + blockMeta.NumActions = int64(len(blk.Actions)) + blockMeta.TransferAmount = blk.CalculateTransferAmount().String() + blockMeta.GasLimit, blockMeta.GasUsed = gasLimitAndUsed(blk) + return &blockMeta +} From 5a9bfa0dea6f63ae43d534a6d50523ada64a19db Mon Sep 17 00:00:00 2001 From: huofei <68298506@qq.com> Date: Tue, 28 Jun 2022 00:21:28 +0800 Subject: [PATCH 16/24] [api] add crashlog (#3456) * add crashlog * use SystemLogDBPath for log file * remove from websocket * use grpc_recovery in grpcServer * use fixed dir * add SetCrashlogDir() * add comment * use _crashlogDir --- api/grpcserver.go | 13 ++++++++++++ config/config.go | 4 ++-- pkg/recovery/recovery.go | 38 +++++++++++++++++++++++++++-------- pkg/recovery/recovery_test.go | 22 ++++---------------- server/main.go | 9 ++++----- 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/api/grpcserver.go b/api/grpcserver.go index d289692a89..c35103bd0e 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/go-pkgs/util" @@ -44,6 +45,7 @@ import ( "github.com/iotexproject/iotex-core/api/logfilter" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/pkg/log" + "github.com/iotexproject/iotex-core/pkg/recovery" "github.com/iotexproject/iotex-core/pkg/tracer" ) @@ -86,6 +88,14 @@ func init() { prometheus.MustRegister(_apiCallSourceWithOutChainIDMtc) } +// RecoveryInterceptor handles panic to a custom error +func RecoveryInterceptor() grpc_recovery.Option { + return grpc_recovery.WithRecoveryHandler(func(p interface{}) (err error) { + recovery.LogCrash(p) + return grpc.Errorf(codes.Unknown, "grpc triggered crash: %v", p) + }) +} + // NewGRPCServer creates a new grpc server func NewGRPCServer(core CoreService, grpcPort int) *GRPCServer { if grpcPort == 0 { @@ -96,10 +106,12 @@ func NewGRPCServer(core CoreService, grpcPort int) *GRPCServer { grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( grpc_prometheus.StreamServerInterceptor, otelgrpc.StreamServerInterceptor(), + grpc_recovery.StreamServerInterceptor(RecoveryInterceptor()), )), grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( grpc_prometheus.UnaryServerInterceptor, otelgrpc.UnaryServerInterceptor(), + grpc_recovery.UnaryServerInterceptor(RecoveryInterceptor()), )), grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp), @@ -127,6 +139,7 @@ func (svr *GRPCServer) Start(_ context.Context) error { } log.L().Info("grpc server is listening.", zap.String("addr", lis.Addr().String())) go func() { + defer recovery.Recover() if err := svr.grpcServer.Serve(lis); err != nil { log.L().Fatal("grpc failed to serve.", zap.Error(err)) } diff --git a/config/config.go b/config/config.go index 270db27b5c..12eb0a2894 100644 --- a/config/config.go +++ b/config/config.go @@ -16,12 +16,12 @@ import ( "time" "github.com/iotexproject/go-pkgs/crypto" + "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-election/committee" "github.com/pkg/errors" uconfig "go.uber.org/config" "go.uber.org/zap" - "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/dispatcher" @@ -170,7 +170,7 @@ var ( HTTPStatsPort: 8080, HTTPAdminPort: 9009, StartSubChainInterval: 10 * time.Second, - SystemLogDBPath: "/var/data/systemlog.db", + SystemLogDBPath: "/var/log", }, DB: db.Config{ NumRetries: 3, diff --git a/pkg/recovery/recovery.go b/pkg/recovery/recovery.go index 262ff4ebf4..a2612817d3 100644 --- a/pkg/recovery/recovery.go +++ b/pkg/recovery/recovery.go @@ -19,6 +19,7 @@ import ( "github.com/shirou/gopsutil/v3/mem" "github.com/iotexproject/iotex-core/pkg/log" + "github.com/iotexproject/iotex-core/pkg/util/fileutil" ) type ( @@ -44,13 +45,33 @@ type ( } ) -// CrashLog write down the current memory and stack info and the cpu/mem/disk infos into log dir -func CrashLog(r interface{}, cfgLog log.GlobalConfig) { - log.S().Errorf("crashlog: %v", r) - if cfgLog.StderrRedirectFile != nil { - writeHeapProfile(filepath.Join(filepath.Dir(*cfgLog.StderrRedirectFile), - "heapdump_"+time.Now().Format("20060102150405")+".out")) +// _crashlogDir saves the directory of crashlog +var _crashlogDir string = "/" + +// Recover catchs the crashing goroutine +func Recover() { + if r := recover(); r != nil { + LogCrash(r) + } +} + +// SetCrashlogDir set the directory of crashlog +func SetCrashlogDir(dir string) error { + if !fileutil.FileExists(dir) { + if err := os.MkdirAll(dir, 0744); err != nil { + log.S().Error(err.Error()) + return err + } } + _crashlogDir = dir + return nil +} + +// LogCrash write down the current memory and stack info and the cpu/mem/disk infos into log dir +func LogCrash(r interface{}) { + log.S().Errorf("crashlog: %v", r) + writeHeapProfile(filepath.Join(_crashlogDir, + "heapdump_"+time.Now().String()+".out")) log.S().Infow("crashlog", "stack", string(debug.Stack())) printInfo("cpu", cpuInfo) printInfo("memory", memInfo) @@ -60,11 +81,12 @@ func CrashLog(r interface{}, cfgLog log.GlobalConfig) { func writeHeapProfile(path string) { f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644) if err != nil { - log.S().Fatalf("crashlog: open heap profile error: %v", err) + log.S().Errorf("crashlog: open heap profile error: %v", err) + return } defer f.Close() if err := pprof.WriteHeapProfile(f); err != nil { - log.S().Fatalf("crashlog: write heap profile error: %v", err) + log.S().Errorf("crashlog: write heap profile error: %v", err) } } diff --git a/pkg/recovery/recovery_test.go b/pkg/recovery/recovery_test.go index c2e7c86ede..9351bd0dec 100644 --- a/pkg/recovery/recovery_test.go +++ b/pkg/recovery/recovery_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/iotexproject/iotex-core/pkg/log" "github.com/iotexproject/iotex-core/testutil" ) @@ -16,35 +15,22 @@ func TestCrashLog(t *testing.T) { heapdumpDir, err := os.MkdirTemp(os.TempDir(), "heapdump") require.NoError(err) defer testutil.CleanupPath(heapdumpDir) - var logCfg log.GlobalConfig - logCfg.StderrRedirectFile = &heapdumpDir + require.NoError(SetCrashlogDir(heapdumpDir)) t.Run("index out of range", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - CrashLog(r, logCfg) - } - }() + defer Recover() strs := make([]string, 2) strs[0] = "a" strs[1] = "b" strs[2] = "c" }) t.Run("invaled memory address or nil pointer", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - CrashLog(r, logCfg) - } - }() + defer Recover() var i *int *i = 1 }) t.Run("divide by zero", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - CrashLog(r, logCfg) - } - }() + defer Recover() a, b := 10, 0 a = a / b }) diff --git a/server/main.go b/server/main.go index 9ccbf81fb4..8847cc6966 100644 --- a/server/main.go +++ b/server/main.go @@ -103,11 +103,10 @@ func main() { glog.Fatalln("Cannot config global logger, use default one: ", zap.Error(err)) } - defer func() { - if r := recover(); r != nil { - recovery.CrashLog(r, cfg.Log) - } - }() + if err = recovery.SetCrashlogDir(cfg.System.SystemLogDBPath); err != nil { + glog.Fatalln("Failed to set directory of crashlog: ", zap.Error(err)) + } + defer recovery.Recover() // populdate chain ID config.SetEVMNetworkID(cfg.Chain.EVMNetworkID) From 388be8c76aecbb59d8e901610d4d431401e87710 Mon Sep 17 00:00:00 2001 From: dustinxie Date: Mon, 27 Jun 2022 10:27:32 -0700 Subject: [PATCH 17/24] [filedao] remove checkMasterChainDBFile() (#3463) --- blockchain/filedao/filedao.go | 14 ++++++++------ blockchain/filedao/filedao_test.go | 2 +- blockchain/filedao/filedao_util.go | 17 ----------------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/blockchain/filedao/filedao.go b/blockchain/filedao/filedao.go index 8a5caa0b0f..3d35250e52 100644 --- a/blockchain/filedao/filedao.go +++ b/blockchain/filedao/filedao.go @@ -84,12 +84,11 @@ type ( // NewFileDAO creates an instance of FileDAO func NewFileDAO(cfg db.Config) (FileDAO, error) { - header, err := checkMasterChainDBFile(cfg.DbPath) - if err == ErrFileInvalid || err == ErrFileCantAccess { - return nil, err - } - - if err == ErrFileNotExist { + header, err := readFileHeader(cfg.DbPath, FileAll) + if err != nil { + if err != ErrFileNotExist { + return nil, err + } // start new chain db using v2 format if err := createNewV2File(1, cfg); err != nil { return nil, err @@ -98,6 +97,9 @@ func NewFileDAO(cfg db.Config) (FileDAO, error) { } switch header.Version { + case FileLegacyAuxiliary: + // default chain db file is legacy format, but not master, the master file has been corrupted + return nil, ErrFileInvalid case FileLegacyMaster: // master file is legacy format return CreateFileDAO(true, cfg) diff --git a/blockchain/filedao/filedao_test.go b/blockchain/filedao/filedao_test.go index 840df82483..b286284b3d 100644 --- a/blockchain/filedao/filedao_test.go +++ b/blockchain/filedao/filedao_test.go @@ -140,7 +140,7 @@ func TestNewFileDAOSplitV2(t *testing.T) { defer os.RemoveAll(cfg.DbPath) // test non-existing file - _, err := checkMasterChainDBFile(cfg.DbPath) + _, err := readFileHeader(cfg.DbPath, FileAll) r.Equal(ErrFileNotExist, err) // test empty db file, this will create new v2 file diff --git a/blockchain/filedao/filedao_util.go b/blockchain/filedao/filedao_util.go index fd20c67ca5..6ff7388cc8 100644 --- a/blockchain/filedao/filedao_util.go +++ b/blockchain/filedao/filedao_util.go @@ -20,23 +20,6 @@ import ( "github.com/iotexproject/iotex-core/db" ) -func checkMasterChainDBFile(defaultName string) (*FileHeader, error) { - h, err := readFileHeader(defaultName, FileAll) - if err == ErrFileNotExist || err == ErrFileInvalid || err == ErrFileCantAccess { - return nil, err - } - - switch h.Version { - case FileLegacyAuxiliary: - // default chain db file is legacy format, but not master, the master file has been corrupted - return h, ErrFileInvalid - case FileLegacyMaster, FileV2: - return h, nil - default: - panic(fmt.Errorf("corrupted file version: %s", h.Version)) - } -} - func readFileHeader(filename, fileType string) (*FileHeader, error) { if err := fileExists(filename); err != nil { return nil, err From b015a15ec6f9d47393a8329bb2caec70de69a555 Mon Sep 17 00:00:00 2001 From: millken Date: Tue, 28 Jun 2022 16:57:29 +0800 Subject: [PATCH 18/24] remove config.EVMNetworkID() (#3460) --- blockchain/block/block_deserializer.go | 37 ++++++++++++++++++ blockchain/block/block_deserializer_test.go | 18 +++++++++ blockchain/block/blockstore.go | 32 --------------- blockchain/block/blockstore_test.go | 16 -------- blockchain/blockdao/blockdao.go | 4 +- blockchain/blockdao/blockdao_test.go | 9 +++-- blockchain/filedao/filedao.go | 39 ++++++++++--------- blockchain/filedao/filedao_legacy.go | 8 ++-- blockchain/filedao/filedao_legacy_test.go | 9 +++-- blockchain/filedao/filedao_test.go | 22 +++++++---- blockchain/filedao/filedao_v2.go | 7 +++- blockchain/filedao/filedao_v2_test.go | 17 ++++---- blockchain/filedao/filedao_v2_util.go | 18 +++------ blockchain/filedao/staging_buffer.go | 8 ++-- blockchain/filedao/testing.go | 1 + blockchain/integrity/benchmark_test.go | 3 +- blockchain/integrity/integrity_test.go | 18 ++++++--- blockindex/indexbuilder_test.go | 5 ++- chainservice/builder.go | 3 +- chainservice/chainservice.go | 2 +- consensus/scheme/rolldpos/blockproposal.go | 2 +- .../scheme/rolldpos/endorsementmanager.go | 4 +- .../scheme/rolldpos/roundcalculator_test.go | 3 +- e2etest/local_test.go | 8 ++-- pkg/util/httputil/httputil_test.go | 7 +++- tools/iomigrater/cmds/check-height.go | 4 +- tools/iomigrater/cmds/migrate-db.go | 6 ++- 27 files changed, 175 insertions(+), 135 deletions(-) diff --git a/blockchain/block/block_deserializer.go b/blockchain/block/block_deserializer.go index 424e59624a..0712a02712 100644 --- a/blockchain/block/block_deserializer.go +++ b/blockchain/block/block_deserializer.go @@ -26,6 +26,13 @@ type Deserializer struct { evmNetworkID uint32 } +// NewDeserializer creates a new deserializer +func NewDeserializer(evmNetworkID uint32) *Deserializer { + return &Deserializer{ + evmNetworkID: evmNetworkID, + } +} + // SetEvmNetworkID sets the evm network ID for web3 actions func (bd *Deserializer) SetEvmNetworkID(id uint32) *Deserializer { bd.evmNetworkID = id @@ -92,3 +99,33 @@ func (bd *Deserializer) DeserializeBody(buf []byte) (*Body, error) { } return &b, nil } + +// FromBlockStoreProto converts protobuf to block store +func (bd *Deserializer) FromBlockStoreProto(pb *iotextypes.BlockStore) (*Store, error) { + in := &Store{} + blk, err := bd.FromBlockProto(pb.Block) + if err != nil { + return nil, err + } + // verify merkle root can match after deserialize + if err := blk.VerifyTxRoot(); err != nil { + return nil, err + } + + in.Block = blk + for _, receiptPb := range pb.Receipts { + receipt := &action.Receipt{} + receipt.ConvertFromReceiptPb(receiptPb) + in.Receipts = append(in.Receipts, receipt) + } + return in, nil +} + +// DeserializeBlockStore de-serializes a block store +func (bd *Deserializer) DeserializeBlockStore(buf []byte) (*Store, error) { + pb := iotextypes.BlockStore{} + if err := proto.Unmarshal(buf, &pb); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal block store") + } + return bd.FromBlockStoreProto(&pb) +} diff --git a/blockchain/block/block_deserializer_test.go b/blockchain/block/block_deserializer_test.go index 6f3788ed45..8ca4545dd6 100644 --- a/blockchain/block/block_deserializer_test.go +++ b/blockchain/block/block_deserializer_test.go @@ -35,3 +35,21 @@ func TestBlockDeserializer(t *testing.T) { r.Equal(_pbBlock.Body.Actions[0].Core.ChainID, blk.Actions[0].ChainID()) r.Equal(_pbBlock.Body.Actions[1].Core.ChainID, blk.Actions[1].ChainID()) } + +func TestBlockStoreDeserializer(t *testing.T) { + require := require.New(t) + store, err := makeStore() + require.NoError(err) + + storeProto := store.ToProto() + + require.NotNil(storeProto) + + bd := Deserializer{} + store1, err := bd.FromBlockStoreProto(storeProto) + require.NoError(err) + + require.Equal(store1.Block.height, store.Block.height) + require.Equal(store1.Block.Header.prevBlockHash, store.Block.Header.prevBlockHash) + require.Equal(store1.Block.Header.blockSig, store.Block.Header.blockSig) +} diff --git a/blockchain/block/blockstore.go b/blockchain/block/blockstore.go index ae6b87b52c..50dd58abac 100644 --- a/blockchain/block/blockstore.go +++ b/blockchain/block/blockstore.go @@ -12,7 +12,6 @@ import ( "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/iotexproject/iotex-core/action" - "github.com/iotexproject/iotex-core/config" ) type ( @@ -40,37 +39,6 @@ func (in *Store) ToProto() *iotextypes.BlockStore { } } -// FromProto converts from proto message -func (in *Store) FromProto(pb *iotextypes.BlockStore) error { - // TODO: pass the correct EVM network ID at the time of newFileDAOv2() - blk, err := (&Deserializer{}).SetEvmNetworkID(config.EVMNetworkID()).FromBlockProto(pb.Block) - if err != nil { - return err - } - // verify merkle root can match after deserialize - if err := blk.VerifyTxRoot(); err != nil { - return err - } - - in.Block = blk - in.Receipts = []*action.Receipt{} - for _, receiptPb := range pb.Receipts { - receipt := &action.Receipt{} - receipt.ConvertFromReceiptPb(receiptPb) - in.Receipts = append(in.Receipts, receipt) - } - return nil -} - -// Deserialize parses the byte stream into Store -func (in *Store) Deserialize(buf []byte) error { - pbStore := &iotextypes.BlockStore{} - if err := proto.Unmarshal(buf, pbStore); err != nil { - return err - } - return in.FromProto(pbStore) -} - // DeserializeBlockStoresPb decode byte stream into BlockStores pb message func DeserializeBlockStoresPb(buf []byte) (*iotextypes.BlockStores, error) { pbStores := &iotextypes.BlockStores{} diff --git a/blockchain/block/blockstore_test.go b/blockchain/block/blockstore_test.go index 9a4a2819d9..09567e8aa8 100644 --- a/blockchain/block/blockstore_test.go +++ b/blockchain/block/blockstore_test.go @@ -28,22 +28,6 @@ func TestStoreProto(t *testing.T) { require.NotNil(storeProto) require.Equal(0, len(storeProto.Receipts)) - require.NoError(store.FromProto(storeProto)) -} - -func TestSerialize(t *testing.T) { - require := require.New(t) - store, err := makeStore() - require.NoError(err) - - ser, err := store.Serialize() - require.NoError(err) - - store1 := &Store{} - require.NoError(store1.Deserialize(ser)) - require.Equal(store1.Block.height, store.Block.height) - require.Equal(store1.Block.Header.prevBlockHash, store.Block.Header.prevBlockHash) - require.Equal(store1.Block.Header.blockSig, store.Block.Header.blockSig) } func makeStore() (*Store, error) { diff --git a/blockchain/blockdao/blockdao.go b/blockchain/blockdao/blockdao.go index 50d93c1eaf..0e1995bd3a 100644 --- a/blockchain/blockdao/blockdao.go +++ b/blockchain/blockdao/blockdao.go @@ -60,8 +60,8 @@ type ( ) // NewBlockDAO instantiates a block DAO -func NewBlockDAO(indexers []BlockIndexer, cfg db.Config) BlockDAO { - blkStore, err := filedao.NewFileDAO(cfg) +func NewBlockDAO(indexers []BlockIndexer, cfg db.Config, deser *block.Deserializer) BlockDAO { + blkStore, err := filedao.NewFileDAO(cfg, deser) if err != nil { log.L().Fatal(err.Error(), zap.Any("cfg", cfg)) return nil diff --git a/blockchain/blockdao/blockdao_test.go b/blockchain/blockdao/blockdao_test.go index 42d6caecb9..3652266a28 100644 --- a/blockchain/blockdao/blockdao_test.go +++ b/blockchain/blockdao/blockdao_test.go @@ -441,9 +441,9 @@ func createTestBlockDAO(inMemory, legacy bool, compressBlock string, cfg db.Conf if inMemory { return NewBlockDAOInMemForTest(nil), nil } - + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) if legacy { - fileDAO, err := filedao.CreateFileDAO(true, cfg) + fileDAO, err := filedao.CreateFileDAO(true, cfg, deser) if err != nil { return nil, err } @@ -451,7 +451,7 @@ func createTestBlockDAO(inMemory, legacy bool, compressBlock string, cfg db.Conf } cfg.Compressor = compressBlock - return NewBlockDAO(nil, cfg), nil + return NewBlockDAO(nil, cfg, deser), nil } func BenchmarkBlockCache(b *testing.B) { @@ -472,7 +472,8 @@ func BenchmarkBlockCache(b *testing.B) { cfg.DbPath = indexPath cfg.DbPath = testPath cfg.MaxCacheSize = cacheSize - blkDao := NewBlockDAO([]BlockIndexer{}, cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + blkDao := NewBlockDAO([]BlockIndexer{}, cfg, deser) require.NoError(b, blkDao.Start(context.Background())) defer func() { require.NoError(b, blkDao.Stop(context.Background())) diff --git a/blockchain/filedao/filedao.go b/blockchain/filedao/filedao.go index 3d35250e52..e7d604f364 100644 --- a/blockchain/filedao/filedao.go +++ b/blockchain/filedao/filedao.go @@ -72,25 +72,26 @@ type ( // fileDAO implements FileDAO fileDAO struct { - lock sync.Mutex - topIndex uint64 - splitHeight uint64 - cfg db.Config - currFd BaseFileDAO - legacyFd FileDAO - v2Fd *FileV2Manager // a collection of v2 db files + lock sync.Mutex + topIndex uint64 + splitHeight uint64 + cfg db.Config + currFd BaseFileDAO + legacyFd FileDAO + v2Fd *FileV2Manager // a collection of v2 db files + blockDeserializer *block.Deserializer } ) // NewFileDAO creates an instance of FileDAO -func NewFileDAO(cfg db.Config) (FileDAO, error) { +func NewFileDAO(cfg db.Config, deser *block.Deserializer) (FileDAO, error) { header, err := readFileHeader(cfg.DbPath, FileAll) if err != nil { if err != ErrFileNotExist { return nil, err } // start new chain db using v2 format - if err := createNewV2File(1, cfg); err != nil { + if err := createNewV2File(1, cfg, deser); err != nil { return nil, err } header = &FileHeader{Version: FileV2} @@ -102,10 +103,10 @@ func NewFileDAO(cfg db.Config) (FileDAO, error) { return nil, ErrFileInvalid case FileLegacyMaster: // master file is legacy format - return CreateFileDAO(true, cfg) + return CreateFileDAO(true, cfg, deser) case FileV2: // master file is v2 format - return CreateFileDAO(false, cfg) + return CreateFileDAO(false, cfg, deser) default: panic(fmt.Errorf("corrupted file version: %s", header.Version)) } @@ -333,7 +334,7 @@ func (fd *fileDAO) addNewV2File(height uint64) error { // create a new v2 file cfg := fd.cfg cfg.DbPath = kthAuxFileName(cfg.DbPath, fd.topIndex+1) - v2, err := newFileDAOv2(height, cfg) + v2, err := newFileDAOv2(height, cfg, fd.blockDeserializer) if err != nil { return err } @@ -367,12 +368,12 @@ func (fd *fileDAO) DeleteTipBlock() error { } // CreateFileDAO creates FileDAO according to master file -func CreateFileDAO(legacy bool, cfg db.Config) (FileDAO, error) { - fd := fileDAO{splitHeight: 1, cfg: cfg} +func CreateFileDAO(legacy bool, cfg db.Config, deser *block.Deserializer) (FileDAO, error) { + fd := fileDAO{splitHeight: 1, cfg: cfg, blockDeserializer: deser} fds := []*fileDAOv2{} v2Top, v2Files := checkAuxFiles(cfg.DbPath, FileV2) if legacy { - legacyFd, err := newFileDAOLegacy(cfg) + legacyFd, err := newFileDAOLegacy(cfg, deser) if err != nil { return nil, err } @@ -385,14 +386,14 @@ func CreateFileDAO(legacy bool, cfg db.Config) (FileDAO, error) { } } else { // v2 master file - fds = append(fds, openFileDAOv2(cfg)) + fds = append(fds, openFileDAOv2(cfg, deser)) } // populate v2 files into v2 manager if len(v2Files) > 0 { for _, name := range v2Files { cfg.DbPath = name - fds = append(fds, openFileDAOv2(cfg)) + fds = append(fds, openFileDAOv2(cfg, deser)) } // v2 file's top index overrides v1's top @@ -407,8 +408,8 @@ func CreateFileDAO(legacy bool, cfg db.Config) (FileDAO, error) { } // createNewV2File creates a new v2 chain db file -func createNewV2File(start uint64, cfg db.Config) error { - v2, err := newFileDAOv2(start, cfg) +func createNewV2File(start uint64, cfg db.Config, deser *block.Deserializer) error { + v2, err := newFileDAOv2(start, cfg, deser) if err != nil { return err } diff --git a/blockchain/filedao/filedao_legacy.go b/blockchain/filedao/filedao_legacy.go index 68363459f3..1279157af8 100644 --- a/blockchain/filedao/filedao_legacy.go +++ b/blockchain/filedao/filedao_legacy.go @@ -21,7 +21,6 @@ import ( "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/blockchain/block" - "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/db/batch" "github.com/iotexproject/iotex-core/pkg/compress" @@ -57,16 +56,18 @@ type ( htf db.RangeIndex kvStore db.KVStore kvStores *cache.ThreadSafeLruCache //store like map[index]db.KVStore,index from 1...N + deser *block.Deserializer } ) // newFileDAOLegacy creates a new legacy file -func newFileDAOLegacy(cfg db.Config) (FileDAO, error) { +func newFileDAOLegacy(cfg db.Config, deser *block.Deserializer) (FileDAO, error) { return &fileDAOLegacy{ compressBlock: cfg.CompressLegacy, cfg: cfg, kvStore: db.NewBoltDB(cfg), kvStores: cache.NewThreadSafeLruCache(0), + deser: deser, }, nil } @@ -263,8 +264,7 @@ func (fd *fileDAOLegacy) body(h hash.Hash256) (*block.Body, error) { // block body could be empty return &block.Body{}, nil } - // TODO: pass the correct EVM network ID at the time of newFileDAOLegacy() - return (&block.Deserializer{}).SetEvmNetworkID(config.EVMNetworkID()).DeserializeBody(value) + return fd.deser.DeserializeBody(value) } func (fd *fileDAOLegacy) footer(h hash.Hash256) (*block.Footer, error) { diff --git a/blockchain/filedao/filedao_legacy_test.go b/blockchain/filedao/filedao_legacy_test.go index cd4758328d..75e6ed5d08 100644 --- a/blockchain/filedao/filedao_legacy_test.go +++ b/blockchain/filedao/filedao_legacy_test.go @@ -31,7 +31,8 @@ func TestFileDAOLegacy_PutBlock(t *testing.T) { r := require.New(t) testutil.CleanupPath(cfg.DbPath) - fdLegacy, err := newFileDAOLegacy(cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fdLegacy, err := newFileDAOLegacy(cfg, deser) r.NoError(err) fd, ok := fdLegacy.(*fileDAOLegacy) r.True(ok) @@ -95,7 +96,8 @@ func TestFileDAOLegacy_DeleteTipBlock(t *testing.T) { cfg.DbPath = "./filedao_legacy.db" cfg.CompressLegacy = true // enable compress - fd, err := newFileDAOLegacy(cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fd, err := newFileDAOLegacy(cfg, deser) r.NoError(err) legacy := fd.(*fileDAOLegacy) @@ -131,7 +133,8 @@ func TestFileDAOLegacy_getBlockValue(t *testing.T) { cfg := db.DefaultConfig cfg.DbPath = "./filedao_legacy.db" - fd, err := newFileDAOLegacy(cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fd, err := newFileDAOLegacy(cfg, deser) r.NoError(err) legacy := fd.(*fileDAOLegacy) diff --git a/blockchain/filedao/filedao_test.go b/blockchain/filedao/filedao_test.go index b286284b3d..aa9c717548 100644 --- a/blockchain/filedao/filedao_test.go +++ b/blockchain/filedao/filedao_test.go @@ -17,6 +17,7 @@ import ( "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/pkg/compress" ) @@ -69,7 +70,8 @@ func TestReadFileHeader(t *testing.T) { r.Equal(ErrFileNotExist, err) // empty legacy file is invalid - legacy, err := newFileDAOLegacy(cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + legacy, err := newFileDAOLegacy(cfg, deser) r.NoError(err) ctx := context.Background() r.NoError(legacy.Start(ctx)) @@ -109,9 +111,8 @@ func TestReadFileHeader(t *testing.T) { } } os.RemoveAll(cfg.DbPath) - // test valid v2 master file - r.NoError(createNewV2File(1, cfg)) + r.NoError(createNewV2File(1, cfg, deser)) defer os.RemoveAll(cfg.DbPath) test2 := []testCheckFile{ @@ -144,7 +145,8 @@ func TestNewFileDAOSplitV2(t *testing.T) { r.Equal(ErrFileNotExist, err) // test empty db file, this will create new v2 file - fd, err := NewFileDAO(cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fd, err := NewFileDAO(cfg, deser) r.NoError(err) r.NotNil(fd) h, err := readFileHeader(cfg.DbPath, FileAll) @@ -195,7 +197,9 @@ func TestNewFileDAOSplitLegacy(t *testing.T) { cfg.SplitDBHeight = 5 cfg.SplitDBSizeMB = 20 - fd, err := newFileDAOLegacy(cfg) + + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fd, err := newFileDAOLegacy(cfg, deser) r.NoError(err) ctx := context.Background() r.NoError(fd.Start(ctx)) @@ -208,7 +212,8 @@ func TestNewFileDAOSplitLegacy(t *testing.T) { // set FileDAO to split at height 15, 30 and 40 cfg.V2BlocksToSplitDB = 15 - fd, err = NewFileDAO(cfg) + + fd, err = NewFileDAO(cfg, deser) r.NoError(err) r.NoError(fd.Start(ctx)) fm := fd.(*fileDAO) @@ -264,7 +269,7 @@ func TestNewFileDAOSplitLegacy(t *testing.T) { r.Equal(files[2], file4) // open 4 db files and verify again - fd, err = NewFileDAO(cfg) + fd, err = NewFileDAO(cfg, deser) fm = fd.(*fileDAO) r.EqualValues(4, fm.topIndex) r.EqualValues(1, fm.splitHeight) @@ -313,10 +318,11 @@ func TestCheckFiles(t *testing.T) { _, files = checkAuxFiles(cfg.DbPath, FileV2) r.Nil(files) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) // create 3 v2 files for i := 1; i <= 3; i++ { cfg.DbPath = kthAuxFileName("./filedao_v2.db", uint64(i)) - r.NoError(createNewV2File(1, cfg)) + r.NoError(createNewV2File(1, cfg, deser)) } defer func() { for i := 1; i <= 3; i++ { diff --git a/blockchain/filedao/filedao_v2.go b/blockchain/filedao/filedao_v2.go index a18a64c479..243f6c014a 100644 --- a/blockchain/filedao/filedao_v2.go +++ b/blockchain/filedao/filedao_v2.go @@ -48,11 +48,12 @@ type ( hashStore db.CountingIndex // store block hash blkStore db.CountingIndex // store raw blocks sysStore db.CountingIndex // store transaction log + deser *block.Deserializer } ) // newFileDAOv2 creates a new v2 file -func newFileDAOv2(bottom uint64, cfg db.Config) (*fileDAOv2, error) { +func newFileDAOv2(bottom uint64, cfg db.Config, deser *block.Deserializer) (*fileDAOv2, error) { if bottom == 0 { return nil, ErrNotSupported } @@ -71,17 +72,19 @@ func newFileDAOv2(bottom uint64, cfg db.Config) (*fileDAOv2, error) { blkCache: cache.NewThreadSafeLruCache(16), kvStore: db.NewBoltDB(cfg), batch: batch.NewBatch(), + deser: deser, } return &fd, nil } // openFileDAOv2 opens an existing v2 file -func openFileDAOv2(cfg db.Config) *fileDAOv2 { +func openFileDAOv2(cfg db.Config, deser *block.Deserializer) *fileDAOv2 { return &fileDAOv2{ filename: cfg.DbPath, blkCache: cache.NewThreadSafeLruCache(16), kvStore: db.NewBoltDB(cfg), batch: batch.NewBatch(), + deser: deser, } } diff --git a/blockchain/filedao/filedao_v2_test.go b/blockchain/filedao/filedao_v2_test.go index 6e3c495d53..270ffce25e 100644 --- a/blockchain/filedao/filedao_v2_test.go +++ b/blockchain/filedao/filedao_v2_test.go @@ -95,12 +95,13 @@ func TestNewFileDAOv2(t *testing.T) { r.Equal(compress.Snappy, cfg.Compressor) r.Equal(16, cfg.BlockStoreBatchSize) cfg.DbPath = testPath - _, err = newFileDAOv2(0, cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + _, err = newFileDAOv2(0, cfg, deser) r.Equal(ErrNotSupported, err) inMemFd, err := newFileDAOv2InMem(1) r.NoError(err) - fd, err := newFileDAOv2(2, cfg) + fd, err := newFileDAOv2(2, cfg, deser) r.NoError(err) for _, v2Fd := range []*fileDAOv2{inMemFd, fd} { @@ -115,7 +116,8 @@ func TestNewFdInterface(t *testing.T) { r := require.New(t) testutil.CleanupPath(cfg.DbPath) - fd, err := newFileDAOv2(start, cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + fd, err := newFileDAOv2(start, cfg, deser) r.NoError(err) ctx := context.Background() @@ -256,7 +258,8 @@ func TestNewFdInterface(t *testing.T) { cfg := db.DefaultConfig cfg.DbPath = testPath - _, err = newFileDAOv2(0, cfg) + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) + _, err = newFileDAOv2(0, cfg, deser) r.Equal(ErrNotSupported, err) genesis.SetGenesisTimestamp(config.Default.Genesis.Timestamp) block.LoadGenesisHash(&config.Default.Genesis) @@ -274,10 +277,10 @@ func TestNewFdInterface(t *testing.T) { func TestNewFdStart(t *testing.T) { testFdStart := func(cfg db.Config, start uint64, t *testing.T) { r := require.New(t) - + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) for _, num := range []uint64{3, _blockStoreBatchSize - 1, _blockStoreBatchSize, 2*_blockStoreBatchSize - 1} { testutil.CleanupPath(cfg.DbPath) - fd, err := newFileDAOv2(start, cfg) + fd, err := newFileDAOv2(start, cfg, deser) r.NoError(err) ctx := context.Background() r.NoError(fd.Start(ctx)) @@ -290,7 +293,7 @@ func TestNewFdStart(t *testing.T) { r.NoError(fd.Stop(ctx)) // start from existing file - fd = openFileDAOv2(cfg) + fd = openFileDAOv2(cfg, deser) r.NoError(fd.Start(ctx)) height, err = fd.Bottom() r.NoError(err) diff --git a/blockchain/filedao/filedao_v2_util.go b/blockchain/filedao/filedao_v2_util.go index 27f4df14a1..009747ac75 100644 --- a/blockchain/filedao/filedao_v2_util.go +++ b/blockchain/filedao/filedao_v2_util.go @@ -19,7 +19,7 @@ import ( ) func (fd *fileDAOv2) populateStagingBuffer() (*stagingBuffer, error) { - buffer := newStagingBuffer(fd.header.BlockStoreSize) + buffer := newStagingBuffer(fd.header.BlockStoreSize, fd.deser) blockStoreTip := fd.highestBlockOfStoreTip() for i := uint64(0); i < fd.header.BlockStoreSize; i++ { v, err := fd.kvStore.Get(_headerDataNs, byteutil.Uint64ToBytesBigEndian(i)) @@ -34,8 +34,8 @@ func (fd *fileDAOv2) populateStagingBuffer() (*stagingBuffer, error) { if err != nil { return nil, err } - info := &block.Store{} - if err := info.Deserialize(v); err != nil { + info, err := fd.deser.DeserializeBlockStore(v) + if err != nil { return nil, err } @@ -185,7 +185,7 @@ func (fd *fileDAOv2) getBlockStore(height uint64) (*block.Store, error) { // check whether block in read cache or not if value, ok := fd.blkCache.Get(storeKey); ok { pbInfos := value.(*iotextypes.BlockStores) - return extractBlockStore(pbInfos, stagingKey(height, fd.header)) + return fd.deser.FromBlockStoreProto(pbInfos.BlockStores[stagingKey(height, fd.header)]) } value, err := fd.blkStore.Get(storeKey) @@ -206,13 +206,5 @@ func (fd *fileDAOv2) getBlockStore(height uint64) (*block.Store, error) { // add to read cache fd.blkCache.Add(storeKey, pbStores) - return extractBlockStore(pbStores, stagingKey(height, fd.header)) -} - -func extractBlockStore(pbStores *iotextypes.BlockStores, height uint64) (*block.Store, error) { - info := &block.Store{} - if err := info.FromProto(pbStores.BlockStores[height]); err != nil { - return nil, err - } - return info, nil + return fd.deser.FromBlockStoreProto(pbStores.BlockStores[stagingKey(height, fd.header)]) } diff --git a/blockchain/filedao/staging_buffer.go b/blockchain/filedao/staging_buffer.go index 5b1297e727..dd41da8b98 100644 --- a/blockchain/filedao/staging_buffer.go +++ b/blockchain/filedao/staging_buffer.go @@ -18,13 +18,15 @@ type ( stagingBuffer struct { size uint64 buffer []*block.Store + deser *block.Deserializer } ) -func newStagingBuffer(size uint64) *stagingBuffer { +func newStagingBuffer(size uint64, deser *block.Deserializer) *stagingBuffer { return &stagingBuffer{ size: size, buffer: make([]*block.Store, size), + deser: deser, } } @@ -39,8 +41,8 @@ func (s *stagingBuffer) Put(pos uint64, blkBytes []byte) (bool, error) { if pos >= s.size { return false, ErrNotSupported } - blk := &block.Store{} - if err := blk.Deserialize(blkBytes); err != nil { + blk, err := s.deser.DeserializeBlockStore(blkBytes) + if err != nil { return false, err } s.buffer[pos] = blk diff --git a/blockchain/filedao/testing.go b/blockchain/filedao/testing.go index a6da90cdfc..67e9bb9244 100644 --- a/blockchain/filedao/testing.go +++ b/blockchain/filedao/testing.go @@ -68,6 +68,7 @@ func newFileDAOv2InMem(bottom uint64) (*fileDAOv2, error) { blkCache: cache.NewThreadSafeLruCache(16), kvStore: db.NewMemKVStore(), batch: batch.NewBatch(), + deser: block.NewDeserializer(config.Default.Chain.EVMNetworkID), } return &fd, nil } diff --git a/blockchain/integrity/benchmark_test.go b/blockchain/integrity/benchmark_test.go index 781d8c2cae..eaf0d2a62d 100644 --- a/blockchain/integrity/benchmark_test.go +++ b/blockchain/integrity/benchmark_test.go @@ -258,7 +258,8 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(1000000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO(indexers, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) if dao == nil { return nil, nil, errors.New("pointer is nil") } diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index c5d843a8f2..07ee66cc1c 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -866,7 +866,8 @@ func TestConstantinople(t *testing.T) { require.NoError(err) // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf, indexer}, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf, indexer}, cfg.DB, deser) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg, @@ -1111,7 +1112,8 @@ func TestLoadBlockchainfromDB(t *testing.T) { cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO(indexers, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg, @@ -1409,7 +1411,8 @@ func TestBlockchainInitialCandidate(t *testing.T) { require.NoError(accountProtocol.Register(registry)) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) bc := blockchain.NewBlockchain( cfg, dao, @@ -1498,7 +1501,8 @@ func TestBlocks(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) // Create a blockchain from scratch bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) @@ -1570,7 +1574,8 @@ func TestActions(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) // Create a blockchain from scratch bc := blockchain.NewBlockchain( cfg, @@ -1855,7 +1860,8 @@ func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factor cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String() // create BlockDAO cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO(indexers, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO(indexers, cfg.DB, deser) require.NotNil(dao) bc := blockchain.NewBlockchain( cfg, diff --git a/blockindex/indexbuilder_test.go b/blockindex/indexbuilder_test.go index 27df65d2d0..994985d617 100644 --- a/blockindex/indexbuilder_test.go +++ b/blockindex/indexbuilder_test.go @@ -13,6 +13,7 @@ import ( "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-core/action/protocol" + "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" @@ -161,7 +162,7 @@ func TestIndexBuilder(t *testing.T) { }() cfg := db.DefaultConfig cfg.DbPath = testPath - + deser := block.NewDeserializer(config.Default.Chain.EVMNetworkID) for _, v := range []struct { dao blockdao.BlockDAO inMem bool @@ -170,7 +171,7 @@ func TestIndexBuilder(t *testing.T) { blockdao.NewBlockDAOInMemForTest(nil), true, }, { - blockdao.NewBlockDAO(nil, cfg), false, + blockdao.NewBlockDAO(nil, cfg, deser), false, }, } { t.Run("test indexbuilder", func(t *testing.T) { diff --git a/chainservice/builder.go b/chainservice/builder.go index d3e6be6bd9..8c704983ee 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -250,7 +250,8 @@ func (builder *Builder) buildBlockDAO(forTest bool) error { } else { dbConfig := builder.cfg.DB dbConfig.DbPath = builder.cfg.Chain.ChainDBPath - builder.cs.blockdao = blockdao.NewBlockDAO(indexers, dbConfig) + deser := block.NewDeserializer(builder.cfg.Chain.EVMNetworkID) + builder.cs.blockdao = blockdao.NewBlockDAO(indexers, dbConfig, deser) } return nil diff --git a/chainservice/chainservice.go b/chainservice/chainservice.go index 320d59e782..fd7b89ff31 100644 --- a/chainservice/chainservice.go +++ b/chainservice/chainservice.go @@ -85,7 +85,7 @@ func (cs *ChainService) HandleAction(ctx context.Context, actPb *iotextypes.Acti // HandleBlock handles incoming block request. func (cs *ChainService) HandleBlock(ctx context.Context, peer string, pbBlock *iotextypes.Block) error { - blk, err := (&block.Deserializer{}).SetEvmNetworkID(cs.chain.EvmNetworkID()).FromBlockProto(pbBlock) + blk, err := block.NewDeserializer(cs.chain.EvmNetworkID()).FromBlockProto(pbBlock) if err != nil { return err } diff --git a/consensus/scheme/rolldpos/blockproposal.go b/consensus/scheme/rolldpos/blockproposal.go index 81dd65b3f9..b0011cc84d 100644 --- a/consensus/scheme/rolldpos/blockproposal.go +++ b/consensus/scheme/rolldpos/blockproposal.go @@ -64,7 +64,7 @@ func (bp *blockProposal) ProposerAddress() string { func (bp *blockProposal) LoadProto(msg *iotextypes.BlockProposal) error { // TODO: pass the correct EVM network ID at time of newConsensus() or from ctx - blk, err := (&block.Deserializer{}).SetEvmNetworkID(config.EVMNetworkID()).FromBlockProto(msg.Block) + blk, err := block.NewDeserializer(config.EVMNetworkID()).FromBlockProto(msg.Block) if err != nil { return err } diff --git a/consensus/scheme/rolldpos/endorsementmanager.go b/consensus/scheme/rolldpos/endorsementmanager.go index ee1b0fb588..ce0f1e197a 100644 --- a/consensus/scheme/rolldpos/endorsementmanager.go +++ b/consensus/scheme/rolldpos/endorsementmanager.go @@ -127,7 +127,7 @@ func (bc *blockEndorsementCollection) fromProto(blockPro *endorsementpb.BlockEnd bc.blk = nil } else { // TODO: pass the correct EVM network ID at time of newConsensus() or from ctx - blk, err := (&block.Deserializer{}).SetEvmNetworkID(config.EVMNetworkID()).FromBlockProto(blockPro.Blk) + blk, err := block.NewDeserializer(config.EVMNetworkID()).FromBlockProto(blockPro.Blk) if err != nil { return err } @@ -292,7 +292,7 @@ func (m *endorsementManager) fromProto(managerPro *endorsementpb.EndorsementMana } if managerPro.CachedMintedBlk != nil { // TODO: pass the correct EVM network ID at time of newConsensus() or from ctx - blk, err := (&block.Deserializer{}).SetEvmNetworkID(config.EVMNetworkID()).FromBlockProto(managerPro.CachedMintedBlk) + blk, err := block.NewDeserializer(config.EVMNetworkID()).FromBlockProto(managerPro.CachedMintedBlk) if err != nil { return err } diff --git a/consensus/scheme/rolldpos/roundcalculator_test.go b/consensus/scheme/rolldpos/roundcalculator_test.go index 930811d214..72cada0d85 100644 --- a/consensus/scheme/rolldpos/roundcalculator_test.go +++ b/consensus/scheme/rolldpos/roundcalculator_test.go @@ -186,7 +186,8 @@ func makeChain(t *testing.T) (blockchain.Blockchain, factory.Factory, actpool.Ac require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf}, dbcfg, deser) chain := blockchain.NewBlockchain( cfg, dao, diff --git a/e2etest/local_test.go b/e2etest/local_test.go index 0c2bfbf85f..b5ca659a6a 100644 --- a/e2etest/local_test.go +++ b/e2etest/local_test.go @@ -161,7 +161,8 @@ func TestLocalCommit(t *testing.T) { require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf2}, dbcfg) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO([]blockdao.BlockIndexer{sf2}, dbcfg, deser) chain := blockchain.NewBlockchain( cfg, dao, @@ -476,7 +477,8 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 3 from empty state DB cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao := blockdao.NewBlockDAO(nil, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + dao := blockdao.NewBlockDAO(nil, cfg.DB, deser) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), protocol.BlockchainCtx{ @@ -498,7 +500,7 @@ func TestStartExistingBlockchain(t *testing.T) { // Recover to height 2 from an existing state DB with Height 3 require.NoError(svr.Stop(ctx)) cfg.DB.DbPath = cfg.Chain.ChainDBPath - dao = blockdao.NewBlockDAO(nil, cfg.DB) + dao = blockdao.NewBlockDAO(nil, cfg.DB, deser) require.NoError(dao.Start(protocol.WithBlockchainCtx( genesis.WithGenesisContext(ctx, cfg.Genesis), protocol.BlockchainCtx{ diff --git a/pkg/util/httputil/httputil_test.go b/pkg/util/httputil/httputil_test.go index 4dd645ca20..29189ed983 100644 --- a/pkg/util/httputil/httputil_test.go +++ b/pkg/util/httputil/httputil_test.go @@ -37,6 +37,11 @@ func TestLimitListener(t *testing.T) { t.Run("input empty string", func(t *testing.T) { _, err := LimitListener("") - require.NoError(t, err) + // fix none root permission error + if err != nil { + require.Equal(t, "listen tcp :80: bind: permission denied", err.Error()) + } else { + require.NoError(t, err) + } }) } diff --git a/tools/iomigrater/cmds/check-height.go b/tools/iomigrater/cmds/check-height.go index 660e33db65..aa72b4b437 100644 --- a/tools/iomigrater/cmds/check-height.go +++ b/tools/iomigrater/cmds/check-height.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/cobra" + "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/tools/iomigrater/common" @@ -53,7 +54,8 @@ func checkDbFileHeight(filePath string) (uint64, error) { } cfg.DB.DbPath = filePath - blockDao := blockdao.NewBlockDAO(nil, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + blockDao := blockdao.NewBlockDAO(nil, cfg.DB, deser) // Load height value. ctx := context.Background() diff --git a/tools/iomigrater/cmds/migrate-db.go b/tools/iomigrater/cmds/migrate-db.go index 7a4c170372..0af5bbf764 100644 --- a/tools/iomigrater/cmds/migrate-db.go +++ b/tools/iomigrater/cmds/migrate-db.go @@ -7,6 +7,7 @@ import ( "github.com/schollz/progressbar/v2" "github.com/spf13/cobra" + "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/tools/iomigrater/common" @@ -113,10 +114,11 @@ func migrateDbFile() error { } cfg.DB.DbPath = oldFile - oldDAO := blockdao.NewBlockDAO(nil, cfg.DB) + deser := block.NewDeserializer(cfg.Chain.EVMNetworkID) + oldDAO := blockdao.NewBlockDAO(nil, cfg.DB, deser) cfg.DB.DbPath = newFile - newDAO := blockdao.NewBlockDAO(nil, cfg.DB) + newDAO := blockdao.NewBlockDAO(nil, cfg.DB, deser) ctx := context.Background() if err := oldDAO.Start(ctx); err != nil { From 00026974ea9aade22859d07485422a1298ba8d0f Mon Sep 17 00:00:00 2001 From: dustinxie Date: Tue, 28 Jun 2022 11:22:44 -0700 Subject: [PATCH 19/24] [api] update chain metrics (#3484) --- api/grpcserver.go | 16 +++++++--------- api/grpcserver_test.go | 1 + go.sum | 9 +++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/api/grpcserver.go b/api/grpcserver.go index c35103bd0e..1a1b21ad29 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -79,7 +79,7 @@ var ( Name: "iotex_apicallsource_nochainid_metrics", Help: "API call Source Without ChainID Statistics", }, - []string{"client_ip", "sender", "recipient"}, + []string{"client_ip", "sender"}, ) ) @@ -336,19 +336,17 @@ func (svr *GRPCServer) SendAction(ctx context.Context, in *iotexapi.SendActionRe if in.GetAction().GetCore().GetChainID() > 0 { _apiCallSourceWithChainIDMtc.WithLabelValues(chainID).Inc() } else { - var clientIP, sender, recipient string - selp, err := (&action.Deserializer{}).ActionToSealedEnvelope(in.GetAction()) + selp, err := (&action.Deserializer{}).SetEvmNetworkID(svr.coreService.EVMNetworkID()).ActionToSealedEnvelope(in.GetAction()) if err != nil { return nil, err } + var clientIP string if p, ok := peer.FromContext(ctx); ok { clientIP, _, _ = net.SplitHostPort(p.Addr.String()) + } else { + clientIP = "unknownIP" } - if senderAddr, err := address.FromBytes(selp.SrcPubkey().Hash()); err == nil { - sender = senderAddr.String() - } - recipient, _ = selp.Destination() - _apiCallSourceWithOutChainIDMtc.WithLabelValues(clientIP, sender, recipient).Inc() + _apiCallSourceWithOutChainIDMtc.WithLabelValues(clientIP, selp.SenderAddress().String()).Inc() } actHash, err := svr.coreService.SendAction(ctx, in.GetAction()) if err != nil { @@ -690,7 +688,7 @@ func (svr *GRPCServer) TraceTransactionStructLogs(ctx context.Context, in *iotex if err != nil { return nil, err } - act, err := (&action.Deserializer{}).ActionToSealedEnvelope(actInfo.Action) + act, err := (&action.Deserializer{}).SetEvmNetworkID(svr.coreService.EVMNetworkID()).ActionToSealedEnvelope(actInfo.Action) if err != nil { return nil, err } diff --git a/api/grpcserver_test.go b/api/grpcserver_test.go index 0c79e32a72..084a65f390 100644 --- a/api/grpcserver_test.go +++ b/api/grpcserver_test.go @@ -67,6 +67,7 @@ func TestGrpcServer_SendAction(t *testing.T) { grpcSvr := NewGRPCServer(core, testutil.RandomPort()) for _, test := range _sendActionTests { + core.EXPECT().EVMNetworkID().Return(uint32(1)) core.EXPECT().SendAction(context.Background(), test.actionPb).Return(test.actionHash, nil) request := &iotexapi.SendActionRequest{Action: test.actionPb} res, err := grpcSvr.SendAction(context.Background(), request) diff --git a/go.sum b/go.sum index eec36516bb..08fc6e57af 100644 --- a/go.sum +++ b/go.sum @@ -133,6 +133,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -445,9 +446,12 @@ github.com/iotexproject/go-p2p v0.3.3 h1:qDGwaHu1oYG93PIcJAnY5Hl2iK0GoeAQewB0Qtv github.com/iotexproject/go-p2p v0.3.3/go.mod h1:MjgwpexfBxhgq0cDoqHCxMQ1cLkv96p3xZJ02LLVGLA= github.com/iotexproject/go-pkgs v0.1.5-0.20210604060651-be5ee19f2575/go.mod h1:ttXhcwrtODyh7JozpJlCml09CjP0pcKqTe2B0MbTGc8= github.com/iotexproject/go-pkgs v0.1.5/go.mod h1:ttXhcwrtODyh7JozpJlCml09CjP0pcKqTe2B0MbTGc8= +github.com/iotexproject/go-pkgs v0.1.6/go.mod h1:E+Fl0XQZz56EzXFajFET2yFoRGsIbL6wQooVIkSim3o= github.com/iotexproject/go-pkgs v0.1.12-0.20220209063039-b876814568a0 h1:2afEg5WhExrhmuLbd6oObvMyhE72H0n3vRTdT8JNAgA= github.com/iotexproject/go-pkgs v0.1.12-0.20220209063039-b876814568a0/go.mod h1:wPM/LtoKhMvekRefuHe+oKPOBSpxmCPxlIuiQHeLrfQ= github.com/iotexproject/iotex-address v0.2.4/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= +github.com/iotexproject/iotex-address v0.2.5/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= +github.com/iotexproject/iotex-address v0.2.6/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= github.com/iotexproject/iotex-address v0.2.8 h1:jaTR5pZe/ljiYW4OqHl9NKPs0h1o91Gi6FILOTaBCXw= github.com/iotexproject/iotex-address v0.2.8/go.mod h1:K78yPSMB4K7gF/iQ7djT1amph0RBrP3rSkFfH7gNG70= github.com/iotexproject/iotex-antenna-go/v2 v2.5.1-0.20210604061028-2c2056a5bfdb/go.mod h1:NqFzRL8RtA3xfXGpYbs0IY71HDiD6Dh2hD9iYngKLIU= @@ -456,6 +460,7 @@ github.com/iotexproject/iotex-antenna-go/v2 v2.5.1/go.mod h1:8pDZcM45M0gY6jm3PoM github.com/iotexproject/iotex-election v0.3.5-0.20210611041425-20ddf674363d h1:/j1xCAC9YiG/8UKqYvycS/v3ddVsb1G7AMyLXOjeYI0= github.com/iotexproject/iotex-election v0.3.5-0.20210611041425-20ddf674363d/go.mod h1:GRWevxtqQ4gPMrd7Qxhr29/7aTgvjiTp+rFI9KMMZEo= github.com/iotexproject/iotex-proto v0.5.0/go.mod h1:Xg6REkv+nTZN+OC22xXIQuqKdTWWHwOAJEXCoMpDwtI= +github.com/iotexproject/iotex-proto v0.5.2/go.mod h1:Xg6REkv+nTZN+OC22xXIQuqKdTWWHwOAJEXCoMpDwtI= github.com/iotexproject/iotex-proto v0.5.10-0.20220415042310-0d4bcef3febf h1:WYy4bBinJXJBqkgIVQk7rTwQzW0d/Ci6DKQL6CnveM4= github.com/iotexproject/iotex-proto v0.5.10-0.20220415042310-0d4bcef3febf/go.mod h1:OfmLvjBmy5EYeLxxDv6kesJq+Mm3Adn5GKgDJgF9G9U= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -549,6 +554,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -786,6 +792,7 @@ github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux/v2 v2.2.0 h1:RwtpYZ2/wVviZ5+3pjC8qdQ4TKnrak0/E01N1UWoAFU= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= @@ -1367,6 +1374,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1461,6 +1469,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= From 3037d8ec77875662bf0072ca4b2d8f089773ecdf Mon Sep 17 00:00:00 2001 From: dustinxie Date: Tue, 28 Jun 2022 23:29:33 -0700 Subject: [PATCH 20/24] [makefile] add go mod tidy (#3471) Co-authored-by: millken --- Makefile | 1 + go.mod | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 69278533b6..cc277ba08f 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,7 @@ build-staterecoverer: .PHONY: fmt fmt: $(GOCMD) fmt ./... + $(GOCMD) mod tidy .PHONY: lint lint: diff --git a/go.mod b/go.mod index 76c039dfd8..073442b341 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,11 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) +require ( + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible + github.com/shirou/gopsutil/v3 v3.22.2 +) + require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/benbjohnson/clock v1.0.3 // indirect @@ -157,8 +162,6 @@ require ( github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/rjeczalik/notify v0.9.2 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible - github.com/shirou/gopsutil/v3 v3.22.2 github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect From 38fb852795d784a07d22b07be877fc0059f5929a Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Thu, 30 Jun 2022 00:00:06 +0800 Subject: [PATCH 21/24] [ioctl] Build hdwallet create command line into new ioctl (#3470) * [ioctl] build hdwallet create command line into new ioctl --- ioctl/newcmd/hdwallet/hdwalletcreate.go | 77 ++++++++++++++++++++ ioctl/newcmd/hdwallet/hdwalletcreate_test.go | 58 +++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 ioctl/newcmd/hdwallet/hdwalletcreate.go create mode 100644 ioctl/newcmd/hdwallet/hdwalletcreate_test.go diff --git a/ioctl/newcmd/hdwallet/hdwalletcreate.go b/ioctl/newcmd/hdwallet/hdwalletcreate.go new file mode 100644 index 0000000000..3c700bd753 --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletcreate.go @@ -0,0 +1,77 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/tyler-smith/go-bip39" + + "github.com/iotexproject/iotex-core/ioctl" + "github.com/iotexproject/iotex-core/ioctl/config" +) + +// Multi-language support +var ( + _createByMnemonicCmdShorts = map[config.Language]string{ + config.English: "create hdwallet using mnemonic", + config.Chinese: "通过助记词创建新钱包", + } + _createByMnemonicCmdUses = map[config.Language]string{ + config.English: "create", + config.Chinese: "create 创建", + } +) + +// NewHdwalletCreateCmd represents the hdwallet create command +func NewHdwalletCreateCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_createByMnemonicCmdUses) + short, _ := client.SelectTranslation(_createByMnemonicCmdShorts) + + return &cobra.Command{ + Use: use, + Short: short, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + if client.IsHdWalletConfigFileExist() { + cmd.Println("Please run 'ioctl hdwallet delete' before import") + return nil + } + cmd.Println("Set password") + password, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + cmd.Println("Enter password again") + passwordAgain, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + if password != passwordAgain { + return ErrPasswdNotMatch + } + + entropy, err := bip39.NewEntropy(128) + if err != nil { + return err + } + mnemonic, err := bip39.NewMnemonic(entropy) + if err != nil { + return err + } + + if err = client.WriteHdWalletConfigFile(mnemonic, password); err != nil { + return err + } + + cmd.Printf("Mnemonic phrase: %s\n"+ + "It is used to recover your wallet in case you forgot the password. Write them down and store it in a safe place.\n", mnemonic) + return nil + }, + } +} diff --git a/ioctl/newcmd/hdwallet/hdwalletcreate_test.go b/ioctl/newcmd/hdwallet/hdwalletcreate_test.go new file mode 100644 index 0000000000..0647ed2719 --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletcreate_test.go @@ -0,0 +1,58 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNewHdwalletCreateCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + password := "123" + + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(9) + client.EXPECT().IsHdWalletConfigFileExist().Return(false).Times(3) + + t.Run("create hdwallet", func(t *testing.T) { + client.EXPECT().ReadSecret().Return(password, nil).Times(2) + client.EXPECT().WriteHdWalletConfigFile(gomock.Any(), gomock.Any()).Return(nil) + + cmd := NewHdwalletCreateCmd(client) + result, err := util.ExecuteCmd(cmd) + require.NoError(err) + require.Contains(result, "It is used to recover your wallet in case you forgot the password. Write them down and store it in a safe place.") + }) + + t.Run("failed to get password", func(t *testing.T) { + expectedErr := errors.New("failed to get password") + client.EXPECT().ReadSecret().Return("", expectedErr) + + cmd := NewHdwalletCreateCmd(client) + _, err := util.ExecuteCmd(cmd) + require.Contains(err.Error(), expectedErr.Error()) + }) + + t.Run("password not match", func(t *testing.T) { + expectedErr := errors.New("password doesn't match") + client.EXPECT().ReadSecret().Return(password, nil) + client.EXPECT().ReadSecret().Return("test", nil) + + cmd := NewHdwalletCreateCmd(client) + _, err := util.ExecuteCmd(cmd) + require.Equal(err.Error(), expectedErr.Error()) + }) +} From a4b10982cfce5ff3298d8816e257e7956305d66d Mon Sep 17 00:00:00 2001 From: Jeremy Chou Date: Fri, 1 Jul 2022 06:04:09 +0800 Subject: [PATCH 22/24] [ioctl] Build hdwallet derive command line into new ioctl (#3418) * [ioctl] build hdwallet derive command line into new ioctl * inline DeriveKey * adjust order * revert DeriveKey inline * create ExportHdwallet client interface combine hdwalletderive & hdwalletexport code and create ExportHdwallet client interface * [ioctl] create main for ioctl/newcmd (#3296) * create main for ioctl/newcmd * change return type of HdwalletMnemonic * refactor unit test to cover the modification * refactor unit test to cover the modification * fix commit * fix commit Co-authored-by: huofei <68298506@qq.com> Co-authored-by: CoderZhi --- ioctl/newcmd/account/account.go | 16 ++-- ioctl/newcmd/hdwallet/hdwalletderive.go | 85 ++++++++++++-------- ioctl/newcmd/hdwallet/hdwalletderive_test.go | 55 +++++++++++++ 3 files changed, 116 insertions(+), 40 deletions(-) create mode 100644 ioctl/newcmd/hdwallet/hdwalletderive_test.go diff --git a/ioctl/newcmd/account/account.go b/ioctl/newcmd/account/account.go index 98b68915c3..27057ee02e 100644 --- a/ioctl/newcmd/account/account.go +++ b/ioctl/newcmd/account/account.go @@ -148,7 +148,7 @@ func PrivateKeyFromSigner(client ioctl.Client, cmd *cobra.Command, signer, passw } if password == "" { - cmd.Println(fmt.Sprintf("Enter password for #%s:\n", signer)) + cmd.Printf("Enter password for #%s:\n", signer) password, err = client.ReadSecret() if err != nil { return nil, errors.Wrap(err, "failed to get password") @@ -160,7 +160,7 @@ func PrivateKeyFromSigner(client ioctl.Client, cmd *cobra.Command, signer, passw if err != nil { return nil, errors.Wrap(err, "invalid HDWallet key format") } - _, prvKey, err = hdwallet.DeriveKey(account, change, index, password) + _, prvKey, err = hdwallet.DeriveKey(client, account, change, index, password) if err != nil { return nil, errors.Wrap(err, "failed to derive key from HDWallet") } @@ -218,12 +218,12 @@ func IsSignerExist(client ioctl.Client, signer string) bool { } func newAccount(client ioctl.Client, cmd *cobra.Command, alias string) (string, error) { - cmd.Println(fmt.Sprintf("#%s: Set password\n", alias)) + cmd.Printf("#%s: Set password\n", alias) password, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") } - cmd.Println(fmt.Sprintf("#%s: Enter password again\n", alias)) + cmd.Printf("#%s: Enter password again\n", alias) passwordAgain, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") @@ -244,12 +244,12 @@ func newAccount(client ioctl.Client, cmd *cobra.Command, alias string) (string, } func newAccountSm2(client ioctl.Client, cmd *cobra.Command, alias string) (string, error) { - cmd.Println(fmt.Sprintf("#%s: Set password\n", alias)) + cmd.Printf("#%s: Set password\n", alias) password, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") } - cmd.Println(fmt.Sprintf("#%s: Enter password again\n", alias)) + cmd.Printf("#%s: Enter password again\n", alias) passwordAgain, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") @@ -276,12 +276,12 @@ func newAccountSm2(client ioctl.Client, cmd *cobra.Command, alias string) (strin } func newAccountByKey(client ioctl.Client, cmd *cobra.Command, alias string, privateKey string) (string, error) { - cmd.Println(fmt.Sprintf("#%s: Set password\n", alias)) + cmd.Printf("#%s: Set password\n", alias) password, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") } - cmd.Println(fmt.Sprintf("#%s: Enter password again\n", alias)) + cmd.Printf("#%s: Enter password again\n", alias) passwordAgain, err := client.ReadSecret() if err != nil { return "", errors.Wrap(err, "failed to get password") diff --git a/ioctl/newcmd/hdwallet/hdwalletderive.go b/ioctl/newcmd/hdwallet/hdwalletderive.go index 71f1ec74a1..c60ab6faf6 100644 --- a/ioctl/newcmd/hdwallet/hdwalletderive.go +++ b/ioctl/newcmd/hdwallet/hdwalletderive.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 IoTeX Foundation +// Copyright (c) 2022 IoTeX Foundation // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -7,50 +7,71 @@ package hdwallet import ( - "bytes" "fmt" - "os" ecrypt "github.com/ethereum/go-ethereum/crypto" "github.com/iotexproject/go-pkgs/crypto" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/iotexproject/iotex-core/ioctl" "github.com/iotexproject/iotex-core/ioctl/config" - "github.com/iotexproject/iotex-core/ioctl/output" "github.com/iotexproject/iotex-core/ioctl/util" - "github.com/iotexproject/iotex-core/pkg/util/fileutil" ) -// DeriveKey derives the key according to path -func DeriveKey(account, change, index uint32, password string) (string, crypto.PrivateKey, error) { - // derive key as "m/44'/304'/account'/change/index" - hdWalletConfigFile := config.ReadConfig.Wallet + "/hdwallet" - if !fileutil.FileExists(hdWalletConfigFile) { - return "", nil, output.NewError(output.InputError, "Run 'ioctl hdwallet create' to create your HDWallet first.", nil) +// Multi-language support +var ( + _hdwalletDeriveCmdUses = map[config.Language]string{ + config.English: "derive id1/id2/id3", + config.Chinese: "derive id1/id2/id3", } - - enctxt, err := os.ReadFile(hdWalletConfigFile) - if err != nil { - return "", nil, output.NewError(output.InputError, "failed to read config", err) + _hdwalletDeriveCmdShorts = map[config.Language]string{ + config.English: "derive key from HDWallet", + config.Chinese: "查询HDWallet钱包的派生key地址", } +) - enckey := util.HashSHA256([]byte(password)) - dectxt, err := util.Decrypt(enctxt, enckey) - if err != nil { - return "", nil, output.NewError(output.InputError, "failed to decrypt", err) - } +// NewHdwalletDeriveCmd represents the hdwallet derive command +func NewHdwalletDeriveCmd(client ioctl.Client) *cobra.Command { + use, _ := client.SelectTranslation(_hdwalletDeriveCmdUses) + short, _ := client.SelectTranslation(_hdwalletDeriveCmdShorts) - dectxtLen := len(dectxt) - if dectxtLen <= 32 { - return "", nil, output.NewError(output.ValidationError, "incorrect data", nil) - } + return &cobra.Command{ + Use: use, + Short: short, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + signer := "hdw::" + args[0] + account, change, index, err := util.ParseHdwPath(signer) + if err != nil { + return errors.Wrap(err, "invalid hdwallet key format") + } - mnemonic, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:] - if !bytes.Equal(hash, util.HashSHA256(mnemonic)) { - return "", nil, output.NewError(output.ValidationError, "password error", nil) + cmd.Println("Enter password:") + password, err := client.ReadSecret() + if err != nil { + return errors.Wrap(err, "failed to get password") + } + + addr, _, err := DeriveKey(client, account, change, index, password) + if err != nil { + return err + } + cmd.Printf("address: %s\n", addr) + return nil + }, } +} - wallet, err := hdwallet.NewFromMnemonic(string(mnemonic)) +// DeriveKey derives the key according to path +func DeriveKey(client ioctl.Client, account, change, index uint32, password string) (string, crypto.PrivateKey, error) { + mnemonic, err := client.HdwalletMnemonic(password) + if err != nil { + return "", nil, err + } + wallet, err := hdwallet.NewFromMnemonic(mnemonic) if err != nil { return "", nil, err } @@ -59,21 +80,21 @@ func DeriveKey(account, change, index uint32, password string) (string, crypto.P path := hdwallet.MustParseDerivationPath(derivationPath) walletAccount, err := wallet.Derive(path, false) if err != nil { - return "", nil, output.NewError(output.InputError, "failed to get account by derive path", err) + return "", nil, errors.Wrap(err, "failed to get account by derive path") } private, err := wallet.PrivateKey(walletAccount) if err != nil { - return "", nil, output.NewError(output.InputError, "failed to get private key", err) + return "", nil, errors.Wrap(err, "failed to get private key") } prvKey, err := crypto.BytesToPrivateKey(ecrypt.FromECDSA(private)) if err != nil { - return "", nil, output.NewError(output.InputError, "failed to Bytes private key", err) + return "", nil, errors.Wrap(err, "failed to Bytes private key") } addr := prvKey.PublicKey().Address() if addr == nil { - return "", nil, output.NewError(output.ConvertError, "failed to convert public key into address", nil) + return "", nil, errors.Wrap(err, "failed to convert public key into address") } return addr.String(), prvKey, nil } diff --git a/ioctl/newcmd/hdwallet/hdwalletderive_test.go b/ioctl/newcmd/hdwallet/hdwalletderive_test.go new file mode 100644 index 0000000000..40828b53f1 --- /dev/null +++ b/ioctl/newcmd/hdwallet/hdwalletderive_test.go @@ -0,0 +1,55 @@ +// Copyright (c) 2022 IoTeX Foundation +// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no +// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent +// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache +// License 2.0 that can be found in the LICENSE file. + +package hdwallet + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/util" + "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" +) + +func TestNewHdwalletDeriveCmd(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + client := mock_ioctlclient.NewMockClient(ctrl) + mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" + + client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(6) + client.EXPECT().ReadSecret().Return("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1", nil).Times(2) + + t.Run("get address from hdwallet", func(t *testing.T) { + client.EXPECT().HdwalletMnemonic(gomock.Any()).Return(mnemonic, nil) + + cmd := NewHdwalletDeriveCmd(client) + result, err := util.ExecuteCmd(cmd, "1/1/2") + require.NoError(err) + require.Contains(result, "address: io1pt2wml6v2tx683ctjn3k9mfgq97zx4c7rzwfuf") + }) + + t.Run("invalid hdwallet key format", func(t *testing.T) { + expectedErr := errors.New("invalid hdwallet key format") + + cmd := NewHdwalletDeriveCmd(client) + _, err := util.ExecuteCmd(cmd, "1") + require.Contains(err.Error(), expectedErr.Error()) + }) + + t.Run("failed to export mnemonic", func(t *testing.T) { + expectedErr := errors.New("failed to export mnemonic") + client.EXPECT().HdwalletMnemonic(gomock.Any()).Return("", expectedErr) + + cmd := NewHdwalletDeriveCmd(client) + _, err := util.ExecuteCmd(cmd, "1/1/2") + require.Contains(err.Error(), expectedErr.Error()) + }) +} From 5ee6a4f1eb2ae1e8659f13bdc6c9131bd26150df Mon Sep 17 00:00:00 2001 From: Haaai <55118568+Liuhaai@users.noreply.github.com> Date: Fri, 1 Jul 2022 01:58:48 -0700 Subject: [PATCH 23/24] [api] Separate Server and Server Handler (#3485) * fix #3372 --- api/grpcserver.go | 96 +++++++++------- api/grpcserver_integrity_test.go | 188 ++++++++++++++++++------------- api/grpcserver_test.go | 7 +- api/http.go | 33 ++++-- api/http_test.go | 4 +- api/serverV2.go | 7 +- api/serverV2_test.go | 4 +- api/web3server_test.go | 5 +- api/websocket.go | 43 ++----- 9 files changed, 208 insertions(+), 179 deletions(-) diff --git a/api/grpcserver.go b/api/grpcserver.go index 1a1b21ad29..1a7ca92703 100644 --- a/api/grpcserver.go +++ b/api/grpcserver.go @@ -49,12 +49,18 @@ import ( "github.com/iotexproject/iotex-core/pkg/tracer" ) -// GRPCServer contains grpc server and the pointer to api coreservice -type GRPCServer struct { - port string - grpcServer *grpc.Server - coreService CoreService -} +type ( + // GRPCServer contains grpc server + GRPCServer struct { + port string + svr *grpc.Server + } + + // GRPCHandler contains the pointer to api coreservice + gRPCHandler struct { + coreService CoreService + } +) // TODO: move this into config var ( @@ -116,23 +122,21 @@ func NewGRPCServer(core CoreService, grpcPort int) *GRPCServer { grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp), ) - svr := &GRPCServer{ - port: ":" + strconv.Itoa(grpcPort), - grpcServer: gSvr, - coreService: core, - } //serviceName: grpc.health.v1.Health grpc_health_v1.RegisterHealthServer(gSvr, health.NewServer()) - iotexapi.RegisterAPIServiceServer(gSvr, svr) + iotexapi.RegisterAPIServiceServer(gSvr, newGRPCHandler(core)) grpc_prometheus.Register(gSvr) reflection.Register(gSvr) - return svr + return &GRPCServer{ + port: ":" + strconv.Itoa(grpcPort), + svr: gSvr, + } } // Start starts the GRPC server -func (svr *GRPCServer) Start(_ context.Context) error { - lis, err := net.Listen("tcp", svr.port) +func (grpc *GRPCServer) Start(_ context.Context) error { + lis, err := net.Listen("tcp", grpc.port) if err != nil { log.L().Error("grpc server failed to listen.", zap.Error(err)) return errors.Wrap(err, "grpc server failed to listen") @@ -140,7 +144,7 @@ func (svr *GRPCServer) Start(_ context.Context) error { log.L().Info("grpc server is listening.", zap.String("addr", lis.Addr().String())) go func() { defer recovery.Recover() - if err := svr.grpcServer.Serve(lis); err != nil { + if err := grpc.svr.Serve(lis); err != nil { log.L().Fatal("grpc failed to serve.", zap.Error(err)) } }() @@ -148,13 +152,19 @@ func (svr *GRPCServer) Start(_ context.Context) error { } // Stop stops the GRPC server -func (svr *GRPCServer) Stop(_ context.Context) error { - svr.grpcServer.Stop() +func (grpc *GRPCServer) Stop(_ context.Context) error { + grpc.svr.Stop() return nil } +func newGRPCHandler(core CoreService) *gRPCHandler { + return &gRPCHandler{ + coreService: core, + } +} + // SuggestGasPrice suggests gas price -func (svr *GRPCServer) SuggestGasPrice(ctx context.Context, in *iotexapi.SuggestGasPriceRequest) (*iotexapi.SuggestGasPriceResponse, error) { +func (svr *gRPCHandler) SuggestGasPrice(ctx context.Context, in *iotexapi.SuggestGasPriceRequest) (*iotexapi.SuggestGasPriceResponse, error) { suggestPrice, err := svr.coreService.SuggestGasPrice() if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -163,7 +173,7 @@ func (svr *GRPCServer) SuggestGasPrice(ctx context.Context, in *iotexapi.Suggest } // GetAccount returns the metadata of an account -func (svr *GRPCServer) GetAccount(ctx context.Context, in *iotexapi.GetAccountRequest) (*iotexapi.GetAccountResponse, error) { +func (svr *gRPCHandler) GetAccount(ctx context.Context, in *iotexapi.GetAccountRequest) (*iotexapi.GetAccountResponse, error) { span := tracer.SpanFromContext(ctx) defer span.End() addr, err := address.FromString(in.Address) @@ -183,7 +193,7 @@ func (svr *GRPCServer) GetAccount(ctx context.Context, in *iotexapi.GetAccountRe } // GetActions returns actions -func (svr *GRPCServer) GetActions(ctx context.Context, in *iotexapi.GetActionsRequest) (*iotexapi.GetActionsResponse, error) { +func (svr *gRPCHandler) GetActions(ctx context.Context, in *iotexapi.GetActionsRequest) (*iotexapi.GetActionsResponse, error) { var ( ret []*iotexapi.ActionInfo err error @@ -279,7 +289,7 @@ func actionsInBlock(blk *block.Block, receipts []*action.Receipt, start, count u } // GetBlockMetas returns block metadata -func (svr *GRPCServer) GetBlockMetas(ctx context.Context, in *iotexapi.GetBlockMetasRequest) (*iotexapi.GetBlockMetasResponse, error) { +func (svr *gRPCHandler) GetBlockMetas(ctx context.Context, in *iotexapi.GetBlockMetasRequest) (*iotexapi.GetBlockMetasResponse, error) { var ( ret []*iotextypes.BlockMeta err error @@ -306,7 +316,7 @@ func (svr *GRPCServer) GetBlockMetas(ctx context.Context, in *iotexapi.GetBlockM } // GetChainMeta returns blockchain metadata -func (svr *GRPCServer) GetChainMeta(ctx context.Context, in *iotexapi.GetChainMetaRequest) (*iotexapi.GetChainMetaResponse, error) { +func (svr *gRPCHandler) GetChainMeta(ctx context.Context, in *iotexapi.GetChainMetaRequest) (*iotexapi.GetChainMetaResponse, error) { chainMeta, syncStatus, err := svr.coreService.ChainMeta() if err != nil { return nil, err @@ -315,7 +325,7 @@ func (svr *GRPCServer) GetChainMeta(ctx context.Context, in *iotexapi.GetChainMe } // GetServerMeta gets the server metadata -func (svr *GRPCServer) GetServerMeta(ctx context.Context, in *iotexapi.GetServerMetaRequest) (*iotexapi.GetServerMetaResponse, error) { +func (svr *gRPCHandler) GetServerMeta(ctx context.Context, in *iotexapi.GetServerMetaRequest) (*iotexapi.GetServerMetaResponse, error) { packageVersion, packageCommitID, gitStatus, goVersion, buildTime := svr.coreService.ServerMeta() return &iotexapi.GetServerMetaResponse{ServerMeta: &iotextypes.ServerMeta{ PackageVersion: packageVersion, @@ -327,7 +337,7 @@ func (svr *GRPCServer) GetServerMeta(ctx context.Context, in *iotexapi.GetServer } // SendAction is the API to send an action to blockchain. -func (svr *GRPCServer) SendAction(ctx context.Context, in *iotexapi.SendActionRequest) (*iotexapi.SendActionResponse, error) { +func (svr *gRPCHandler) SendAction(ctx context.Context, in *iotexapi.SendActionRequest) (*iotexapi.SendActionResponse, error) { span := tracer.SpanFromContext(ctx) // tags output span.SetAttributes(attribute.String("actType", fmt.Sprintf("%T", in.GetAction().GetCore()))) @@ -356,7 +366,7 @@ func (svr *GRPCServer) SendAction(ctx context.Context, in *iotexapi.SendActionRe } // GetReceiptByAction gets receipt with corresponding action hash -func (svr *GRPCServer) GetReceiptByAction(ctx context.Context, in *iotexapi.GetReceiptByActionRequest) (*iotexapi.GetReceiptByActionResponse, error) { +func (svr *gRPCHandler) GetReceiptByAction(ctx context.Context, in *iotexapi.GetReceiptByActionRequest) (*iotexapi.GetReceiptByActionResponse, error) { actHash, err := hash.HexStringToHash256(in.ActionHash) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -379,7 +389,7 @@ func (svr *GRPCServer) GetReceiptByAction(ctx context.Context, in *iotexapi.GetR } // ReadContract reads the state in a contract address specified by the slot -func (svr *GRPCServer) ReadContract(ctx context.Context, in *iotexapi.ReadContractRequest) (*iotexapi.ReadContractResponse, error) { +func (svr *gRPCHandler) ReadContract(ctx context.Context, in *iotexapi.ReadContractRequest) (*iotexapi.ReadContractResponse, error) { from := in.CallerAddress if from == action.EmptyAddress { from = address.ZeroAddress @@ -405,12 +415,12 @@ func (svr *GRPCServer) ReadContract(ctx context.Context, in *iotexapi.ReadContra } // ReadState reads state on blockchain -func (svr *GRPCServer) ReadState(ctx context.Context, in *iotexapi.ReadStateRequest) (*iotexapi.ReadStateResponse, error) { +func (svr *gRPCHandler) ReadState(ctx context.Context, in *iotexapi.ReadStateRequest) (*iotexapi.ReadStateResponse, error) { return svr.coreService.ReadState(string(in.ProtocolID), in.GetHeight(), in.MethodName, in.Arguments) } // EstimateGasForAction estimates gas for action -func (svr *GRPCServer) EstimateGasForAction(ctx context.Context, in *iotexapi.EstimateGasForActionRequest) (*iotexapi.EstimateGasForActionResponse, error) { +func (svr *gRPCHandler) EstimateGasForAction(ctx context.Context, in *iotexapi.EstimateGasForActionRequest) (*iotexapi.EstimateGasForActionResponse, error) { estimateGas, err := svr.coreService.EstimateGasForAction(ctx, in.Action) if err != nil { return nil, err @@ -419,7 +429,7 @@ func (svr *GRPCServer) EstimateGasForAction(ctx context.Context, in *iotexapi.Es } // EstimateActionGasConsumption estimate gas consume for action without signature -func (svr *GRPCServer) EstimateActionGasConsumption(ctx context.Context, in *iotexapi.EstimateActionGasConsumptionRequest) (*iotexapi.EstimateActionGasConsumptionResponse, error) { +func (svr *gRPCHandler) EstimateActionGasConsumption(ctx context.Context, in *iotexapi.EstimateActionGasConsumptionRequest) (*iotexapi.EstimateActionGasConsumptionResponse, error) { if in.GetExecution() != nil { callerAddr, err := address.FromString(in.GetCallerAddress()) if err != nil { @@ -508,7 +518,7 @@ func (svr *GRPCServer) EstimateActionGasConsumption(ctx context.Context, in *iot } // GetEpochMeta gets epoch metadata -func (svr *GRPCServer) GetEpochMeta(ctx context.Context, in *iotexapi.GetEpochMetaRequest) (*iotexapi.GetEpochMetaResponse, error) { +func (svr *gRPCHandler) GetEpochMeta(ctx context.Context, in *iotexapi.GetEpochMetaRequest) (*iotexapi.GetEpochMetaResponse, error) { epochData, numBlks, blockProducersInfo, err := svr.coreService.EpochMeta(in.EpochNumber) if err != nil { return nil, err @@ -521,7 +531,7 @@ func (svr *GRPCServer) GetEpochMeta(ctx context.Context, in *iotexapi.GetEpochMe } // GetRawBlocks gets raw block data -func (svr *GRPCServer) GetRawBlocks(ctx context.Context, in *iotexapi.GetRawBlocksRequest) (*iotexapi.GetRawBlocksResponse, error) { +func (svr *gRPCHandler) GetRawBlocks(ctx context.Context, in *iotexapi.GetRawBlocksRequest) (*iotexapi.GetRawBlocksResponse, error) { ret, err := svr.coreService.RawBlocks(in.StartHeight, in.Count, in.WithReceipts, in.WithTransactionLogs) if err != nil { return nil, err @@ -530,7 +540,7 @@ func (svr *GRPCServer) GetRawBlocks(ctx context.Context, in *iotexapi.GetRawBloc } // GetLogs get logs filtered by contract address and topics -func (svr *GRPCServer) GetLogs(ctx context.Context, in *iotexapi.GetLogsRequest) (*iotexapi.GetLogsResponse, error) { +func (svr *gRPCHandler) GetLogs(ctx context.Context, in *iotexapi.GetLogsRequest) (*iotexapi.GetLogsResponse, error) { if in.GetFilter() == nil { return nil, status.Error(codes.InvalidArgument, "empty filter") } @@ -569,7 +579,7 @@ func toLogPb(lg *action.Log, blkHash hash.Hash256) *iotextypes.Log { } // StreamBlocks streams blocks -func (svr *GRPCServer) StreamBlocks(_ *iotexapi.StreamBlocksRequest, stream iotexapi.APIService_StreamBlocksServer) error { +func (svr *gRPCHandler) StreamBlocks(_ *iotexapi.StreamBlocksRequest, stream iotexapi.APIService_StreamBlocksServer) error { errChan := make(chan error) defer close(errChan) chainListener := svr.coreService.ChainListener() @@ -589,7 +599,7 @@ func (svr *GRPCServer) StreamBlocks(_ *iotexapi.StreamBlocksRequest, stream iote } // StreamLogs streams logs that match the filter condition -func (svr *GRPCServer) StreamLogs(in *iotexapi.StreamLogsRequest, stream iotexapi.APIService_StreamLogsServer) error { +func (svr *gRPCHandler) StreamLogs(in *iotexapi.StreamLogsRequest, stream iotexapi.APIService_StreamLogsServer) error { if in.GetFilter() == nil { return status.Error(codes.InvalidArgument, "empty filter") } @@ -613,7 +623,7 @@ func (svr *GRPCServer) StreamLogs(in *iotexapi.StreamLogsRequest, stream iotexap } // GetElectionBuckets returns the native election buckets. -func (svr *GRPCServer) GetElectionBuckets(ctx context.Context, in *iotexapi.GetElectionBucketsRequest) (*iotexapi.GetElectionBucketsResponse, error) { +func (svr *gRPCHandler) GetElectionBuckets(ctx context.Context, in *iotexapi.GetElectionBucketsRequest) (*iotexapi.GetElectionBucketsResponse, error) { ret, err := svr.coreService.ElectionBuckets(in.GetEpochNum()) if err != nil { return nil, err @@ -622,17 +632,17 @@ func (svr *GRPCServer) GetElectionBuckets(ctx context.Context, in *iotexapi.GetE } // GetEvmTransfersByActionHash returns evm transfers by action hash -func (svr *GRPCServer) GetEvmTransfersByActionHash(ctx context.Context, in *iotexapi.GetEvmTransfersByActionHashRequest) (*iotexapi.GetEvmTransfersByActionHashResponse, error) { +func (svr *gRPCHandler) GetEvmTransfersByActionHash(ctx context.Context, in *iotexapi.GetEvmTransfersByActionHashRequest) (*iotexapi.GetEvmTransfersByActionHashResponse, error) { return nil, status.Error(codes.Unimplemented, "evm transfer index is deprecated, call GetSystemLogByActionHash instead") } // GetEvmTransfersByBlockHeight returns evm transfers by block height -func (svr *GRPCServer) GetEvmTransfersByBlockHeight(ctx context.Context, in *iotexapi.GetEvmTransfersByBlockHeightRequest) (*iotexapi.GetEvmTransfersByBlockHeightResponse, error) { +func (svr *gRPCHandler) GetEvmTransfersByBlockHeight(ctx context.Context, in *iotexapi.GetEvmTransfersByBlockHeightRequest) (*iotexapi.GetEvmTransfersByBlockHeightResponse, error) { return nil, status.Error(codes.Unimplemented, "evm transfer index is deprecated, call GetSystemLogByBlockHeight instead") } // GetTransactionLogByActionHash returns transaction log by action hash -func (svr *GRPCServer) GetTransactionLogByActionHash(ctx context.Context, in *iotexapi.GetTransactionLogByActionHashRequest) (*iotexapi.GetTransactionLogByActionHashResponse, error) { +func (svr *gRPCHandler) GetTransactionLogByActionHash(ctx context.Context, in *iotexapi.GetTransactionLogByActionHashRequest) (*iotexapi.GetTransactionLogByActionHashResponse, error) { ret, err := svr.coreService.TransactionLogByActionHash(in.ActionHash) if err != nil { return nil, err @@ -643,7 +653,7 @@ func (svr *GRPCServer) GetTransactionLogByActionHash(ctx context.Context, in *io } // GetTransactionLogByBlockHeight returns transaction log by block height -func (svr *GRPCServer) GetTransactionLogByBlockHeight(ctx context.Context, in *iotexapi.GetTransactionLogByBlockHeightRequest) (*iotexapi.GetTransactionLogByBlockHeightResponse, error) { +func (svr *gRPCHandler) GetTransactionLogByBlockHeight(ctx context.Context, in *iotexapi.GetTransactionLogByBlockHeightRequest) (*iotexapi.GetTransactionLogByBlockHeightResponse, error) { blockIdentifier, transactionLogs, err := svr.coreService.TransactionLogByBlockHeight(in.BlockHeight) if err != nil { return nil, err @@ -655,7 +665,7 @@ func (svr *GRPCServer) GetTransactionLogByBlockHeight(ctx context.Context, in *i } // GetActPoolActions returns the all Transaction Identifiers in the mempool -func (svr *GRPCServer) GetActPoolActions(ctx context.Context, in *iotexapi.GetActPoolActionsRequest) (*iotexapi.GetActPoolActionsResponse, error) { +func (svr *gRPCHandler) GetActPoolActions(ctx context.Context, in *iotexapi.GetActPoolActionsRequest) (*iotexapi.GetActPoolActionsResponse, error) { acts, err := svr.coreService.ActionsInActPool(in.ActionHashes) if err != nil { return nil, status.Error(codes.NotFound, err.Error()) @@ -670,7 +680,7 @@ func (svr *GRPCServer) GetActPoolActions(ctx context.Context, in *iotexapi.GetAc } // ReadContractStorage reads contract's storage -func (svr *GRPCServer) ReadContractStorage(ctx context.Context, in *iotexapi.ReadContractStorageRequest) (*iotexapi.ReadContractStorageResponse, error) { +func (svr *gRPCHandler) ReadContractStorage(ctx context.Context, in *iotexapi.ReadContractStorageRequest) (*iotexapi.ReadContractStorageResponse, error) { addr, err := address.FromString(in.GetContract()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -683,7 +693,7 @@ func (svr *GRPCServer) ReadContractStorage(ctx context.Context, in *iotexapi.Rea } // TraceTransactionStructLogs get trace transaction struct logs -func (svr *GRPCServer) TraceTransactionStructLogs(ctx context.Context, in *iotexapi.TraceTransactionStructLogsRequest) (*iotexapi.TraceTransactionStructLogsResponse, error) { +func (svr *gRPCHandler) TraceTransactionStructLogs(ctx context.Context, in *iotexapi.TraceTransactionStructLogsRequest) (*iotexapi.TraceTransactionStructLogsResponse, error) { actInfo, err := svr.coreService.Action(util.Remove0xPrefix(in.GetActionHash()), false) if err != nil { return nil, err diff --git a/api/grpcserver_integrity_test.go b/api/grpcserver_integrity_test.go index 5f260803a0..5ea1787bc9 100644 --- a/api/grpcserver_integrity_test.go +++ b/api/grpcserver_integrity_test.go @@ -823,6 +823,7 @@ func TestGrpcServer_GetAccountIntegrity(t *testing.T) { svr, bc, dao, _, _, actPool, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -835,7 +836,7 @@ func TestGrpcServer_GetAccountIntegrity(t *testing.T) { // read contract address request := &iotexapi.GetAccountRequest{Address: contract} - res, err := svr.grpcServer.GetAccount(context.Background(), request) + res, err := grpcHandler.GetAccount(context.Background(), request) require.NoError(err) accountMeta := res.AccountMeta require.Equal(contract, accountMeta.Address) @@ -850,7 +851,7 @@ func TestGrpcServer_GetAccountIntegrity(t *testing.T) { // success for _, test := range _getAccountTests { request := &iotexapi.GetAccountRequest{Address: test.in} - res, err := svr.grpcServer.GetAccount(context.Background(), request) + res, err := grpcHandler.GetAccount(context.Background(), request) require.NoError(err) accountMeta := res.AccountMeta require.Equal(test.address, accountMeta.Address) @@ -862,14 +863,14 @@ func TestGrpcServer_GetAccountIntegrity(t *testing.T) { require.NotZero(res.BlockIdentifier.Hash) } // failure - _, err = svr.grpcServer.GetAccount(context.Background(), &iotexapi.GetAccountRequest{}) + _, err = grpcHandler.GetAccount(context.Background(), &iotexapi.GetAccountRequest{}) require.Error(err) // error account - _, err = svr.grpcServer.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: "io3fn88lge6hyzmruh40cn6l3e49dfkqzqk3lgtq3"}) + _, err = grpcHandler.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: "io3fn88lge6hyzmruh40cn6l3e49dfkqzqk3lgtq3"}) require.Error(err) // success: reward pool - res, err = svr.grpcServer.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: address.RewardingPoolAddr}) + res, err = grpcHandler.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: address.RewardingPoolAddr}) require.NoError(err) require.Equal(address.RewardingPoolAddr, res.AccountMeta.Address) require.Equal("200000000000000000000101000", res.AccountMeta.Balance) @@ -877,7 +878,7 @@ func TestGrpcServer_GetAccountIntegrity(t *testing.T) { require.NotZero(res.BlockIdentifier.Hash) //failure: protocol staking isn't registered - res, err = svr.grpcServer.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: address.StakingBucketPoolAddr}) + res, err = grpcHandler.GetAccount(context.Background(), &iotexapi.GetAccountRequest{Address: address.StakingBucketPoolAddr}) require.Contains(err.Error(), "protocol staking isn't registered") } @@ -886,6 +887,7 @@ func TestGrpcServer_GetActionsIntegrity(t *testing.T) { cfg := newConfig() svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -900,7 +902,7 @@ func TestGrpcServer_GetActionsIntegrity(t *testing.T) { }, } - res, err := svr.grpcServer.GetActions(context.Background(), request) + res, err := grpcHandler.GetActions(context.Background(), request) if test.count == 0 { require.Error(err) } else { @@ -912,11 +914,11 @@ func TestGrpcServer_GetActionsIntegrity(t *testing.T) { } // failure: empty request - _, err = svr.grpcServer.GetActions(context.Background(), &iotexapi.GetActionsRequest{}) + _, err = grpcHandler.GetActions(context.Background(), &iotexapi.GetActionsRequest{}) require.Error(err) // failure: range exceed limit - _, err = svr.grpcServer.GetActions(context.Background(), + _, err = grpcHandler.GetActions(context.Background(), &iotexapi.GetActionsRequest{ Lookup: &iotexapi.GetActionsRequest_ByIndex{ ByIndex: &iotexapi.GetActionsByIndexRequest{ @@ -928,7 +930,7 @@ func TestGrpcServer_GetActionsIntegrity(t *testing.T) { require.Error(err) // failure: start exceed limit - _, err = svr.grpcServer.GetActions(context.Background(), + _, err = grpcHandler.GetActions(context.Background(), &iotexapi.GetActionsRequest{ Lookup: &iotexapi.GetActionsRequest_ByIndex{ ByIndex: &iotexapi.GetActionsByIndexRequest{ @@ -946,6 +948,7 @@ func TestGrpcServer_GetActionIntegrity(t *testing.T) { svr, _, dao, _, _, _, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -959,7 +962,7 @@ func TestGrpcServer_GetActionIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetActions(context.Background(), request) + res, err := grpcHandler.GetActions(context.Background(), request) require.NoError(err) require.Equal(1, len(res.ActionInfo)) act := res.ActionInfo[0] @@ -981,7 +984,7 @@ func TestGrpcServer_GetActionIntegrity(t *testing.T) { } // failure: invalid hash - _, err = svr.grpcServer.GetActions(context.Background(), + _, err = grpcHandler.GetActions(context.Background(), &iotexapi.GetActionsRequest{ Lookup: &iotexapi.GetActionsRequest_ByHash{ ByHash: &iotexapi.GetActionByHashRequest{ @@ -999,6 +1002,7 @@ func TestGrpcServer_GetActionsByAddressIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1013,7 +1017,7 @@ func TestGrpcServer_GetActionsByAddressIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetActions(context.Background(), request) + res, err := grpcHandler.GetActions(context.Background(), request) require.NoError(err) require.Equal(test.numActions, len(res.ActionInfo)) if test.numActions == 0 { @@ -1037,7 +1041,7 @@ func TestGrpcServer_GetActionsByAddressIntegrity(t *testing.T) { }, }, } - prevRes, err := svr.grpcServer.GetActions(context.Background(), request) + prevRes, err := grpcHandler.GetActions(context.Background(), request) require.NoError(err) require.True(prevRes.ActionInfo[len(prevRes.ActionInfo)-1].Timestamp.GetSeconds() <= res.ActionInfo[0].Timestamp.GetSeconds()) } @@ -1050,6 +1054,7 @@ func TestGrpcServer_GetUnconfirmedActionsByAddressIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1064,7 +1069,7 @@ func TestGrpcServer_GetUnconfirmedActionsByAddressIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetActions(context.Background(), request) + res, err := grpcHandler.GetActions(context.Background(), request) if test.count == 0 { require.Error(err) continue @@ -1081,6 +1086,7 @@ func TestGrpcServer_GetActionsByBlockIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1095,7 +1101,7 @@ func TestGrpcServer_GetActionsByBlockIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetActions(context.Background(), request) + res, err := grpcHandler.GetActions(context.Background(), request) if test.count == 0 { require.Error(err) continue @@ -1120,6 +1126,7 @@ func TestGrpcServer_GetBlockMetasIntegrity(t *testing.T) { block.LoadGenesisHash(&cfg.Genesis) svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1133,7 +1140,7 @@ func TestGrpcServer_GetBlockMetasIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetBlockMetas(context.Background(), request) + res, err := grpcHandler.GetBlockMetas(context.Background(), request) if test.count == 0 { require.Error(err) continue @@ -1157,17 +1164,17 @@ func TestGrpcServer_GetBlockMetasIntegrity(t *testing.T) { } } // failure: empty request - _, err = svr.grpcServer.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{}) + _, err = grpcHandler.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{}) require.Error(err) - _, err = svr.grpcServer.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{ + _, err = grpcHandler.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{ Lookup: &iotexapi.GetBlockMetasRequest_ByIndex{ ByIndex: &iotexapi.GetBlockMetasByIndexRequest{Start: 10, Count: 1}, }, }) require.Error(err) - _, err = svr.grpcServer.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{ + _, err = grpcHandler.GetBlockMetas(context.Background(), &iotexapi.GetBlockMetasRequest{ Lookup: &iotexapi.GetBlockMetasRequest_ByHash{ ByHash: &iotexapi.GetBlockMetaByHashRequest{BlkHash: "0xa2e8e0c9cafbe93f2b7f7c9d32534bc6fde95f2185e5f2aaa6bf7ebdf1a6610a"}, }, @@ -1181,6 +1188,7 @@ func TestGrpcServer_GetBlockMetaIntegrity(t *testing.T) { svr, bc, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1196,7 +1204,7 @@ func TestGrpcServer_GetBlockMetaIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetBlockMetas(context.Background(), request) + res, err := grpcHandler.GetBlockMetas(context.Background(), request) require.NoError(err) require.Equal(1, len(res.BlkMetas)) blkPb := res.BlkMetas[0] @@ -1248,6 +1256,7 @@ func TestGrpcServer_GetChainMetaIntegrity(t *testing.T) { cfg.API.TpsWindow = test.tpsWindow svr, _, _, _, registry, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1263,7 +1272,7 @@ func TestGrpcServer_GetChainMetaIntegrity(t *testing.T) { // TODO: create a core service with empty chain to test coreService.bc = mbc } - res, err := svr.grpcServer.GetChainMeta(context.Background(), &iotexapi.GetChainMetaRequest{}) + res, err := grpcHandler.GetChainMeta(context.Background(), &iotexapi.GetChainMetaRequest{}) require.NoError(err) chainMetaPb := res.ChainMeta require.Equal(test.height, chainMetaPb.Height) @@ -1281,6 +1290,7 @@ func TestGrpcServer_SendActionIntegrity(t *testing.T) { cfg.Genesis.MidwayBlockHeight = 10 svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1295,7 +1305,7 @@ func TestGrpcServer_SendActionIntegrity(t *testing.T) { for i, test := range _sendActionTests { request := &iotexapi.SendActionRequest{Action: test.actionPb} - res, err := svr.grpcServer.SendAction(context.Background(), request) + res, err := grpcHandler.SendAction(context.Background(), request) require.NoError(err) require.Equal(i+1, broadcastHandlerCount) require.Equal(test.actionHash, res.ActionHash) @@ -1360,11 +1370,12 @@ func TestGrpcServer_SendActionIntegrity(t *testing.T) { request := &iotexapi.SendActionRequest{Action: test.action} svr, _, _, _, _, _, file, err := createServerV2(test.cfg(), true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(file) }() - _, err = svr.grpcServer.SendAction(ctx, request) + _, err = grpcHandler.SendAction(ctx, request) require.Contains(err.Error(), test.err) } } @@ -1375,11 +1386,12 @@ func TestGrpcServer_StreamLogsIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - err = svr.grpcServer.StreamLogs(&iotexapi.StreamLogsRequest{}, nil) + err = grpcHandler.StreamLogs(&iotexapi.StreamLogsRequest{}, nil) require.Error(err) } @@ -1389,13 +1401,14 @@ func TestGrpcServer_GetReceiptByActionIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() for _, test := range _getReceiptByActionTests { request := &iotexapi.GetReceiptByActionRequest{ActionHash: test.in} - res, err := svr.grpcServer.GetReceiptByAction(context.Background(), request) + res, err := grpcHandler.GetReceiptByAction(context.Background(), request) require.NoError(err) receiptPb := res.ReceiptInfo.Receipt require.Equal(test.status, receiptPb.Status) @@ -1404,10 +1417,10 @@ func TestGrpcServer_GetReceiptByActionIntegrity(t *testing.T) { } // failure: empty request - _, err = svr.grpcServer.GetReceiptByAction(context.Background(), &iotexapi.GetReceiptByActionRequest{ActionHash: "0x"}) + _, err = grpcHandler.GetReceiptByAction(context.Background(), &iotexapi.GetReceiptByActionRequest{ActionHash: "0x"}) require.Error(err) // failure: wrong hash - _, err = svr.grpcServer.GetReceiptByAction(context.Background(), &iotexapi.GetReceiptByActionRequest{ActionHash: "b7faffcb8b01fa9f32112155bcb93d714f599eab3178e577e88dafd2140bfc5a"}) + _, err = grpcHandler.GetReceiptByAction(context.Background(), &iotexapi.GetReceiptByActionRequest{ActionHash: "b7faffcb8b01fa9f32112155bcb93d714f599eab3178e577e88dafd2140bfc5a"}) require.Error(err) } @@ -1418,11 +1431,12 @@ func TestGrpcServer_GetServerMetaIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - resProto, err := svr.grpcServer.GetServerMeta(context.Background(), &iotexapi.GetServerMetaRequest{}) + resProto, err := grpcHandler.GetServerMeta(context.Background(), &iotexapi.GetServerMetaRequest{}) res := resProto.GetServerMeta() require.Equal(res.BuildTime, version.BuildTime) require.Equal(res.GoVersion, version.GoVersion) @@ -1437,6 +1451,7 @@ func TestGrpcServer_ReadContractIntegrity(t *testing.T) { svr, _, dao, indexer, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1455,7 +1470,7 @@ func TestGrpcServer_ReadContractIntegrity(t *testing.T) { GasPrice: big.NewInt(unit.Qev).String(), } - res, err := svr.grpcServer.ReadContract(context.Background(), request) + res, err := grpcHandler.ReadContract(context.Background(), request) require.NoError(err) require.Equal(test.retValue, res.Data) require.EqualValues(1, res.Receipt.Status) @@ -1472,10 +1487,11 @@ func TestGrpcServer_SuggestGasPriceIntegrity(t *testing.T) { cfg.API.GasStation.DefaultGas = test.defaultGasPrice svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - res, err := svr.grpcServer.SuggestGasPrice(context.Background(), &iotexapi.SuggestGasPriceRequest{}) + res, err := grpcHandler.SuggestGasPrice(context.Background(), &iotexapi.SuggestGasPriceRequest{}) require.NoError(err) require.Equal(test.suggestedGasPrice, res.GasPrice) } @@ -1487,6 +1503,7 @@ func TestGrpcServer_EstimateGasForActionIntegrity(t *testing.T) { svr, _, dao, indexer, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1500,7 +1517,7 @@ func TestGrpcServer_EstimateGasForActionIntegrity(t *testing.T) { require.NoError(err) request := &iotexapi.EstimateGasForActionRequest{Action: act.Proto()} - res, err := svr.grpcServer.EstimateGasForAction(context.Background(), request) + res, err := grpcHandler.EstimateGasForAction(context.Background(), request) require.NoError(err) require.Equal(test.estimatedGas, res.Gas) } @@ -1511,6 +1528,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { cfg := newConfig() svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -1527,7 +1545,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err := svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err := grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(286579), res.Gas) @@ -1540,7 +1558,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1566,7 +1584,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1579,7 +1597,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1592,7 +1610,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1605,7 +1623,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1618,7 +1636,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1631,7 +1649,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1644,7 +1662,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1657,7 +1675,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10300), res.Gas) @@ -1670,7 +1688,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(0).String(), } - res, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10000), res.Gas) @@ -1679,7 +1697,7 @@ func TestGrpcServer_EstimateActionGasConsumptionIntegrity(t *testing.T) { Action: nil, CallerAddress: identityset.Address(0).String(), } - _, err = svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + _, err = grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.Error(err) } @@ -1689,12 +1707,13 @@ func TestGrpcServer_ReadUnclaimedBalanceIntegrity(t *testing.T) { cfg.Consensus.Scheme = config.RollDPoSScheme svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() for _, test := range _readUnclaimedBalanceTests { - out, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + out, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), Arguments: [][]byte{[]byte(test.addr)}, @@ -1716,11 +1735,12 @@ func TestGrpcServer_TotalBalanceIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - out, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + out, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte("rewarding"), MethodName: []byte("TotalBalance"), Arguments: nil, @@ -1737,11 +1757,12 @@ func TestGrpcServer_AvailableBalanceIntegrity(t *testing.T) { cfg.Consensus.Scheme = config.RollDPoSScheme svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - out, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + out, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte("rewarding"), MethodName: []byte("AvailableBalance"), Arguments: nil, @@ -1806,12 +1827,13 @@ func TestGrpcServer_ReadCandidatesByEpochIntegrity(t *testing.T) { } svr, _, _, _, registry, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() require.NoError(pol.ForceRegister(registry)) - res, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + res, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), Arguments: [][]byte{[]byte(strconv.FormatUint(test.epoch, 10))}, @@ -1878,11 +1900,12 @@ func TestGrpcServer_ReadBlockProducersByEpochIntegrity(t *testing.T) { } svr, _, _, _, registry, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() require.NoError(pol.ForceRegister(registry)) - res, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + res, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), Arguments: [][]byte{[]byte(strconv.FormatUint(test.epoch, 10))}, @@ -1948,12 +1971,13 @@ func TestGrpcServer_ReadActiveBlockProducersByEpochIntegrity(t *testing.T) { } svr, _, _, _, registry, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() require.NoError(pol.ForceRegister(registry)) - res, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + res, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), Arguments: [][]byte{[]byte(strconv.FormatUint(test.epoch, 10))}, @@ -1972,10 +1996,11 @@ func TestGrpcServer_ReadRollDPoSMetaIntegrity(t *testing.T) { for _, test := range _readRollDPoSMetaTests { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - res, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + res, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), }) @@ -1993,10 +2018,11 @@ func TestGrpcServer_ReadEpochCtxIntegrity(t *testing.T) { for _, test := range _readEpochCtxTests { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - res, err := svr.grpcServer.ReadState(context.Background(), &iotexapi.ReadStateRequest{ + res, err := grpcHandler.ReadState(context.Background(), &iotexapi.ReadStateRequest{ ProtocolID: []byte(test.protocolID), MethodName: []byte(test.methodName), Arguments: [][]byte{[]byte(strconv.FormatUint(test.argument, 10))}, @@ -2016,6 +2042,7 @@ func TestGrpcServer_GetEpochMetaIntegrity(t *testing.T) { svr, _, _, _, registry, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2113,7 +2140,7 @@ func TestGrpcServer_GetEpochMetaIntegrity(t *testing.T) { coreService, ok := svr.core.(*coreService) require.True(ok) coreService.readCache.Clear() - res, err := svr.grpcServer.GetEpochMeta(context.Background(), &iotexapi.GetEpochMetaRequest{EpochNumber: test.EpochNumber}) + res, err := grpcHandler.GetEpochMeta(context.Background(), &iotexapi.GetEpochMetaRequest{EpochNumber: test.EpochNumber}) require.NoError(err) require.Equal(test.epochData.Num, res.EpochData.Num) require.Equal(test.epochData.Height, res.EpochData.Height) @@ -2137,7 +2164,7 @@ func TestGrpcServer_GetEpochMetaIntegrity(t *testing.T) { } // failure: epoch number - _, err = svr.grpcServer.GetEpochMeta(context.Background(), &iotexapi.GetEpochMetaRequest{EpochNumber: 0}) + _, err = grpcHandler.GetEpochMeta(context.Background(), &iotexapi.GetEpochMetaRequest{EpochNumber: 0}) require.Error(err) } @@ -2147,6 +2174,7 @@ func TestGrpcServer_GetRawBlocksIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2157,7 +2185,7 @@ func TestGrpcServer_GetRawBlocksIntegrity(t *testing.T) { Count: test.count, WithReceipts: test.withReceipts, } - res, err := svr.grpcServer.GetRawBlocks(context.Background(), request) + res, err := grpcHandler.GetRawBlocks(context.Background(), request) require.NoError(err) blkInfos := res.Blocks require.Equal(test.numBlks, len(blkInfos)) @@ -2183,7 +2211,7 @@ func TestGrpcServer_GetRawBlocksIntegrity(t *testing.T) { } // failure: invalid count - _, err = svr.grpcServer.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ + _, err = grpcHandler.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ StartHeight: 1, Count: 0, WithReceipts: true, @@ -2191,7 +2219,7 @@ func TestGrpcServer_GetRawBlocksIntegrity(t *testing.T) { require.Error(err) // failure: invalid startHeight - _, err = svr.grpcServer.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ + _, err = grpcHandler.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ StartHeight: 1000000, Count: 10, WithReceipts: true, @@ -2199,7 +2227,7 @@ func TestGrpcServer_GetRawBlocksIntegrity(t *testing.T) { require.Error(err) // failure: invalid endHeight - _, err = svr.grpcServer.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ + _, err = grpcHandler.GetRawBlocks(context.Background(), &iotexapi.GetRawBlocksRequest{ StartHeight: 3, Count: 1000, WithReceipts: true, @@ -2214,6 +2242,7 @@ func TestGrpcServer_GetLogsIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2231,7 +2260,7 @@ func TestGrpcServer_GetLogsIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetLogs(context.Background(), request) + res, err := grpcHandler.GetLogs(context.Background(), request) require.NoError(err) logs := res.Logs require.Equal(test.numLogs, len(logs)) @@ -2250,20 +2279,20 @@ func TestGrpcServer_GetLogsIntegrity(t *testing.T) { }, }, } - res, err := svr.grpcServer.GetLogs(context.Background(), request) + res, err := grpcHandler.GetLogs(context.Background(), request) require.NoError(err) logs := res.Logs require.Equal(1, len(logs)) } // failure: empty request - _, err = svr.grpcServer.GetLogs(context.Background(), &iotexapi.GetLogsRequest{ + _, err = grpcHandler.GetLogs(context.Background(), &iotexapi.GetLogsRequest{ Filter: &iotexapi.LogsFilter{}, }) require.Error(err) // failure: empty filter - _, err = svr.grpcServer.GetLogs(context.Background(), &iotexapi.GetLogsRequest{}) + _, err = grpcHandler.GetLogs(context.Background(), &iotexapi.GetLogsRequest{}) require.Error(err) } @@ -2273,6 +2302,7 @@ func TestGrpcServer_GetElectionBucketsIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2281,7 +2311,7 @@ func TestGrpcServer_GetElectionBucketsIntegrity(t *testing.T) { request := &iotexapi.GetElectionBucketsRequest{ EpochNum: 0, } - _, err = svr.grpcServer.GetElectionBuckets(context.Background(), request) + _, err = grpcHandler.GetElectionBuckets(context.Background(), request) require.Error(err) } @@ -2307,6 +2337,7 @@ func TestGrpcServer_GetTransactionLogByActionHashIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2314,7 +2345,7 @@ func TestGrpcServer_GetTransactionLogByActionHashIntegrity(t *testing.T) { request := &iotexapi.GetTransactionLogByActionHashRequest{ ActionHash: hex.EncodeToString(hash.ZeroHash256[:]), } - _, err = svr.grpcServer.GetTransactionLogByActionHash(context.Background(), request) + _, err = grpcHandler.GetTransactionLogByActionHash(context.Background(), request) require.Error(err) sta, ok := status.FromError(err) require.Equal(true, ok) @@ -2322,7 +2353,7 @@ func TestGrpcServer_GetTransactionLogByActionHashIntegrity(t *testing.T) { for h, log := range _implicitLogs { request.ActionHash = hex.EncodeToString(h[:]) - res, err := svr.grpcServer.GetTransactionLogByActionHash(context.Background(), request) + res, err := grpcHandler.GetTransactionLogByActionHash(context.Background(), request) require.NoError(err) require.Equal(log.Proto(), res.TransactionLog) } @@ -2342,6 +2373,7 @@ func TestGrpcServer_GetEvmTransfersByBlockHeightIntegrity(t *testing.T) { svr, _, _, _, _, _, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2349,7 +2381,7 @@ func TestGrpcServer_GetEvmTransfersByBlockHeightIntegrity(t *testing.T) { request := &iotexapi.GetTransactionLogByBlockHeightRequest{} for _, test := range _getImplicitLogByBlockHeightTest { request.BlockHeight = test.height - res, err := svr.grpcServer.GetTransactionLogByBlockHeight(context.Background(), request) + res, err := grpcHandler.GetTransactionLogByBlockHeight(context.Background(), request) if test.code != codes.OK { require.Error(err) sta, ok := status.FromError(err) @@ -2376,11 +2408,12 @@ func TestGrpcServer_GetActPoolActionsIntegrity(t *testing.T) { svr, _, _, _, _, actPool, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() - res, err := svr.grpcServer.GetActPoolActions(ctx, &iotexapi.GetActPoolActionsRequest{}) + res, err := grpcHandler.GetActPoolActions(ctx, &iotexapi.GetActPoolActionsRequest{}) require.NoError(err) require.Equal(len(actPool.PendingActionMap()[identityset.Address(27).String()]), len(res.Actions)) @@ -2406,24 +2439,24 @@ func TestGrpcServer_GetActPoolActionsIntegrity(t *testing.T) { require.NoError(err) requests = append(requests, hex.EncodeToString(h1[:])) - res, err = svr.grpcServer.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{}) + res, err = grpcHandler.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{}) require.NoError(err) require.Equal(len(actPool.PendingActionMap()[identityset.Address(27).String()]), len(res.Actions)) - res, err = svr.grpcServer.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: requests}) + res, err = grpcHandler.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: requests}) require.NoError(err) require.Equal(1, len(res.Actions)) h2, err := tsf2.Hash() require.NoError(err) requests = append(requests, hex.EncodeToString(h2[:])) - res, err = svr.grpcServer.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: requests}) + res, err = grpcHandler.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: requests}) require.NoError(err) require.Equal(2, len(res.Actions)) h3, err := tsf3.Hash() require.NoError(err) - _, err = svr.grpcServer.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: []string{hex.EncodeToString(h3[:])}}) + _, err = grpcHandler.GetActPoolActions(context.Background(), &iotexapi.GetActPoolActionsRequest{ActionHashes: []string{hex.EncodeToString(h3[:])}}) require.Error(err) } @@ -2433,6 +2466,7 @@ func TestGrpcServer_GetEstimateGasSpecialIntegrity(t *testing.T) { svr, bc, dao, _, _, actPool, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2456,7 +2490,7 @@ func TestGrpcServer_GetEstimateGasSpecialIntegrity(t *testing.T) { }, CallerAddress: identityset.Address(13).String(), } - res, err := svr.grpcServer.EstimateActionGasConsumption(context.Background(), request) + res, err := grpcHandler.EstimateActionGasConsumption(context.Background(), request) require.NoError(err) require.Equal(uint64(10777), res.Gas) } @@ -2551,12 +2585,13 @@ func TestChainlinkErrIntegrity(t *testing.T) { t.Run(strconv.Itoa(i), func(t *testing.T) { svr, _, _, _, _, _, file, err := createServerV2(test.cfg(), true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(file) }() for _, action := range test.actions { - _, err = svr.grpcServer.SendAction(context.Background(), &iotexapi.SendActionRequest{Action: action}) + _, err = grpcHandler.SendAction(context.Background(), &iotexapi.SendActionRequest{Action: action}) if err != nil { break } @@ -2574,6 +2609,7 @@ func TestGrpcServer_TraceTransactionStructLogsIntegrity(t *testing.T) { svr, bc, _, _, _, actPool, bfIndexFile, err := createServerV2(cfg, true) require.NoError(err) + grpcHandler := newGRPCHandler(svr.core) defer func() { testutil.CleanupPath(bfIndexFile) }() @@ -2581,12 +2617,12 @@ func TestGrpcServer_TraceTransactionStructLogsIntegrity(t *testing.T) { request := &iotexapi.TraceTransactionStructLogsRequest{ ActionHash: hex.EncodeToString(hash.ZeroHash256[:]), } - _, err = svr.grpcServer.TraceTransactionStructLogs(context.Background(), request) + _, err = grpcHandler.TraceTransactionStructLogs(context.Background(), request) require.Error(err) //unsupport type request.ActionHash = hex.EncodeToString(_transferHash1[:]) - _, err = svr.grpcServer.TraceTransactionStructLogs(context.Background(), request) + _, err = grpcHandler.TraceTransactionStructLogs(context.Background(), request) require.Error(err) // deploy a contract @@ -2604,7 +2640,7 @@ func TestGrpcServer_TraceTransactionStructLogsIntegrity(t *testing.T) { actPool.Reset() ex1Hash, _ := ex1.Hash() request.ActionHash = hex.EncodeToString(ex1Hash[:]) - ret, err := svr.grpcServer.TraceTransactionStructLogs(context.Background(), request) + ret, err := grpcHandler.TraceTransactionStructLogs(context.Background(), request) require.NoError(err) require.Equal(len(ret.StructLogs), 17) log := ret.StructLogs[0] diff --git a/api/grpcserver_test.go b/api/grpcserver_test.go index 084a65f390..e91dbeedaa 100644 --- a/api/grpcserver_test.go +++ b/api/grpcserver_test.go @@ -20,7 +20,6 @@ import ( "github.com/iotexproject/iotex-core/pkg/version" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice" - "github.com/iotexproject/iotex-core/testutil" ) func TestGrpcServer_GetAccount(t *testing.T) { @@ -64,7 +63,7 @@ func TestGrpcServer_SendAction(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() core := mock_apicoreservice.NewMockCoreService(ctrl) - grpcSvr := NewGRPCServer(core, testutil.RandomPort()) + grpcSvr := newGRPCHandler(core) for _, test := range _sendActionTests { core.EXPECT().EVMNetworkID().Return(uint32(1)) @@ -97,7 +96,7 @@ func TestGrpcServer_SuggestGasPrice(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() core := mock_apicoreservice.NewMockCoreService(ctrl) - grpcSvr := NewGRPCServer(core, testutil.RandomPort()) + grpcSvr := newGRPCHandler(core) core.EXPECT().SuggestGasPrice().Return(uint64(1), nil) res, err := grpcSvr.SuggestGasPrice(context.Background(), &iotexapi.SuggestGasPriceRequest{}) @@ -114,7 +113,7 @@ func TestGrpcServer_EstimateGasForAction(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() core := mock_apicoreservice.NewMockCoreService(ctrl) - grpcSvr := NewGRPCServer(core, testutil.RandomPort()) + grpcSvr := newGRPCHandler(core) core.EXPECT().EstimateGasForAction(gomock.Any(), gomock.Any()).Return(uint64(10000), nil) resp, err := grpcSvr.EstimateGasForAction(context.Background(), &iotexapi.EstimateGasForActionRequest{Action: getAction()}) diff --git a/api/http.go b/api/http.go index 7cf73cc94e..b7d67824d9 100644 --- a/api/http.go +++ b/api/http.go @@ -13,15 +13,21 @@ import ( "github.com/iotexproject/iotex-core/pkg/log" ) -// HTTPServer handles requests from http protocol -type HTTPServer struct { - svr *http.Server - msgHandler Web3Handler -} +type ( + // HTTPServer crates a http server + HTTPServer struct { + svr *http.Server + } + + // hTTPHandler handles requests from http protocol + hTTPHandler struct { + msgHandler Web3Handler + } +) // NewHTTPServer creates a new http server // TODO: move timeout into config -func NewHTTPServer(route string, port int, handler Web3Handler) *HTTPServer { +func NewHTTPServer(route string, port int, handler http.Handler) *HTTPServer { if port == 0 { return nil } @@ -30,11 +36,9 @@ func NewHTTPServer(route string, port int, handler Web3Handler) *HTTPServer { Addr: ":" + strconv.Itoa(port), WriteTimeout: 30 * time.Second, }, - msgHandler: handler, } - mux := http.NewServeMux() - mux.Handle("/"+route, svr) + mux.Handle("/"+route, handler) svr.svr.Handler = mux return svr } @@ -54,13 +58,20 @@ func (hSvr *HTTPServer) Stop(ctx context.Context) error { return hSvr.svr.Shutdown(ctx) } -func (hSvr *HTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { +// newHTTPHandler creates a new http handler +func newHTTPHandler(web3Handler Web3Handler) *hTTPHandler { + return &hTTPHandler{ + msgHandler: web3Handler, + } +} + +func (handler *hTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { w.WriteHeader(http.StatusMethodNotAllowed) return } - if err := hSvr.msgHandler.HandlePOSTReq(req.Body, + if err := handler.msgHandler.HandlePOSTReq(req.Body, apitypes.NewResponseWriter( func(resp interface{}) error { w.Header().Set("Access-Control-Allow-Origin", "*") diff --git a/api/http_test.go b/api/http_test.go index 6a49f24233..23b7824270 100644 --- a/api/http_test.go +++ b/api/http_test.go @@ -21,7 +21,7 @@ func TestServeHTTP(t *testing.T) { defer ctrl.Finish() handler := mock_web3server.NewMockWeb3Handler(ctrl) handler.EXPECT().HandlePOSTReq(gomock.Any(), gomock.Any()).Return(nil) - svr := NewHTTPServer("", testutil.RandomPort(), handler) + svr := newHTTPHandler(handler) t.Run("WrongHTTPMethod", func(t *testing.T) { req, _ := http.NewRequest(http.MethodGet, "http://url.com", nil) @@ -45,7 +45,7 @@ func TestServerStartStop(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() handler := mock_web3server.NewMockWeb3Handler(ctrl) - svr := NewHTTPServer("", testutil.RandomPort(), handler) + svr := NewHTTPServer("", testutil.RandomPort(), newHTTPHandler(handler)) err := svr.Start(context.Background()) require.NoError(err) diff --git a/api/serverV2.go b/api/serverV2.go index 7d48a9df97..2a8cc05baa 100644 --- a/api/serverV2.go +++ b/api/serverV2.go @@ -29,7 +29,7 @@ type ServerV2 struct { core CoreService grpcServer *GRPCServer httpSvr *HTTPServer - websocketSvr *WebsocketServer + websocketSvr *HTTPServer tracer *tracesdk.TracerProvider } @@ -61,11 +61,12 @@ func NewServerV2( if err != nil { return nil, errors.Wrapf(err, "cannot config tracer provider") } + return &ServerV2{ core: coreAPI, grpcServer: NewGRPCServer(coreAPI, cfg.GRPCPort), - httpSvr: NewHTTPServer("", cfg.HTTPPort, web3Handler), - websocketSvr: NewWebSocketServer("", cfg.WebSocketPort, web3Handler), + httpSvr: NewHTTPServer("", cfg.HTTPPort, newHTTPHandler(web3Handler)), + websocketSvr: NewHTTPServer("", cfg.WebSocketPort, NewWebsocketHandler(web3Handler)), tracer: tp, }, nil } diff --git a/api/serverV2_test.go b/api/serverV2_test.go index 03a88cac87..0727ce1cd9 100644 --- a/api/serverV2_test.go +++ b/api/serverV2_test.go @@ -23,8 +23,8 @@ func TestServerV2(t *testing.T) { svr := &ServerV2{ core: core, grpcServer: NewGRPCServer(core, testutil.RandomPort()), - httpSvr: NewHTTPServer("", testutil.RandomPort(), web3Handler), - websocketSvr: NewWebSocketServer("", testutil.RandomPort(), web3Handler), + httpSvr: NewHTTPServer("", testutil.RandomPort(), newHTTPHandler(web3Handler)), + websocketSvr: NewHTTPServer("", testutil.RandomPort(), NewWebsocketHandler(web3Handler)), } ctx := context.Background() diff --git a/api/web3server_test.go b/api/web3server_test.go index be7ba43c00..38b4897f61 100644 --- a/api/web3server_test.go +++ b/api/web3server_test.go @@ -16,7 +16,6 @@ import ( "github.com/tidwall/gjson" "github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice" - "github.com/iotexproject/iotex-core/testutil" ) func TestGetWeb3Reqs(t *testing.T) { @@ -73,8 +72,8 @@ func TestHandlePost(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() core := mock_apicoreservice.NewMockCoreService(ctrl) - svr := NewHTTPServer("", testutil.RandomPort(), NewWeb3Handler(core, "")) - getServerResp := func(svr *HTTPServer, req *http.Request) *httptest.ResponseRecorder { + svr := newHTTPHandler(NewWeb3Handler(core, "")) + getServerResp := func(svr *hTTPHandler, req *http.Request) *httptest.ResponseRecorder { req.Header.Set("Content-Type", "application/json") resp := httptest.NewRecorder() svr.ServeHTTP(resp, req) diff --git a/api/websocket.go b/api/websocket.go index 30029d97b2..466b78f0e6 100644 --- a/api/websocket.go +++ b/api/websocket.go @@ -3,7 +3,6 @@ package api import ( "context" "net/http" - "strconv" "time" "github.com/gorilla/websocket" @@ -27,9 +26,8 @@ const ( maxMessageSize = 15 * 1024 * 1024 ) -// WebsocketServer handles requests from websocket protocol -type WebsocketServer struct { - svr *http.Server +// WebsocketHandler handles requests from websocket protocol +type WebsocketHandler struct { msgHandler Web3Handler } @@ -38,39 +36,14 @@ var upgrader = websocket.Upgrader{ WriteBufferSize: 1024, } -// NewWebSocketServer creates a new websocket server -func NewWebSocketServer(route string, port int, handler Web3Handler) *WebsocketServer { - if port == 0 { - return nil - } - svr := &WebsocketServer{ - svr: &http.Server{ - Addr: ":" + strconv.Itoa(port), - }, - msgHandler: handler, +// NewWebsocketHandler creates a new websocket handler +func NewWebsocketHandler(web3Handler Web3Handler) *WebsocketHandler { + return &WebsocketHandler{ + msgHandler: web3Handler, } - mux := http.NewServeMux() - mux.Handle("/"+route, svr) - svr.svr.Handler = mux - return svr -} - -// Start starts the websocket server -func (wsSvr *WebsocketServer) Start(_ context.Context) error { - go func() { - if err := wsSvr.svr.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.L().Fatal("Node failed to serve.", zap.Error(err)) - } - }() - return nil -} - -// Stop stops the websocket server -func (wsSvr *WebsocketServer) Stop(ctx context.Context) error { - return wsSvr.svr.Shutdown(ctx) } -func (wsSvr *WebsocketServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { +func (wsSvr *WebsocketHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { upgrader.CheckOrigin = func(_ *http.Request) bool { return true } // upgrade this connection to a WebSocket connection @@ -83,7 +56,7 @@ func (wsSvr *WebsocketServer) ServeHTTP(w http.ResponseWriter, req *http.Request wsSvr.handleConnection(ws) } -func (wsSvr *WebsocketServer) handleConnection(ws *websocket.Conn) { +func (wsSvr *WebsocketHandler) handleConnection(ws *websocket.Conn) { defer ws.Close() ws.SetReadDeadline(time.Now().Add(pongWait)) ws.SetReadLimit(maxMessageSize) From 7382ab7a47e18b13dfc7dbe402086c9e61df1db2 Mon Sep 17 00:00:00 2001 From: CoderZhi Date: Fri, 1 Jul 2022 22:08:20 -0700 Subject: [PATCH 24/24] account type with zero init nonce (#3387) * set balance via SubBalance and AddBalance * create account with NewAccount and NewEmptyAccount * refactor state.nonce * skip update nonce and gas for system actions * check nonce value * account type * read state with context * address comments * fix unit test * address comment * address comment Co-authored-by: Haaai <55118568+Liuhaai@users.noreply.github.com> --- action/const.go | 1 + .../protocol/account/accountpb/account.pb.go | 104 +++++++-- .../protocol/account/accountpb/account.proto | 10 +- action/protocol/account/protocol.go | 21 +- action/protocol/account/protocol_test.go | 8 +- action/protocol/account/transfer.go | 37 ++- action/protocol/account/transfer_test.go | 35 +-- action/protocol/account/util/util.go | 101 ++++---- action/protocol/context.go | 100 ++++---- .../protocol/execution/evm/contract_test.go | 14 +- action/protocol/execution/evm/evm.go | 19 +- action/protocol/execution/evm/evm_test.go | 3 +- .../execution/evm/evmstatedbadapter.go | 160 ++++++++----- .../execution/evm/evmstatedbadapter_test.go | 112 ++++++--- action/protocol/execution/protocol_test.go | 25 +- .../testdata-london/basic-token.json | 4 +- .../execution/testdata-london/datacopy.json | 6 +- .../execution/testdata-london/gas-test.json | 4 +- .../testdata-london/mapping-delete.json | 2 +- .../execution/testdata-london/maxtime.json | 4 +- .../testdata-london/reentry-attack.json | 14 +- .../testdata-london/remove-from-array.json | 2 +- .../testdata-london/storage-test.json | 4 +- action/protocol/generic_validator.go | 26 ++- action/protocol/generic_validator_test.go | 41 +++- .../protocol/poll/governance_protocol_test.go | 1 + .../protocol/poll/lifelong_protocol_test.go | 1 + .../protocol/poll/staking_committee_test.go | 1 + action/protocol/poll/util.go | 12 +- action/protocol/rewarding/fund.go | 30 +-- action/protocol/rewarding/protocol.go | 86 +++++-- action/protocol/rewarding/protocol_test.go | 31 ++- action/protocol/rewarding/reward.go | 11 +- action/protocol/staking/handlers.go | 13 +- action/protocol/staking/handlers_test.go | 160 ++++++++----- action/protocol/staking/protocol.go | 11 +- actpool/actpool.go | 46 ++-- actpool/actpool_test.go | 215 ++++++++++-------- actpool/actqueue.go | 9 +- actpool/actqueue_test.go | 10 +- api/coreservice.go | 20 +- api/grpcserver_integrity_test.go | 6 +- api/serverV2_integrity_test.go | 6 +- blockchain/block/validator_test.go | 7 +- blockchain/integrity/benchmark_test.go | 2 +- blockchain/integrity/integrity_test.go | 90 ++++---- blocksync/blocksync_test.go | 14 +- blocksync/buffer_test.go | 4 +- chainservice/builder.go | 2 +- consensus/scheme/rolldpos/rolldpos_test.go | 2 +- .../scheme/rolldpos/roundcalculator_test.go | 2 +- e2etest/bigint_test.go | 26 ++- e2etest/local_test.go | 30 +-- e2etest/local_transfer_test.go | 14 +- e2etest/rewarding_test.go | 17 +- e2etest/staking_test.go | 6 +- gasstation/gasstattion_test.go | 4 +- go.mod | 2 +- go.sum | 4 +- state/account.go | 163 ++++++++++--- state/account_test.go | 44 +++- state/factory/factory_test.go | 81 +++---- state/factory/workingset.go | 13 +- .../internal/client/client_test.go | 1 - 64 files changed, 1316 insertions(+), 738 deletions(-) diff --git a/action/const.go b/action/const.go index 16dcbdfab9..52b6958190 100644 --- a/action/const.go +++ b/action/const.go @@ -16,6 +16,7 @@ var ( ErrChainID = errors.New("invalid chainID") ErrExistedInPool = errors.New("known transaction") ErrReplaceUnderpriced = errors.New("replacement transaction underpriced") + ErrSystemActionNonce = errors.New("invalid system action nonce") ErrNonceTooLow = errors.New("nonce too low") ErrUnderpriced = errors.New("transaction underpriced") ErrNegativeValue = errors.New("negative value") diff --git a/action/protocol/account/accountpb/account.pb.go b/action/protocol/account/accountpb/account.pb.go index 47cb4051b1..762b79fa8c 100644 --- a/action/protocol/account/accountpb/account.pb.go +++ b/action/protocol/account/accountpb/account.pb.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018 IoTeX +// Copyright (c) 2022 IoTeX // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -9,8 +9,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.23.0 -// protoc v3.12.4 +// protoc-gen-go v1.26.0 +// protoc v3.20.1 // source: account.proto package accountpb @@ -29,18 +29,65 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type AccountType int32 + +const ( + AccountType_DEFAULT AccountType = 0 + AccountType_ZERO_NONCE AccountType = 1 +) + +// Enum value maps for AccountType. +var ( + AccountType_name = map[int32]string{ + 0: "DEFAULT", + 1: "ZERO_NONCE", + } + AccountType_value = map[string]int32{ + "DEFAULT": 0, + "ZERO_NONCE": 1, + } +) + +func (x AccountType) Enum() *AccountType { + p := new(AccountType) + *p = x + return p +} + +func (x AccountType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AccountType) Descriptor() protoreflect.EnumDescriptor { + return file_account_proto_enumTypes[0].Descriptor() +} + +func (AccountType) Type() protoreflect.EnumType { + return &file_account_proto_enumTypes[0] +} + +func (x AccountType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AccountType.Descriptor instead. +func (AccountType) EnumDescriptor() ([]byte, []int) { + return file_account_proto_rawDescGZIP(), []int{0} +} + type Account struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // used by state-based model - Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` - Balance string `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - Root []byte `protobuf:"bytes,3,opt,name=root,proto3" json:"root,omitempty"` - CodeHash []byte `protobuf:"bytes,4,opt,name=codeHash,proto3" json:"codeHash,omitempty"` - IsCandidate bool `protobuf:"varint,5,opt,name=isCandidate,proto3" json:"isCandidate,omitempty"` - VotingWeight []byte `protobuf:"bytes,6,opt,name=votingWeight,proto3" json:"votingWeight,omitempty"` + Nonce uint64 `protobuf:"varint,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + Balance string `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` + Root []byte `protobuf:"bytes,3,opt,name=root,proto3" json:"root,omitempty"` + CodeHash []byte `protobuf:"bytes,4,opt,name=codeHash,proto3" json:"codeHash,omitempty"` + IsCandidate bool `protobuf:"varint,5,opt,name=isCandidate,proto3" json:"isCandidate,omitempty"` + VotingWeight []byte `protobuf:"bytes,6,opt,name=votingWeight,proto3" json:"votingWeight,omitempty"` + Type AccountType `protobuf:"varint,7,opt,name=type,proto3,enum=accountpb.AccountType" json:"type,omitempty"` } func (x *Account) Reset() { @@ -117,11 +164,18 @@ func (x *Account) GetVotingWeight() []byte { return nil } +func (x *Account) GetType() AccountType { + if x != nil { + return x.Type + } + return AccountType_DEFAULT +} + var File_account_proto protoreflect.FileDescriptor var file_account_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x62, 0x22, 0xaf, 0x01, 0x0a, 0x07, 0x41, + 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x62, 0x22, 0xdb, 0x01, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, @@ -132,7 +186,17 @@ var file_account_proto_rawDesc = []byte{ 0x69, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x43, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, - 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2a, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x2a, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, + 0x4c, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x4e, 0x4f, 0x4e, + 0x43, 0x45, 0x10, 0x01, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x69, 0x6f, 0x74, 0x65, 0x78, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2f, + 0x69, 0x6f, 0x74, 0x65, 0x78, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } @@ -148,16 +212,19 @@ func file_account_proto_rawDescGZIP() []byte { return file_account_proto_rawDescData } +var file_account_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_account_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_account_proto_goTypes = []interface{}{ - (*Account)(nil), // 0: accountpb.Account + (AccountType)(0), // 0: accountpb.AccountType + (*Account)(nil), // 1: accountpb.Account } var file_account_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 0, // 0: accountpb.Account.type:type_name -> accountpb.AccountType + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_account_proto_init() } @@ -184,13 +251,14 @@ func file_account_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_account_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_account_proto_goTypes, DependencyIndexes: file_account_proto_depIdxs, + EnumInfos: file_account_proto_enumTypes, MessageInfos: file_account_proto_msgTypes, }.Build() File_account_proto = out.File diff --git a/action/protocol/account/accountpb/account.proto b/action/protocol/account/accountpb/account.proto index 9d4dff064f..aedfb4d458 100644 --- a/action/protocol/account/accountpb/account.proto +++ b/action/protocol/account/accountpb/account.proto @@ -1,4 +1,4 @@ -// Copyright (c) 2018 IoTeX +// Copyright (c) 2022 IoTeX // This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no // warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent // permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache @@ -8,6 +8,12 @@ // protoc --go_out=plugins=grpc:. *.proto syntax = "proto3"; package accountpb; +option go_package = "github.com/iotexproject/iotex-core/action/protocol/account/accountpb"; + +enum AccountType { + DEFAULT = 0; + ZERO_NONCE = 1; +} message Account { // used by state-based model @@ -17,5 +23,5 @@ message Account { bytes codeHash = 4; bool isCandidate = 5; bytes votingWeight = 6; + AccountType type = 7; } - diff --git a/action/protocol/account/protocol.go b/action/protocol/account/protocol.go index 60e27a0ccc..036f23afb7 100644 --- a/action/protocol/account/protocol.go +++ b/action/protocol/account/protocol.go @@ -107,20 +107,25 @@ func (p *Protocol) Name() string { return protocolID } -func createAccount(sm protocol.StateManager, encodedAddr string, init *big.Int) error { - var account state.Account +func createAccount(sm protocol.StateManager, encodedAddr string, init *big.Int, opts ...state.AccountCreationOption) error { + account := &state.Account{} addr, err := address.FromString(encodedAddr) if err != nil { return errors.Wrap(err, "failed to get address public key hash from encoded address") } addrHash := hash.BytesToHash160(addr.Bytes()) - _, err = sm.State(&account, protocol.LegacyKeyOption(addrHash)) + _, err = sm.State(account, protocol.LegacyKeyOption(addrHash)) switch errors.Cause(err) { case nil: return errors.Errorf("failed to create account %s", encodedAddr) case state.ErrStateNotExist: - account.Balance = init - account.VotingWeight = big.NewInt(0) + account, err := state.NewAccount(opts...) + if err != nil { + return err + } + if err := account.AddBalance(init); err != nil { + return errors.Wrapf(err, "failed to add balance %s", init) + } if _, err := sm.PutState(account, protocol.LegacyKeyOption(addrHash)); err != nil { return errors.Wrapf(err, "failed to put state for account %x", addrHash) } @@ -143,8 +148,12 @@ func (p *Protocol) CreateGenesisStates(ctx context.Context, sm protocol.StateMan if err := p.assertAmounts(amounts); err != nil { return err } + opts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + opts = append(opts, state.LegacyNonceAccountTypeOption()) + } for i, addr := range addrs { - if err := createAccount(sm, addr.String(), amounts[i]); err != nil { + if err := createAccount(sm, addr.String(), amounts[i], opts...); err != nil { return err } } diff --git a/action/protocol/account/protocol_test.go b/action/protocol/account/protocol_test.go index 1e245c9de0..1501c41c4f 100644 --- a/action/protocol/account/protocol_test.go +++ b/action/protocol/account/protocol_test.go @@ -61,14 +61,14 @@ func TestLoadOrCreateAccountState(t *testing.T) { addrv1 := identityset.Address(27) s, err := accountutil.LoadAccount(sm, addrv1) require.NoError(err) - require.Equal(s.Balance, state.EmptyAccount().Balance) + require.Equal(s.Balance, big.NewInt(0)) // create account - require.NoError(createAccount(sm, addrv1.String(), big.NewInt(5))) + require.NoError(createAccount(sm, addrv1.String(), big.NewInt(5), state.LegacyNonceAccountTypeOption())) s, err = accountutil.LoadAccount(sm, addrv1) require.NoError(err) require.Equal("5", s.Balance.String()) - require.Equal(uint64(0x0), s.Nonce) + require.Equal(uint64(0x1), s.PendingNonce()) } func TestProtocol_Initialize(t *testing.T) { @@ -109,7 +109,7 @@ func TestProtocol_Initialize(t *testing.T) { ctx := protocol.WithBlockCtx(context.Background(), protocol.BlockCtx{ BlockHeight: 0, }) - ctx = genesis.WithGenesisContext(ctx, ge) + ctx = protocol.WithFeatureCtx(genesis.WithGenesisContext(ctx, ge)) p := NewProtocol(rewarding.DepositGas) require.NoError( p.CreateGenesisStates( diff --git a/action/protocol/account/transfer.go b/action/protocol/account/transfer.go index e78d855748..929088c83d 100644 --- a/action/protocol/account/transfer.go +++ b/action/protocol/account/transfer.go @@ -25,20 +25,23 @@ const TransferSizeLimit = 32 * 1024 // handleTransfer handles a transfer func (p *Protocol) handleTransfer(ctx context.Context, act action.Action, sm protocol.StateManager) (*action.Receipt, error) { - actionCtx := protocol.MustGetActionCtx(ctx) - blkCtx := protocol.MustGetBlockCtx(ctx) tsf, ok := act.(*action.Transfer) if !ok { return nil, nil } + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } + actionCtx := protocol.MustGetActionCtx(ctx) // check sender - sender, err := accountutil.LoadOrCreateAccount(sm, actionCtx.Caller) + sender, err := accountutil.LoadOrCreateAccount(sm, actionCtx.Caller, accountCreationOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to load or create the account of sender %s", actionCtx.Caller.String()) } gasFee := big.NewInt(0).Mul(tsf.GasPrice(), big.NewInt(0).SetUint64(actionCtx.IntrinsicGas)) - if big.NewInt(0).Add(tsf.Amount(), gasFee).Cmp(sender.Balance) == 1 { + if !sender.HasSufficientBalance(big.NewInt(0).Add(tsf.Amount(), gasFee)) { return nil, errors.Wrapf( state.ErrNotEnoughBalance, "sender %s balance %s, required amount %s", @@ -74,13 +77,19 @@ func (p *Protocol) handleTransfer(ctx context.Context, act action.Action, sm pro if err != nil { return nil, errors.Wrapf(err, "failed to decode recipient address %s", tsf.Recipient()) } - recipientAcct, err := accountutil.LoadAccount(sm, recipientAddr) + recipientAcct, err := accountutil.LoadAccount(sm, recipientAddr, accountCreationOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to load address %s", tsf.Recipient()) } + fixNonce := protocol.MustGetFeatureCtx(ctx).FixGasAndNonceUpdate + blkCtx := protocol.MustGetBlockCtx(ctx) if recipientAcct.IsContract() { - // update sender Nonce - accountutil.SetNonce(tsf, sender) + if fixNonce || tsf.Nonce() != 0 { + // update sender Nonce + if err := sender.SetPendingNonce(tsf.Nonce() + 1); err != nil { + return nil, errors.Wrapf(err, "failed to update pending nonce of sender %s", actionCtx.Caller.String()) + } + } // put updated sender's state to trie if err := accountutil.StoreAccount(sm, actionCtx.Caller, sender); err != nil { return nil, errors.Wrap(err, "failed to update pending account changes to trie") @@ -108,18 +117,24 @@ func (p *Protocol) handleTransfer(ctx context.Context, act action.Action, sm pro if err := sender.SubBalance(tsf.Amount()); err != nil { return nil, errors.Wrapf(err, "failed to update the Balance of sender %s", actionCtx.Caller.String()) } - // update sender Nonce - accountutil.SetNonce(tsf, sender) + if fixNonce || tsf.Nonce() != 0 { + // update sender Nonce + if err := sender.SetPendingNonce(tsf.Nonce() + 1); err != nil { + return nil, errors.Wrapf(err, "failed to update pending nonce of sender %s", actionCtx.Caller.String()) + } + } // put updated sender's state to trie if err := accountutil.StoreAccount(sm, actionCtx.Caller, sender); err != nil { return nil, errors.Wrap(err, "failed to update pending account changes to trie") } // check recipient - recipient, err := accountutil.LoadOrCreateAccount(sm, recipientAddr) + recipient, err := accountutil.LoadOrCreateAccount(sm, recipientAddr, accountCreationOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to load or create the account of recipient %s", tsf.Recipient()) } - recipient.AddBalance(tsf.Amount()) + if err := recipient.AddBalance(tsf.Amount()); err != nil { + return nil, errors.Wrapf(err, "failed to add balance %s", tsf.Amount()) + } // put updated recipient's state to trie if err := accountutil.StoreAccount(sm, recipientAddr, recipient); err != nil { return nil, errors.Wrap(err, "failed to update pending account changes to trie") diff --git a/action/protocol/account/transfer_test.go b/action/protocol/account/transfer_test.go index fe93964b44..665bd07ada 100644 --- a/action/protocol/account/transfer_test.go +++ b/action/protocol/account/transfer_test.go @@ -78,12 +78,14 @@ func TestProtocol_HandleTransfer(t *testing.T) { alfa := identityset.Address(28) bravo := identityset.Address(29) charlie := identityset.Address(30) - require.NoError(accountutil.StoreAccount(sm, alfa, &state.Account{ - Balance: big.NewInt(50005), - })) - require.NoError(accountutil.StoreAccount(sm, charlie, &state.Account{ - CodeHash: []byte("codeHash"), - })) + acct1, err := state.NewAccount(state.LegacyNonceAccountTypeOption()) + require.NoError(err) + require.NoError(acct1.AddBalance(big.NewInt(50005))) + require.NoError(accountutil.StoreAccount(sm, alfa, acct1)) + acct2, err := state.NewAccount() + require.NoError(err) + acct2.CodeHash = []byte("codeHash") + require.NoError(accountutil.StoreAccount(sm, charlie, acct2)) tests := []struct { caller address.Address @@ -116,9 +118,10 @@ func TestProtocol_HandleTransfer(t *testing.T) { gas, err := tsf.IntrinsicGas() require.NoError(err) - ctx = protocol.WithActionCtx(chainCtx, protocol.ActionCtx{ + ctx := protocol.WithActionCtx(chainCtx, protocol.ActionCtx{ Caller: v.caller, IntrinsicGas: gas, + Nonce: v.nonce, }) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: 1, @@ -126,11 +129,11 @@ func TestProtocol_HandleTransfer(t *testing.T) { GasLimit: testutil.TestGasLimit, }) - sender, err := accountutil.AccountState(sm, v.caller) + sender, err := accountutil.AccountState(ctx, sm, v.caller) require.NoError(err) addr, err := address.FromString(v.recipient) require.NoError(err) - recipient, err := accountutil.AccountState(sm, addr) + recipient, err := accountutil.AccountState(ctx, sm, addr) require.NoError(err) gasFee := new(big.Int).Mul(v.gasPrice, new(big.Int).SetUint64(gas)) @@ -140,10 +143,10 @@ func TestProtocol_HandleTransfer(t *testing.T) { if err != nil { require.Nil(receipt) // sender balance/nonce remains the same in case of error - newSender, err := accountutil.AccountState(sm, v.caller) + newSender, err := accountutil.AccountState(ctx, sm, v.caller) require.NoError(err) require.Equal(sender.Balance, newSender.Balance) - require.Equal(sender.Nonce, newSender.Nonce) + require.Equal(sender.PendingNonce(), newSender.PendingNonce()) continue } require.Equal(v.status, receipt.Status) @@ -154,17 +157,17 @@ func TestProtocol_HandleTransfer(t *testing.T) { // verify recipient addr, err := address.FromString(v.recipient) require.NoError(err) - newRecipient, err := accountutil.AccountState(sm, addr) + newRecipient, err := accountutil.AccountState(ctx, sm, addr) require.NoError(err) - recipient.AddBalance(v.amount) + require.NoError(recipient.AddBalance(v.amount)) require.Equal(recipient.Balance, newRecipient.Balance) } // verify sender balance/nonce - newSender, err := accountutil.AccountState(sm, v.caller) + newSender, err := accountutil.AccountState(ctx, sm, v.caller) require.NoError(err) - sender.SubBalance(gasFee) + require.NoError(sender.SubBalance(gasFee)) require.Equal(sender.Balance, newSender.Balance) - require.Equal(v.nonce, newSender.Nonce) + require.Equal(v.nonce+1, newSender.PendingNonce()) // verify transaction log tLog := block.ReceiptTransactionLog(receipt) diff --git a/action/protocol/account/util/util.go b/action/protocol/account/util/util.go index 437a6d190e..4114290016 100644 --- a/action/protocol/account/util/util.go +++ b/action/protocol/account/util/util.go @@ -7,7 +7,7 @@ package accountutil import ( - "math/big" + "context" "github.com/pkg/errors" @@ -18,54 +18,46 @@ import ( "github.com/iotexproject/iotex-core/state" ) -type noncer interface { - Nonce() uint64 -} - -// SetNonce sets nonce for account -func SetNonce(i noncer, state *state.Account) { - if i.Nonce() > state.Nonce { - state.Nonce = i.Nonce() - } -} - // LoadOrCreateAccount either loads an account state or creates an account state -func LoadOrCreateAccount(sm protocol.StateManager, addr address.Address) (*state.Account, error) { +func LoadOrCreateAccount(sm protocol.StateManager, addr address.Address, opts ...state.AccountCreationOption) (*state.Account, error) { var ( - account state.Account + account = &state.Account{} addrHash = hash.BytesToHash160(addr.Bytes()) ) - _, err := sm.State(&account, protocol.LegacyKeyOption(addrHash)) - if err == nil { - return &account, nil - } - if errors.Cause(err) == state.ErrStateNotExist { - account.Balance = big.NewInt(0) - account.VotingWeight = big.NewInt(0) + _, err := sm.State(account, protocol.LegacyKeyOption(addrHash)) + switch errors.Cause(err) { + case nil: + return account, nil + case state.ErrStateNotExist: + account, err := state.NewAccount(opts...) + if err != nil { + return nil, errors.Wrapf(err, "failed to create state account for %x", addrHash) + } if _, err := sm.PutState(account, protocol.LegacyKeyOption(addrHash)); err != nil { return nil, errors.Wrapf(err, "failed to put state for account %x", addrHash) } - return &account, nil + return account, nil + default: + return nil, err } - return nil, err } // LoadAccount loads an account state by address.Address -func LoadAccount(sr protocol.StateReader, addr address.Address) (*state.Account, error) { - return LoadAccountByHash160(sr, hash.BytesToHash160(addr.Bytes())) +func LoadAccount(sr protocol.StateReader, addr address.Address, opts ...state.AccountCreationOption) (*state.Account, error) { + return LoadAccountByHash160(sr, hash.BytesToHash160(addr.Bytes()), opts...) } // LoadAccountByHash160 loads an account state by 20-byte address -func LoadAccountByHash160(sr protocol.StateReader, addrHash hash.Hash160) (*state.Account, error) { - var account state.Account - if _, err := sr.State(&account, protocol.LegacyKeyOption(addrHash)); err != nil { - if errors.Cause(err) == state.ErrStateNotExist { - account = state.EmptyAccount() - return &account, nil - } +func LoadAccountByHash160(sr protocol.StateReader, addrHash hash.Hash160, opts ...state.AccountCreationOption) (*state.Account, error) { + account := &state.Account{} + switch _, err := sr.State(account, protocol.LegacyKeyOption(addrHash)); errors.Cause(err) { + case state.ErrStateNotExist: + return state.NewAccount(opts...) + case nil: + return account, nil + default: return nil, err } - return &account, nil } // StoreAccount puts updated account state to trie @@ -77,34 +69,47 @@ func StoreAccount(sm protocol.StateManager, addr address.Address, account *state // Recorded tests if an account has been actually stored func Recorded(sr protocol.StateReader, addr address.Address) (bool, error) { - var account state.Account - _, err := sr.State(&account, protocol.LegacyKeyOption(hash.BytesToHash160(addr.Bytes()))) - if err == nil { + account := &state.Account{} + _, err := sr.State(account, protocol.LegacyKeyOption(hash.BytesToHash160(addr.Bytes()))) + switch errors.Cause(err) { + case nil: return true, nil - } - if errors.Cause(err) == state.ErrStateNotExist { + case state.ErrStateNotExist: return false, nil } return false, err } // AccountState returns the confirmed account state on the chain -func AccountState(sr protocol.StateReader, addr address.Address) (*state.Account, error) { - a, _, err := AccountStateWithHeight(sr, addr) +func AccountState(ctx context.Context, sr protocol.StateReader, addr address.Address) (*state.Account, error) { + a, _, err := AccountStateWithHeight(ctx, sr, addr) return a, err } // AccountStateWithHeight returns the confirmed account state on the chain with what height the state is read from. -func AccountStateWithHeight(sr protocol.StateReader, addr address.Address) (*state.Account, uint64, error) { +func AccountStateWithHeight(ctx context.Context, sr protocol.StateReader, addr address.Address) (*state.Account, uint64, error) { pkHash := hash.BytesToHash160(addr.Bytes()) - var account state.Account - h, err := sr.State(&account, protocol.LegacyKeyOption(pkHash)) - if err != nil { - if errors.Cause(err) == state.ErrStateNotExist { - account = state.EmptyAccount() - return &account, h, nil + account := &state.Account{} + h, err := sr.State(account, protocol.LegacyKeyOption(pkHash)) + switch errors.Cause(err) { + case nil: + return account, h, nil + case state.ErrStateNotExist: + tip, err := sr.Height() + if err != nil { + return nil, 0, err + } + ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ + BlockHeight: tip + 1, + }) + ctx = protocol.WithFeatureCtx(ctx) + var opts []state.AccountCreationOption + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + opts = append(opts, state.LegacyNonceAccountTypeOption()) } + account, err = state.NewAccount(opts...) + return account, h, err + default: return nil, h, errors.Wrapf(err, "error when loading state of %x", pkHash) } - return &account, h, nil } diff --git a/action/protocol/context.go b/action/protocol/context.go index 9121e028e6..085f6c71fb 100644 --- a/action/protocol/context.go +++ b/action/protocol/context.go @@ -81,30 +81,32 @@ type ( // FeatureCtx provides features information. FeatureCtx struct { - FixDoubleChargeGas bool - SystemWideActionGasLimit bool - NotFixTopicCopyBug bool - SetRevertMessageToReceipt bool - FixGetHashFnHeight bool - UsePendingNonceOption bool - AsyncContractTrie bool - AddOutOfGasToTransactionLog bool - AddChainIDToConfig bool - UseV2Storage bool - CannotUnstakeAgain bool - SkipStakingIndexer bool - ReturnFetchError bool - CannotTranferToSelf bool - NewStakingReceiptFormat bool - UpdateBlockMeta bool - CurrentEpochProductivity bool - FixSnapshotOrder bool - AllowCorrectDefaultChainID bool - CorrectGetHashFn bool - CorrectTxLogIndex bool - RevertLog bool - TolerateLegacyAddress bool - ValidateRewardProtocol bool + FixDoubleChargeGas bool + SystemWideActionGasLimit bool + NotFixTopicCopyBug bool + SetRevertMessageToReceipt bool + FixGetHashFnHeight bool + FixSortCacheContractsAndUsePendingNonce bool + AsyncContractTrie bool + AddOutOfGasToTransactionLog bool + AddChainIDToConfig bool + UseV2Storage bool + CannotUnstakeAgain bool + SkipStakingIndexer bool + ReturnFetchError bool + CannotTranferToSelf bool + NewStakingReceiptFormat bool + UpdateBlockMeta bool + CurrentEpochProductivity bool + FixSnapshotOrder bool + AllowCorrectDefaultChainID bool + CorrectGetHashFn bool + CorrectTxLogIndex bool + RevertLog bool + TolerateLegacyAddress bool + ValidateRewardProtocol bool + CreateLegacyNonceAccount bool + FixGasAndNonceUpdate bool } // FeatureWithHeightCtx provides feature check functions. @@ -210,30 +212,32 @@ func WithFeatureCtx(ctx context.Context) context.Context { ctx, featureContextKey{}, FeatureCtx{ - FixDoubleChargeGas: g.IsPacific(height), - SystemWideActionGasLimit: !g.IsAleutian(height), - NotFixTopicCopyBug: !g.IsAleutian(height), - SetRevertMessageToReceipt: g.IsHawaii(height), - FixGetHashFnHeight: g.IsHawaii(height), - UsePendingNonceOption: g.IsHawaii(height), - AsyncContractTrie: g.IsGreenland(height), - AddOutOfGasToTransactionLog: !g.IsGreenland(height), - AddChainIDToConfig: g.IsIceland(height), - UseV2Storage: g.IsGreenland(height), - CannotUnstakeAgain: g.IsGreenland(height), - SkipStakingIndexer: !g.IsFairbank(height), - ReturnFetchError: !g.IsGreenland(height), - CannotTranferToSelf: g.IsHawaii(height), - NewStakingReceiptFormat: g.IsFbkMigration(height), - UpdateBlockMeta: g.IsGreenland(height), - CurrentEpochProductivity: g.IsGreenland(height), - FixSnapshotOrder: g.IsKamchatka(height), - AllowCorrectDefaultChainID: g.IsMidway(height), - CorrectGetHashFn: g.IsMidway(height), - CorrectTxLogIndex: g.IsMidway(height), - RevertLog: g.IsMidway(height), - TolerateLegacyAddress: !g.IsNewfoundland(height), - ValidateRewardProtocol: g.IsNewfoundland(height), + FixDoubleChargeGas: g.IsPacific(height), + SystemWideActionGasLimit: !g.IsAleutian(height), + NotFixTopicCopyBug: !g.IsAleutian(height), + SetRevertMessageToReceipt: g.IsHawaii(height), + FixGetHashFnHeight: g.IsHawaii(height), + FixSortCacheContractsAndUsePendingNonce: g.IsHawaii(height), + AsyncContractTrie: g.IsGreenland(height), + AddOutOfGasToTransactionLog: !g.IsGreenland(height), + AddChainIDToConfig: g.IsIceland(height), + UseV2Storage: g.IsGreenland(height), + CannotUnstakeAgain: g.IsGreenland(height), + SkipStakingIndexer: !g.IsFairbank(height), + ReturnFetchError: !g.IsGreenland(height), + CannotTranferToSelf: g.IsHawaii(height), + NewStakingReceiptFormat: g.IsFbkMigration(height), + UpdateBlockMeta: g.IsGreenland(height), + CurrentEpochProductivity: g.IsGreenland(height), + FixSnapshotOrder: g.IsKamchatka(height), + AllowCorrectDefaultChainID: g.IsMidway(height), + CorrectGetHashFn: g.IsMidway(height), + CorrectTxLogIndex: g.IsMidway(height), + RevertLog: g.IsMidway(height), + TolerateLegacyAddress: !g.IsNewfoundland(height), + ValidateRewardProtocol: g.IsNewfoundland(height), + CreateLegacyNonceAccount: !g.IsToBeEnabled(height), + FixGasAndNonceUpdate: g.IsToBeEnabled(height), }, ) } diff --git a/action/protocol/execution/evm/contract_test.go b/action/protocol/execution/evm/contract_test.go index 78580bd8ef..8cf45f7416 100644 --- a/action/protocol/execution/evm/contract_test.go +++ b/action/protocol/execution/evm/contract_test.go @@ -67,7 +67,8 @@ func TestCreateContract(t *testing.T) { addr := identityset.Address(28) _, err = accountutil.LoadOrCreateAccount(sm, addr) require.NoError(err) - stateDB := NewStateDBAdapter(sm, 0, hash.ZeroHash256, NotFixTopicCopyBugOption()) + stateDB, err := NewStateDBAdapter(sm, 0, hash.ZeroHash256, NotFixTopicCopyBugOption()) + require.NoError(err) contract := addr.Bytes() var evmContract common.Address @@ -101,7 +102,8 @@ func TestLoadStoreCommit(t *testing.T) { ctrl := gomock.NewController(t) sm, err := initMockStateManager(ctrl) require.NoError(err) - cntr1, err := newContract(hash.BytesToHash160(_c1[:]), &state.Account{}, sm, enableAsync) + acct := &state.Account{} + cntr1, err := newContract(hash.BytesToHash160(_c1[:]), acct, sm, enableAsync) require.NoError(err) tests := []cntrTest{ @@ -252,9 +254,9 @@ func TestSnapshot(t *testing.T) { testfunc := func(enableAsync bool) { sm, err := initMockStateManager(ctrl) require.NoError(err) - s := &state.Account{ - Balance: big.NewInt(5), - } + s, err := state.NewAccount() + require.NoError(err) + require.NoError(s.AddBalance(big.NewInt(5))) _c1, err := newContract( hash.BytesToHash160(identityset.Address(28).Bytes()), s, @@ -264,7 +266,7 @@ func TestSnapshot(t *testing.T) { require.NoError(err) require.NoError(_c1.SetState(_k2b, _v2[:])) _c2 := _c1.Snapshot() - _c1.SelfState().AddBalance(big.NewInt(7)) + require.NoError(_c1.SelfState().AddBalance(big.NewInt(7))) require.NoError(_c1.SetState(_k1b, _v1[:])) require.Equal(big.NewInt(12), _c1.SelfState().Balance) require.Equal(big.NewInt(5), _c2.SelfState().Balance) diff --git a/action/protocol/execution/evm/evm.go b/action/protocol/execution/evm/evm.go index 1ab9cdf2fe..e9c6be8fe0 100644 --- a/action/protocol/execution/evm/evm.go +++ b/action/protocol/execution/evm/evm.go @@ -199,7 +199,10 @@ func ExecuteContract( blkCtx := protocol.MustGetBlockCtx(ctx) g := genesis.MustExtractGenesisContext(ctx) featureCtx := protocol.MustGetFeatureCtx(ctx) - stateDB := prepareStateDB(ctx, sm) + stateDB, err := prepareStateDB(ctx, sm) + if err != nil { + return nil, nil, err + } ps, err := newParams(ctx, execution, stateDB, getBlockHash) if err != nil { return nil, nil, err @@ -280,18 +283,24 @@ func ReadContractStorage( BlockHeight: bcCtx.Tip.Height + 1, }, )) - stateDB := prepareStateDB(ctx, sm) + stateDB, err := prepareStateDB(ctx, sm) + if err != nil { + return nil, err + } res := stateDB.GetState(common.BytesToAddress(contract.Bytes()), common.BytesToHash(key)) return res[:], nil } -func prepareStateDB(ctx context.Context, sm protocol.StateManager) *StateDBAdapter { +func prepareStateDB(ctx context.Context, sm protocol.StateManager) (*StateDBAdapter, error) { actionCtx := protocol.MustGetActionCtx(ctx) blkCtx := protocol.MustGetBlockCtx(ctx) featureCtx := protocol.MustGetFeatureCtx(ctx) opts := []StateDBAdapterOption{} - if featureCtx.UsePendingNonceOption { - opts = append(opts, SortCachedContractsOption(), UsePendingNonceOption()) + if featureCtx.CreateLegacyNonceAccount { + opts = append(opts, LegacyNonceAccountOption()) + } + if !featureCtx.FixSortCacheContractsAndUsePendingNonce { + opts = append(opts, DisableSortCachedContractsOption(), UseConfirmedNonceOption()) } if featureCtx.NotFixTopicCopyBug { opts = append(opts, NotFixTopicCopyBugOption()) diff --git a/action/protocol/execution/evm/evm_test.go b/action/protocol/execution/evm/evm_test.go index 53e2c54667..8db5696525 100644 --- a/action/protocol/execution/evm/evm_test.go +++ b/action/protocol/execution/evm/evm_test.go @@ -214,7 +214,8 @@ func TestConstantinople(t *testing.T) { if g.IsKamchatka(e.height) { opt = append(opt, FixSnapshotOrderOption()) } - stateDB := NewStateDBAdapter(sm, e.height, hash.ZeroHash256, opt...) + stateDB, err := NewStateDBAdapter(sm, e.height, hash.ZeroHash256, opt...) + require.NoError(err) fCtx := protocol.WithBlockCtx(ctx, protocol.BlockCtx{ Producer: identityset.Address(27), diff --git a/action/protocol/execution/evm/evmstatedbadapter.go b/action/protocol/execution/evm/evmstatedbadapter.go index 7fdfc5311b..a7833c6770 100644 --- a/action/protocol/execution/evm/evmstatedbadapter.go +++ b/action/protocol/execution/evm/evmstatedbadapter.go @@ -49,39 +49,40 @@ type ( // StateDBAdapter represents the state db adapter for evm to access iotx blockchain StateDBAdapter struct { - sm protocol.StateManager - logs []*action.Log - transactionLogs []*action.TransactionLog - err error - blockHeight uint64 - executionHash hash.Hash256 - refund uint64 - cachedContract contractMap - contractSnapshot map[int]contractMap // snapshots of contracts - suicided deleteAccount // account/contract calling Suicide - suicideSnapshot map[int]deleteAccount // snapshots of suicide accounts - preimages preimageMap - preimageSnapshot map[int]preimageMap - accessList *accessList // per-transaction access list - accessListSnapshot map[int]*accessList - logsSnapshot map[int]int // logs is an array, save len(logs) at time of snapshot suffices - txLogsSnapshot map[int]int - notFixTopicCopyBug bool - asyncContractTrie bool - sortCachedContracts bool - usePendingNonce bool - fixSnapshotOrder bool - revertLog bool + sm protocol.StateManager + logs []*action.Log + transactionLogs []*action.TransactionLog + err error + blockHeight uint64 + executionHash hash.Hash256 + refund uint64 + cachedContract contractMap + contractSnapshot map[int]contractMap // snapshots of contracts + suicided deleteAccount // account/contract calling Suicide + suicideSnapshot map[int]deleteAccount // snapshots of suicide accounts + preimages preimageMap + preimageSnapshot map[int]preimageMap + accessList *accessList // per-transaction access list + accessListSnapshot map[int]*accessList + logsSnapshot map[int]int // logs is an array, save len(logs) at time of snapshot suffices + txLogsSnapshot map[int]int + notFixTopicCopyBug bool + asyncContractTrie bool + disableSortCachedContracts bool + useConfirmedNonce bool + legacyNonceAccount bool + fixSnapshotOrder bool + revertLog bool } ) // StateDBAdapterOption set StateDBAdapter construction param type StateDBAdapterOption func(*StateDBAdapter) error -// SortCachedContractsOption set sort cached contracts as true -func SortCachedContractsOption() StateDBAdapterOption { +// DisableSortCachedContractsOption set disable sort cached contracts as true +func DisableSortCachedContractsOption() StateDBAdapterOption { return func(adapter *StateDBAdapter) error { - adapter.sortCachedContracts = true + adapter.disableSortCachedContracts = true return nil } } @@ -102,10 +103,18 @@ func AsyncContractTrieOption() StateDBAdapterOption { } } -// UsePendingNonceOption set usePendingNonce as true -func UsePendingNonceOption() StateDBAdapterOption { +// UseConfirmedNonceOption set usePendingNonce as true +func UseConfirmedNonceOption() StateDBAdapterOption { return func(adapter *StateDBAdapter) error { - adapter.usePendingNonce = true + adapter.useConfirmedNonce = true + return nil + } +} + +// LegacyNonceAccountOption set legacyNonceAccount as true +func LegacyNonceAccountOption() StateDBAdapterOption { + return func(adapter *StateDBAdapter) error { + adapter.legacyNonceAccount = true return nil } } @@ -132,7 +141,7 @@ func NewStateDBAdapter( blockHeight uint64, executionHash hash.Hash256, opts ...StateDBAdapterOption, -) *StateDBAdapter { +) (*StateDBAdapter, error) { s := &StateDBAdapter{ sm: sm, logs: []*action.Log{}, @@ -152,10 +161,13 @@ func NewStateDBAdapter( } for _, opt := range opts { if err := opt(s); err != nil { - log.L().Panic("failed to execute stateDB creation option") + return nil, errors.Wrap(err, "failed to execute stateDB creation option") } } - return s + if !s.legacyNonceAccount && s.useConfirmedNonce { + return nil, errors.New("invalid parameter combination") + } + return s, nil } func (stateDB *StateDBAdapter) logError(err error) { @@ -169,6 +181,13 @@ func (stateDB *StateDBAdapter) Error() error { return stateDB.err } +func (stateDB *StateDBAdapter) accountCreationOpts() []state.AccountCreationOption { + if stateDB.legacyNonceAccount { + return []state.AccountCreationOption{state.LegacyNonceAccountTypeOption()} + } + return nil +} + // CreateAccount creates an account in iotx blockchain func (stateDB *StateDBAdapter) CreateAccount(evmAddr common.Address) { addr, err := address.FromBytes(evmAddr.Bytes()) @@ -176,7 +195,7 @@ func (stateDB *StateDBAdapter) CreateAccount(evmAddr common.Address) { log.L().Error("Failed to convert evm address.", zap.Error(err)) return } - _, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr) + _, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr, stateDB.accountCreationOpts()...) if err != nil { log.L().Error("Failed to create account.", zap.Error(err)) stateDB.logError(err) @@ -232,14 +251,18 @@ func (stateDB *StateDBAdapter) AddBalance(evmAddr common.Address, amount *big.In if contract, ok := stateDB.cachedContract[addrHash]; ok { state = contract.SelfState() } else { - state, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr) + state, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr, stateDB.accountCreationOpts()...) if err != nil { log.L().Error("Failed to add balance.", log.Hex("addrHash", evmAddr[:])) stateDB.logError(err) return } } - state.AddBalance(amount) + if err := state.AddBalance(amount); err != nil { + log.L().Error("failed to add balance", zap.Error(err), zap.String("amount", amount.String())) + stateDB.logError(err) + return + } if err := accountutil.StoreAccount(stateDB.sm, addr, state); err != nil { log.L().Error("Failed to update pending account changes to trie.", zap.Error(err)) stateDB.logError(err) @@ -263,12 +286,20 @@ func (stateDB *StateDBAdapter) GetBalance(evmAddr common.Address) *big.Int { return state.Balance } -// InitNonce returns the init nonce of an account -func (stateDB *StateDBAdapter) InitNonce() uint64 { - if stateDB.usePendingNonce { - return 1 +// IsNewAccount returns true if this is a new account +func (stateDB *StateDBAdapter) IsNewAccount(evmAddr common.Address) bool { + addr, err := address.FromBytes(evmAddr.Bytes()) + if err != nil { + log.L().Error("Failed to convert evm address.", zap.Error(err)) + return false + } + state, err := stateDB.AccountState(addr.String()) + if err != nil { + log.L().Error("failed to load account.", zap.Error(err), zap.String("address", addr.String())) + return false } - return 0 + + return state.IsNewbieAccount() } // GetNonce gets the nonce of account @@ -278,22 +309,30 @@ func (stateDB *StateDBAdapter) GetNonce(evmAddr common.Address) uint64 { log.L().Error("Failed to convert evm address.", zap.Error(err)) return 0 } - nonce := uint64(0) + var pendingNonce uint64 + if stateDB.legacyNonceAccount { + pendingNonce = uint64(1) + } else { + pendingNonce = uint64(0) + } state, err := stateDB.AccountState(addr.String()) if err != nil { log.L().Error("Failed to get nonce.", zap.Error(err)) // stateDB.logError(err) } else { - nonce = state.Nonce + pendingNonce = state.PendingNonce() } - if stateDB.usePendingNonce { - nonce++ + if stateDB.useConfirmedNonce { + if pendingNonce == 0 { + panic("invalid pending nonce") + } + pendingNonce-- } log.L().Debug("Called GetNonce.", zap.String("address", addr.String()), - zap.Uint64("nonce", nonce)) + zap.Uint64("pendingNonce", pendingNonce)) - return nonce + return pendingNonce } // SetNonce sets the nonce of account @@ -309,7 +348,7 @@ func (stateDB *StateDBAdapter) SetNonce(evmAddr common.Address, nonce uint64) { // stateDB.logError(err) return } - if stateDB.usePendingNonce { + if !stateDB.useConfirmedNonce { if nonce == 0 { panic("invalid nonce zero") } @@ -318,9 +357,14 @@ func (stateDB *StateDBAdapter) SetNonce(evmAddr common.Address, nonce uint64) { log.L().Debug("Called SetNonce.", zap.String("address", addr.String()), zap.Uint64("nonce", nonce)) - s.Nonce = nonce + if !s.IsNewbieAccount() || s.AccountType() != 0 || nonce != 0 { + if err := s.SetPendingNonce(nonce + 1); err != nil { + log.L().Panic("Failed to set nonce.", zap.Error(err), zap.String("addr", addr.Hex()), zap.Uint64("pendingNonce", s.PendingNonce()), zap.Uint64("nonce", nonce), zap.String("execution", hex.EncodeToString(stateDB.executionHash[:]))) + stateDB.logError(err) + } + } if err := accountutil.StoreAccount(stateDB.sm, addr, s); err != nil { - log.L().Error("Failed to set nonce.", zap.Error(err)) + log.L().Error("Failed to store account.", zap.Error(err)) stateDB.logError(err) } } @@ -365,8 +409,10 @@ func (stateDB *StateDBAdapter) Suicide(evmAddr common.Address) bool { return false } // clears the account balance - s.Balance = nil - s.Balance = big.NewInt(0) + if err := s.SubBalance(s.Balance); err != nil { + log.L().Debug("failed to clear balance", zap.Error(err), zap.String("address", addr.String())) + return false + } addrHash := hash.BytesToHash160(evmAddr.Bytes()) if _, err := stateDB.sm.PutState(s, protocol.LegacyKeyOption(addrHash)); err != nil { log.L().Error("Failed to kill contract.", zap.Error(err)) @@ -466,7 +512,7 @@ func (stateDB *StateDBAdapter) Empty(evmAddr common.Address) bool { return true } // TODO: delete hash.ZeroHash256 - return s.Nonce == 0 && + return s.IsNewbieAccount() && s.Balance.Sign() == 0 && (len(s.CodeHash) == 0 || bytes.Equal(s.CodeHash, hash.ZeroHash256[:])) } @@ -572,7 +618,7 @@ func (stateDB *StateDBAdapter) cachedContractAddrs() []hash.Hash160 { for addr := range stateDB.cachedContract { addrs = append(addrs, addr) } - if stateDB.sortCachedContracts { + if !stateDB.disableSortCachedContracts { sort.Slice(addrs, func(i, j int) bool { return bytes.Compare(addrs[i][:], addrs[j][:]) < 0 }) } return addrs @@ -729,7 +775,7 @@ func (stateDB *StateDBAdapter) AccountState(encodedAddr string) (*state.Account, if contract, ok := stateDB.cachedContract[addrHash]; ok { return contract.SelfState(), nil } - return accountutil.LoadAccountByHash160(stateDB.sm, addrHash) + return accountutil.LoadAccountByHash160(stateDB.sm, addrHash, stateDB.accountCreationOpts()...) } //====================================== @@ -744,7 +790,7 @@ func (stateDB *StateDBAdapter) GetCodeHash(evmAddr common.Address) common.Hash { copy(codeHash[:], contract.SelfState().CodeHash) return codeHash } - account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr) + account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) if err != nil { log.L().Error("Failed to get code hash.", zap.Error(err)) // TODO (zhi) not all err should be logged @@ -766,7 +812,7 @@ func (stateDB *StateDBAdapter) GetCode(evmAddr common.Address) []byte { } return code } - account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr) + account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) if err != nil { log.L().Error("Failed to load account state for address.", log.Hex("addrHash", addr[:])) return nil @@ -936,7 +982,7 @@ func (stateDB *StateDBAdapter) getContract(addr hash.Hash160) (Contract, error) } func (stateDB *StateDBAdapter) getNewContract(addr hash.Hash160) (Contract, error) { - account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr) + account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) if err != nil { return nil, errors.Wrapf(err, "failed to load account state for address %x", addr) } diff --git a/action/protocol/execution/evm/evmstatedbadapter_test.go b/action/protocol/execution/evm/evmstatedbadapter_test.go index 203857f391..3a10eba4fc 100644 --- a/action/protocol/execution/evm/evmstatedbadapter_test.go +++ b/action/protocol/execution/evm/evmstatedbadapter_test.go @@ -91,13 +91,14 @@ func TestAddBalance(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) addr := common.HexToAddress("02ae2a956d21e8d481c3a69e146633470cf625ec") - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) addAmount := big.NewInt(40000) stateDB.AddBalance(addr, addAmount) amount := stateDB.GetBalance(addr) @@ -113,13 +114,14 @@ func TestRefundAPIs(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) require.Zero(stateDB.GetRefund()) refund := uint64(1024) stateDB.AddRefund(refund) @@ -133,13 +135,14 @@ func TestEmptyAndCode(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) addr := common.HexToAddress("02ae2a956d21e8d481c3a69e146633470cf625ec") - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) require.True(stateDB.Empty(addr)) stateDB.CreateAccount(addr) require.True(stateDB.Empty(addr)) @@ -169,13 +172,14 @@ func TestForEachStorage(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) addr := common.HexToAddress("02ae2a956d21e8d481c3a69e146633470cf625ec") - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) stateDB.CreateAccount(addr) for k, v := range kvs { stateDB.SetState(addr, k, v) @@ -197,15 +201,14 @@ func TestReadContractStorage(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) addr := common.HexToAddress("02ae2a956d21e8d481c3a69e146633470cf625ec") - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, AsyncContractTrieOption(), - SortCachedContractsOption(), - UsePendingNonceOption(), FixSnapshotOrderOption(), ) + require.NoError(err) stateDB.CreateAccount(addr) kvs := map[common.Hash]common.Hash{ common.HexToHash("0123456701234567012345670123456701234567012345670123456701234560"): common.HexToHash("0123456701234567012345670123456701234567012345670123456701234560"), @@ -240,17 +243,60 @@ func TestNonce(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - sm, err := initMockStateManager(ctrl) - require.NoError(err) addr := common.HexToAddress("02ae2a956d21e8d481c3a69e146633470cf625ec") - opt := []StateDBAdapterOption{ - NotFixTopicCopyBugOption(), - FixSnapshotOrderOption(), - } - stateDB := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) - require.Equal(uint64(0), stateDB.GetNonce(addr)) - stateDB.SetNonce(addr, 1) - require.Equal(uint64(1), stateDB.GetNonce(addr)) + t.Run("legacy nonce account with confirmed nonce", func(t *testing.T) { + sm, err := initMockStateManager(ctrl) + require.NoError(err) + opt := []StateDBAdapterOption{ + NotFixTopicCopyBugOption(), + FixSnapshotOrderOption(), + LegacyNonceAccountOption(), + UseConfirmedNonceOption(), + } + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + require.NoError(err) + require.Equal(uint64(0), stateDB.GetNonce(addr)) + stateDB.SetNonce(addr, 1) + require.Equal(uint64(1), stateDB.GetNonce(addr)) + }) + t.Run("legacy nonce account with pending nonce", func(t *testing.T) { + sm, err := initMockStateManager(ctrl) + require.NoError(err) + opt := []StateDBAdapterOption{ + NotFixTopicCopyBugOption(), + FixSnapshotOrderOption(), + LegacyNonceAccountOption(), + } + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + require.NoError(err) + require.Equal(uint64(1), stateDB.GetNonce(addr)) + stateDB.SetNonce(addr, 2) + require.Equal(uint64(2), stateDB.GetNonce(addr)) + }) + t.Run("zero nonce account with confirmed nonce", func(t *testing.T) { + sm, err := initMockStateManager(ctrl) + require.NoError(err) + opt := []StateDBAdapterOption{ + NotFixTopicCopyBugOption(), + FixSnapshotOrderOption(), + UseConfirmedNonceOption(), + } + _, err = NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + require.Error(err) + }) + t.Run("zero nonce account with pending nonce", func(t *testing.T) { + sm, err := initMockStateManager(ctrl) + require.NoError(err) + opt := []StateDBAdapterOption{ + NotFixTopicCopyBugOption(), + FixSnapshotOrderOption(), + } + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + require.NoError(err) + require.Equal(uint64(0), stateDB.GetNonce(addr)) + stateDB.SetNonce(addr, 1) + require.Equal(uint64(1), stateDB.GetNonce(addr)) + }) } var tests = []stateDBTest{ @@ -363,7 +409,8 @@ func TestSnapshotRevertAndCommit(t *testing.T) { if revertLog { opt = append(opt, RevertLogOption()) } - stateDB := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opt...) + require.NoError(err) for i, test := range tests { // add balance @@ -625,7 +672,8 @@ func TestClearSnapshots(t *testing.T) { if fixSnapshotOrder { opts = append(opts, FixSnapshotOrderOption()) } - stateDB := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opts...) + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opts...) + require.NoError(err) for i, test := range tests { // add balance @@ -701,13 +749,14 @@ func TestGetCommittedState(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) stateDB.SetState(_c1, _k1, _v1) // _k2 does not exist @@ -739,13 +788,14 @@ func TestGetBalanceOnError(t *testing.T) { for _, err := range errs { sm.EXPECT().State(gomock.Any(), gomock.Any()).Return(uint64(0), err).Times(1) addr := common.HexToAddress("test address") - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + assert.NoError(t, err) amount := stateDB.GetBalance(addr) assert.Equal(t, big.NewInt(0), amount) } @@ -757,13 +807,14 @@ func TestPreimage(t *testing.T) { sm, err := initMockStateManager(ctrl) require.NoError(err) - stateDB := NewStateDBAdapter( + stateDB, err := NewStateDBAdapter( sm, 1, hash.ZeroHash256, NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) + require.NoError(err) stateDB.AddPreimage(common.BytesToHash(_v1[:]), []byte("cat")) stateDB.AddPreimage(common.BytesToHash(_v2[:]), []byte("dog")) @@ -785,6 +836,7 @@ func TestPreimage(t *testing.T) { } func TestSortMap(t *testing.T) { + require := require.New(t) uniqueSlice := func(slice []string) bool { for _, v := range slice[1:] { if v != slice[0] { @@ -799,7 +851,8 @@ func TestSortMap(t *testing.T) { NotFixTopicCopyBugOption(), FixSnapshotOrderOption(), ) - stateDB := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opts...) + stateDB, err := NewStateDBAdapter(sm, 1, hash.ZeroHash256, opts...) + require.NoError(err) size := 10 for i := 0; i < size; i++ { @@ -812,13 +865,13 @@ func TestSortMap(t *testing.T) { for i := 0; i < size; i++ { stateDB.RevertToSnapshot(sn) s := "" - if stateDB.sortCachedContracts { - for _, addr := range stateDB.cachedContractAddrs() { - c := stateDB.cachedContract[addr] + if stateDB.disableSortCachedContracts { + for _, c := range stateDB.cachedContract { s += string(c.SelfState().Root[:]) } } else { - for _, c := range stateDB.cachedContract { + for _, addr := range stateDB.cachedContractAddrs() { + c := stateDB.cachedContract[addr] s += string(c.SelfState().Root[:]) } } @@ -827,16 +880,15 @@ func TestSortMap(t *testing.T) { } return uniqueSlice(caches) } - require := require.New(t) ctrl := gomock.NewController(t) sm, err := initMockStateManager(ctrl) require.NoError(err) t.Run("before fix sort map", func(t *testing.T) { - require.False(testFunc(t, sm)) + require.False(testFunc(t, sm, DisableSortCachedContractsOption())) }) t.Run("after fix sort map", func(t *testing.T) { - require.True(testFunc(t, sm, SortCachedContractsOption())) + require.True(testFunc(t, sm)) }) } diff --git a/action/protocol/execution/protocol_test.go b/action/protocol/execution/protocol_test.go index 40ba0e3a3d..0c255f1479 100644 --- a/action/protocol/execution/protocol_test.go +++ b/action/protocol/execution/protocol_test.go @@ -39,6 +39,7 @@ import ( "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/block" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/blockindex" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/db" @@ -259,13 +260,13 @@ func readExecution( contractAddr string, ) ([]byte, *action.Receipt, error) { log.S().Info(ecfg.Comment) - state, err := accountutil.AccountState(sf, ecfg.Executor()) + state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, ecfg.Executor()) if err != nil { return nil, nil, err } exec, err := action.NewExecutionWithAccessList( contractAddr, - state.Nonce+1, + state.PendingNonce(), ecfg.Amount(), ecfg.GasLimit(), ecfg.GasPrice(), @@ -299,17 +300,16 @@ func runExecutions( hashes := []hash.Hash256{} for i, ecfg := range ecfgs { log.S().Info(ecfg.Comment) - var nonce uint64 + nonce := uint64(1) var ok bool executor := ecfg.Executor() if nonce, ok = nonces[executor.String()]; !ok { - state, err := accountutil.AccountState(sf, executor) + state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, executor) if err != nil { return nil, nil, err } - nonce = state.Nonce + nonce = state.PendingNonce() } - nonce = nonce + 1 nonces[executor.String()] = nonce exec, err := action.NewExecutionWithAccessList( contractAddrs[i], @@ -423,7 +423,7 @@ func (sct *SmartContractTest) prepareBlockchain( sf, err = factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) } r.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) r.NoError(err) // create indexer indexer, err := blockindex.NewIndexer(db.NewMemKVStore(), cfg.Genesis.Hash()) @@ -509,7 +509,7 @@ func (sct *SmartContractTest) run(r *require.Assertions) { defer func() { r.NoError(bc.Stop(ctx)) }() - + ctx = genesis.WithGenesisContext(context.Background(), bc.Genesis()) // deploy smart contract contractAddresses := sct.deployContracts(bc, sf, dao, ap, r) if len(contractAddresses) == 0 { @@ -569,7 +569,7 @@ func (sct *SmartContractTest) run(r *require.Assertions) { } addr, err := address.FromString(account) r.NoError(err) - state, err := accountutil.AccountState(sf, addr) + state, err := accountutil.AccountState(ctx, sf, addr) r.NoError(err) r.Equal( 0, @@ -606,7 +606,6 @@ func TestProtocol_Handle(t *testing.T) { log.S().Info("Test EVM") require := require.New(t) - ctx := context.Background() cfg := config.Default defer func() { delete(cfg.Plugins, config.GatewayPlugin) @@ -632,6 +631,8 @@ func TestProtocol_Handle(t *testing.T) { cfg.Genesis.EnableGravityChainVoting = false cfg.ActPool.MinGasPriceStr = "0" cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(1000000000).String() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) + registry := protocol.NewRegistry() acc := account.NewProtocol(rewarding.DepositGas) require.NoError(acc.Register(registry)) @@ -640,7 +641,7 @@ func TestProtocol_Handle(t *testing.T) { // create state factory sf, err := factory.NewStateDB(cfg, factory.CachedStateDBOption(), factory.RegistryStateDBOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) // create indexer cfg.DB.DbPath = cfg.Chain.IndexDBPath @@ -693,7 +694,7 @@ func TestProtocol_Handle(t *testing.T) { require.NoError(err) // test IsContract - state, err := accountutil.AccountState(sf, contract) + state, err := accountutil.AccountState(ctx, sf, contract) require.NoError(err) require.True(state.IsContract()) diff --git a/action/protocol/execution/testdata-london/basic-token.json b/action/protocol/execution/testdata-london/basic-token.json index 39ae2a2d1a..f59be8685a 100644 --- a/action/protocol/execution/testdata-london/basic-token.json +++ b/action/protocol/execution/testdata-london/basic-token.json @@ -26,7 +26,7 @@ "rawGasLimit": 1000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "cd7bfe84e3fe161aeb958aa899cea602147a8edb25bcc4cc49f4753fa3410c17" ] @@ -42,7 +42,7 @@ "rawGasLimit": 1000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "cd7bfe84e3fe161aeb958aa899cea602147a8edb25bcc4cc49f4753fa3410c17" ] diff --git a/action/protocol/execution/testdata-london/datacopy.json b/action/protocol/execution/testdata-london/datacopy.json index 8fd715248a..862f1e42d3 100644 --- a/action/protocol/execution/testdata-london/datacopy.json +++ b/action/protocol/execution/testdata-london/datacopy.json @@ -30,9 +30,9 @@ "expectedStatus": 1, "comment": "the data of return is [0x11, 0x22, 0x33]", "expectedBlockInfos" : { - "txRootHash" : "3672945ca662bea4dd977e799374c5ce36c0c3e9ecbe98f1655f33439bbfe40c", - "stateRootHash" : "31d9f2c50c45877029ed9afa24e2052bfc36232e9b0d220adfb0f90ec941d86c", - "receiptRootHash" : "596f5fd6f5931b252cff495050859df5faffd86ca960d0222b907a31bc1f75ae" + "txRootHash" : "3d03a074dee9d9edb3dbd2bc30cf854c768e863ecf053c491fd71b2b1092c202", + "stateRootHash" : "3595fffd9f80f99887e3108d84f3558e2691ab9dc1c73f6279e3da5735d02afa", + "receiptRootHash" : "5182918a42865f1ebddb18ad846b9657c49592e4252a9f4234f224bfda05b738" } }] } diff --git a/action/protocol/execution/testdata-london/gas-test.json b/action/protocol/execution/testdata-london/gas-test.json index 361cd44673..7b6fa44944 100644 --- a/action/protocol/execution/testdata-london/gas-test.json +++ b/action/protocol/execution/testdata-london/gas-test.json @@ -67,7 +67,7 @@ "rawGasLimit": 6000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", @@ -333,7 +333,7 @@ "rawGasLimit": 6000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", diff --git a/action/protocol/execution/testdata-london/mapping-delete.json b/action/protocol/execution/testdata-london/mapping-delete.json index 7eeada4857..209b39a609 100644 --- a/action/protocol/execution/testdata-london/mapping-delete.json +++ b/action/protocol/execution/testdata-london/mapping-delete.json @@ -15,7 +15,7 @@ "rawGasLimit": 5000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb6", diff --git a/action/protocol/execution/testdata-london/maxtime.json b/action/protocol/execution/testdata-london/maxtime.json index c133254959..fe18122157 100644 --- a/action/protocol/execution/testdata-london/maxtime.json +++ b/action/protocol/execution/testdata-london/maxtime.json @@ -25,7 +25,7 @@ "rawGasLimit": 1000000, "rawGasPrice": "1", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000001", @@ -93,7 +93,7 @@ "rawGasLimit": 5000000, "rawGasPrice": "1", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000001", diff --git a/action/protocol/execution/testdata-london/reentry-attack.json b/action/protocol/execution/testdata-london/reentry-attack.json index 29adcc7324..82995b566f 100644 --- a/action/protocol/execution/testdata-london/reentry-attack.json +++ b/action/protocol/execution/testdata-london/reentry-attack.json @@ -27,16 +27,16 @@ "rawGasLimit": 5000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "67ec2fd251e5563c112b2534590ae74d23e6df19", + "address": "06Abb2Ca03834bd4f62C610CA7627E3dD12D9a97", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000002" ] },{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ - "809fddd0e44ad4227f52c39fc29ccd10b3c1d7ca546bc63db1a7bdde63de0cee" + "a13f8e0b4dc774404729f73c84108ed3304902e8d516606ec7c44c0bf6ad9f74" ] }], "rawExpectedGasConsumed": 228673, @@ -52,14 +52,14 @@ "rawGasLimit": 1000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "67ec2fd251e5563c112b2534590ae74d23e6df19", + "address": "06Abb2Ca03834bd4f62C610CA7627E3dD12D9a97", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000" ] },{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ - "809fddd0e44ad4227f52c39fc29ccd10b3c1d7ca546bc63db1a7bdde63de0cee" + "a13f8e0b4dc774404729f73c84108ed3304902e8d516606ec7c44c0bf6ad9f74" ] }], "rawExpectedGasConsumed": 81795, @@ -71,7 +71,7 @@ "account": "", "rawBalance": "2000000000000000000" },{ - "account": "io1q64m9jsrsd9afa3vvyx2wcn78hgjmx5h0y0kh6", + "account": "io1va03q4lcr608dr3nltwm64sfcz05czjuycsqgn", "rawBalance": "3000000000000000000" }], "comment": "attack" diff --git a/action/protocol/execution/testdata-london/remove-from-array.json b/action/protocol/execution/testdata-london/remove-from-array.json index 6ea867c6d1..4be95cabd6 100644 --- a/action/protocol/execution/testdata-london/remove-from-array.json +++ b/action/protocol/execution/testdata-london/remove-from-array.json @@ -26,7 +26,7 @@ "rawGasLimit": 1000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", diff --git a/action/protocol/execution/testdata-london/storage-test.json b/action/protocol/execution/testdata-london/storage-test.json index ad29218d18..0ee3eac03b 100644 --- a/action/protocol/execution/testdata-london/storage-test.json +++ b/action/protocol/execution/testdata-london/storage-test.json @@ -26,7 +26,7 @@ "rawGasLimit": 6000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", @@ -265,7 +265,7 @@ "rawGasLimit": 6000000, "rawGasPrice": "0", "rawAccessList": [{ - "address": "06abb2ca03834bd4f62c610ca7627e3dd12d9a97", + "address": "675f1057F81e9e768e33faddbd5609C09F4c0a5C", "storageKeys": [ "0000000000000000000000000000000000000000000000000000000000000000", "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57f", diff --git a/action/protocol/generic_validator.go b/action/protocol/generic_validator.go index 2d457c2924..863e2e5ab9 100644 --- a/action/protocol/generic_validator.go +++ b/action/protocol/generic_validator.go @@ -19,7 +19,7 @@ import ( type ( // AccountState defines a function to return the account state of a given address - AccountState func(StateReader, address.Address) (*state.Account, error) + AccountState func(context.Context, StateReader, address.Address) (*state.Account, error) // GenericValidator is the validator for generic action verification GenericValidator struct { accountState AccountState @@ -36,7 +36,7 @@ func NewGenericValidator(sr StateReader, accountState AccountState) *GenericVali } // Validate validates a generic action -func (v *GenericValidator) Validate(_ context.Context, selp action.SealedEnvelope) error { +func (v *GenericValidator) Validate(ctx context.Context, selp action.SealedEnvelope) error { intrinsicGas, err := selp.IntrinsicGas() if err != nil { return err @@ -54,14 +54,22 @@ func (v *GenericValidator) Validate(_ context.Context, selp action.SealedEnvelop return errors.New("failed to get address") } // Reject action if nonce is too low - confirmedState, err := v.accountState(v.sr, caller) - if err != nil { - return errors.Wrapf(err, "invalid state of account %s", caller.String()) + if action.IsSystemAction(selp) { + if selp.Nonce() != 0 { + return action.ErrSystemActionNonce + } + } else { + featureCtx, ok := GetFeatureCtx(ctx) + if ok && featureCtx.FixGasAndNonceUpdate || selp.Nonce() != 0 { + confirmedState, err := v.accountState(ctx, v.sr, caller) + if err != nil { + return errors.Wrapf(err, "invalid state of account %s", caller.String()) + } + if confirmedState.PendingNonce() > selp.Nonce() { + return action.ErrNonceTooLow + } + } } - pendingNonce := confirmedState.Nonce + 1 - if selp.Nonce() > 0 && pendingNonce > selp.Nonce() { - return action.ErrNonceTooLow - } return selp.Action().SanityCheck() } diff --git a/action/protocol/generic_validator_test.go b/action/protocol/generic_validator_test.go index 9814754785..c0b20f6c57 100644 --- a/action/protocol/generic_validator_test.go +++ b/action/protocol/generic_validator_test.go @@ -59,24 +59,39 @@ func TestActionProtoAndGenericValidator(t *testing.T) { }, ) - ctx = genesis.WithGenesisContext(ctx, config.Default.Genesis) + ctx = WithFeatureCtx(genesis.WithGenesisContext(ctx, config.Default.Genesis)) - valid := NewGenericValidator(nil, func(sr StateReader, addr address.Address) (*state.Account, error) { + valid := NewGenericValidator(nil, func(_ context.Context, sr StateReader, addr address.Address) (*state.Account, error) { pk := identityset.PrivateKey(27).PublicKey() eAddr := pk.Address() if strings.EqualFold(eAddr.String(), addr.String()) { return nil, errors.New("MockChainManager nonce error") } - return &state.Account{Nonce: 2}, nil + acct, err := state.NewAccount() + if err != nil { + return nil, err + } + if err := acct.SetPendingNonce(1); err != nil { + return nil, err + } + if err := acct.SetPendingNonce(2); err != nil { + return nil, err + } + if err := acct.SetPendingNonce(3); err != nil { + return nil, err + } + + return acct, nil }) data, err := hex.DecodeString("") require.NoError(err) t.Run("normal", func(t *testing.T) { - v, err := action.NewExecution("", 0, big.NewInt(10), uint64(10), big.NewInt(10), data) + v, err := action.NewExecution("", 3, big.NewInt(10), uint64(10), big.NewInt(10), data) require.NoError(err) bd := &action.EnvelopeBuilder{} elp := bd.SetGasPrice(big.NewInt(10)). SetGasLimit(uint64(100000)). + SetNonce(3). SetAction(v).Build() selp, err := action.Sign(elp, identityset.PrivateKey(28)) require.NoError(err) @@ -100,11 +115,12 @@ func TestActionProtoAndGenericValidator(t *testing.T) { require.Contains(err.Error(), action.ErrIntrinsicGas.Error()) }) t.Run("state error", func(t *testing.T) { - v, err := action.NewExecution("", 0, big.NewInt(10), uint64(10), big.NewInt(10), data) + v, err := action.NewExecution("", 1, big.NewInt(10), uint64(10), big.NewInt(10), data) require.NoError(err) bd := &action.EnvelopeBuilder{} elp := bd.SetGasPrice(big.NewInt(10)). SetGasLimit(uint64(100000)). + SetNonce(1). SetAction(v).Build() selp, err := action.Sign(elp, identityset.PrivateKey(27)) require.NoError(err) @@ -114,6 +130,21 @@ func TestActionProtoAndGenericValidator(t *testing.T) { require.Error(err) require.Contains(err.Error(), "invalid state of account") }) + t.Run("invalid system action nonce", func(t *testing.T) { + gr := action.GrantReward{} + gr.SetNonce(1) + bd := &action.EnvelopeBuilder{} + elp := bd.SetGasPrice(big.NewInt(10)). + SetNonce(1). + SetGasLimit(uint64(100000)). + SetAction(&gr).Build() + selp, err := action.Sign(elp, identityset.PrivateKey(28)) + require.NoError(err) + nselp, err := (&action.Deserializer{}).SetEvmNetworkID(_evmNetworkID).ActionToSealedEnvelope(selp.Proto()) + require.NoError(err) + err = valid.Validate(ctx, nselp) + require.Equal(action.ErrSystemActionNonce, errors.Cause(err)) + }) t.Run("nonce too low", func(t *testing.T) { v, err := action.NewExecution("", 1, big.NewInt(10), uint64(10), big.NewInt(10), data) require.NoError(err) diff --git a/action/protocol/poll/governance_protocol_test.go b/action/protocol/poll/governance_protocol_test.go index 1b701dd724..c986e1a94e 100644 --- a/action/protocol/poll/governance_protocol_test.go +++ b/action/protocol/poll/governance_protocol_test.go @@ -68,6 +68,7 @@ func initConstruct(ctrl *gomock.Controller) (Protocol, context.Context, protocol ctx, protocol.ActionCtx{}, ) + ctx = protocol.WithFeatureCtx(ctx) sm := mock_chainmanager.NewMockStateManager(ctrl) committee := mock_committee.NewMockCommittee(ctrl) diff --git a/action/protocol/poll/lifelong_protocol_test.go b/action/protocol/poll/lifelong_protocol_test.go index ec2285c0be..9bfce501ac 100644 --- a/action/protocol/poll/lifelong_protocol_test.go +++ b/action/protocol/poll/lifelong_protocol_test.go @@ -82,6 +82,7 @@ func TestCreateGenesisStates_WithLifeLong(t *testing.T) { require.NoError(err) ctx = protocol.WithFeatureWithHeightCtx(ctx) + ctx = protocol.WithFeatureCtx(ctx) require.NoError(p.CreateGenesisStates(ctx, sm)) } diff --git a/action/protocol/poll/staking_committee_test.go b/action/protocol/poll/staking_committee_test.go index a3434019af..fc2084bfbd 100644 --- a/action/protocol/poll/staking_committee_test.go +++ b/action/protocol/poll/staking_committee_test.go @@ -62,6 +62,7 @@ func initConstructStakingCommittee(ctrl *gomock.Controller) (Protocol, context.C Caller: producer, }, ) + ctx = protocol.WithFeatureCtx(ctx) sm := mock_chainmanager.NewMockStateManager(ctrl) committee := mock_committee.NewMockCommittee(ctrl) diff --git a/action/protocol/poll/util.go b/action/protocol/poll/util.go index 4096d38376..18b8676a83 100644 --- a/action/protocol/poll/util.go +++ b/action/protocol/poll/util.go @@ -168,16 +168,24 @@ func setCandidates( return errors.New("put poll result height should be epoch start height") } loadCandidatesLegacy := featureCtx.LoadCandidatesLegacy(height) + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } else { + accountCreationOpts = append(accountCreationOpts, state.DelegateCandidateOption()) + } for _, candidate := range candidates { addr, err := address.FromString(candidate.Address) if err != nil { return errors.Wrapf(err, "failed to decode delegate address %s", candidate.Address) } - delegate, err := accountutil.LoadOrCreateAccount(sm, addr) + delegate, err := accountutil.LoadOrCreateAccount(sm, addr, accountCreationOpts...) if err != nil { return errors.Wrapf(err, "failed to load or create the account for delegate %s", candidate.Address) } - delegate.IsCandidate = true + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + delegate.MarkAsCandidate() + } if loadCandidatesLegacy { if err := candidatesutil.LoadAndAddCandidates(sm, height, candidate.Address); err != nil { return err diff --git a/action/protocol/rewarding/fund.go b/action/protocol/rewarding/fund.go index 4b321a86cd..4b42c03131 100644 --- a/action/protocol/rewarding/fund.go +++ b/action/protocol/rewarding/fund.go @@ -20,6 +20,7 @@ import ( "github.com/iotexproject/iotex-core/action/protocol" accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" "github.com/iotexproject/iotex-core/action/protocol/rewarding/rewardingpb" + "github.com/iotexproject/iotex-core/state" ) // fund stores the balance of the rewarding fund. The difference between total and available balance should be @@ -65,18 +66,18 @@ func (p *Protocol) Deposit( transactionLogType iotextypes.TransactionLogType, ) (*action.TransactionLog, error) { actionCtx := protocol.MustGetActionCtx(ctx) - if err := p.assertAmount(amount); err != nil { - return nil, err - } - if err := p.assertEnoughBalance(actionCtx, sm, amount); err != nil { - return nil, err + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) } // Subtract balance from caller - acc, err := accountutil.LoadAccount(sm, actionCtx.Caller) + acc, err := accountutil.LoadAccount(sm, actionCtx.Caller, accountCreationOpts...) if err != nil { return nil, err } - acc.Balance = big.NewInt(0).Sub(acc.Balance, amount) + if err := acc.SubBalance(amount); err != nil { + return nil, err + } if err := accountutil.StoreAccount(sm, actionCtx.Caller, acc); err != nil { return nil, err } @@ -124,21 +125,6 @@ func (p *Protocol) AvailableBalance( return f.unclaimedBalance, height, nil } -func (p *Protocol) assertEnoughBalance( - actionCtx protocol.ActionCtx, - sm protocol.StateReader, - amount *big.Int, -) error { - acc, err := accountutil.LoadAccount(sm, actionCtx.Caller) - if err != nil { - return err - } - if acc.Balance.Cmp(amount) < 0 { - return errors.New("balance is not enough for donation") - } - return nil -} - // DepositGas deposits gas into the rewarding fund func DepositGas(ctx context.Context, sm protocol.StateManager, amount *big.Int) (*action.TransactionLog, error) { // If the gas fee is 0, return immediately diff --git a/action/protocol/rewarding/protocol.go b/action/protocol/rewarding/protocol.go index dea92ee31c..15df94adc4 100644 --- a/action/protocol/rewarding/protocol.go +++ b/action/protocol/rewarding/protocol.go @@ -214,17 +214,17 @@ func (p *Protocol) Handle( rlog, err := p.Deposit(ctx, sm, act.Amount(), iotextypes.TransactionLogType_DEPOSIT_TO_REWARDING_FUND) if err != nil { log.L().Debug("Error when handling rewarding action", zap.Error(err)) - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) + return p.settleUserAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) } - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil, rlog) + return p.settleUserAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil, rlog) case *action.ClaimFromRewardingFund: si := sm.Snapshot() rlog, err := p.Claim(ctx, sm, act.Amount()) if err != nil { log.L().Debug("Error when handling rewarding action", zap.Error(err)) - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) + return p.settleUserAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) } - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil, rlog) + return p.settleUserAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil, rlog) case *action.GrantReward: switch act.RewardType() { case action.BlockReward: @@ -232,20 +232,20 @@ func (p *Protocol) Handle( rewardLog, err := p.GrantBlockReward(ctx, sm) if err != nil { log.L().Debug("Error when handling rewarding action", zap.Error(err)) - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) + return p.settleSystemAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) } if rewardLog == nil { - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil) + return p.settleSystemAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, nil) } - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, []*action.Log{rewardLog}) + return p.settleSystemAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, []*action.Log{rewardLog}) case action.EpochReward: si := sm.Snapshot() rewardLogs, err := p.GrantEpochReward(ctx, sm) if err != nil { log.L().Debug("Error when handling rewarding action", zap.Error(err)) - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) + return p.settleSystemAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Failure), si, nil) } - return p.settleAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, rewardLogs) + return p.settleSystemAction(ctx, sm, uint64(iotextypes.ReceiptStatus_Success), si, rewardLogs) } } return nil, nil @@ -381,11 +381,34 @@ func (p *Protocol) deleteStateV2(sm protocol.StateManager, key []byte) error { return err } +func (p *Protocol) settleSystemAction( + ctx context.Context, + sm protocol.StateManager, + status uint64, + si int, + logs []*action.Log, + tLogs ...*action.TransactionLog, +) (*action.Receipt, error) { + return p.settleAction(ctx, sm, status, si, true, logs, tLogs...) +} + +func (p *Protocol) settleUserAction( + ctx context.Context, + sm protocol.StateManager, + status uint64, + si int, + logs []*action.Log, + tLogs ...*action.TransactionLog, +) (*action.Receipt, error) { + return p.settleAction(ctx, sm, status, si, false, logs, tLogs...) +} + func (p *Protocol) settleAction( ctx context.Context, sm protocol.StateManager, status uint64, si int, + isSystemAction bool, logs []*action.Log, tLogs ...*action.TransactionLog, ) (*action.Receipt, error) { @@ -396,28 +419,43 @@ func (p *Protocol) settleAction( return nil, err } } - gasFee := big.NewInt(0).Mul(actionCtx.GasPrice, big.NewInt(0).SetUint64(actionCtx.IntrinsicGas)) - depositLog, err := DepositGas(ctx, sm, gasFee) - if err != nil { - return nil, err - } - if depositLog != nil { - tLogs = append(tLogs, depositLog) - } - if err := p.increaseNonce(sm, actionCtx.Caller, actionCtx.Nonce); err != nil { - return nil, err + skipUpdateForSystemAction := protocol.MustGetFeatureCtx(ctx).FixGasAndNonceUpdate + if !isSystemAction || !skipUpdateForSystemAction { + gasFee := big.NewInt(0).Mul(actionCtx.GasPrice, big.NewInt(0).SetUint64(actionCtx.IntrinsicGas)) + depositLog, err := DepositGas(ctx, sm, gasFee) + if err != nil { + return nil, err + } + if depositLog != nil { + tLogs = append(tLogs, depositLog) + } + if err := p.increaseNonce( + ctx, + sm, + actionCtx.Caller, + actionCtx.Nonce, + !skipUpdateForSystemAction && actionCtx.Nonce == 0, + ); err != nil { + return nil, err + } } + return p.createReceipt(status, blkCtx.BlockHeight, actionCtx.ActionHash, actionCtx.IntrinsicGas, logs, tLogs...), nil } -func (p *Protocol) increaseNonce(sm protocol.StateManager, addr address.Address, nonce uint64) error { - acc, err := accountutil.LoadOrCreateAccount(sm, addr) +func (p *Protocol) increaseNonce(ctx context.Context, sm protocol.StateManager, addr address.Address, nonce uint64, skipSetNonce bool) error { + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } + acc, err := accountutil.LoadOrCreateAccount(sm, addr, accountCreationOpts...) if err != nil { return err } - // TODO: this check shouldn't be necessary - if nonce > acc.Nonce { - acc.Nonce = nonce + if !skipSetNonce { + if err := acc.SetPendingNonce(nonce + 1); err != nil { + return errors.Wrapf(err, "invalid nonce %d", nonce) + } } return accountutil.StoreAccount(sm, addr, acc) } diff --git a/action/protocol/rewarding/protocol_test.go b/action/protocol/rewarding/protocol_test.go index 4a2658c190..1b89025d43 100644 --- a/action/protocol/rewarding/protocol_test.go +++ b/action/protocol/rewarding/protocol_test.go @@ -364,6 +364,7 @@ func TestProtocol_Handle(t *testing.T) { protocol.ActionCtx{ Caller: identityset.Address(0), GasPrice: big.NewInt(0), + Nonce: 1, }, ) @@ -371,7 +372,7 @@ func TestProtocol_Handle(t *testing.T) { db := action.DepositToRewardingFundBuilder{} deposit := db.SetAmount(big.NewInt(1000000)).Build() eb1 := action.EnvelopeBuilder{} - e1 := eb1.SetNonce(0). + e1 := eb1.SetNonce(1). SetGasPrice(big.NewInt(0)). SetGasLimit(deposit.GasLimit()). SetAction(&deposit). @@ -390,11 +391,26 @@ func TestProtocol_Handle(t *testing.T) { e2 := createGrantRewardAction(0, uint64(0)) se2, err := action.Sign(e2, identityset.PrivateKey(0)) require.NoError(t, err) - + ctx = protocol.WithActionCtx( + ctx, + protocol.ActionCtx{ + Caller: identityset.Address(0), + GasPrice: big.NewInt(0), + Nonce: 0, + }, + ) receipt, err := p.Handle(ctx, se2.Action(), sm) require.NoError(t, err) assert.Equal(t, uint64(iotextypes.ReceiptStatus_Success), receipt.Status) assert.Equal(t, 1, len(receipt.Logs())) + ctx = protocol.WithActionCtx( + ctx, + protocol.ActionCtx{ + Caller: identityset.Address(0), + GasPrice: big.NewInt(0), + Nonce: 0, + }, + ) // Grant the block reward again should fail receipt, err = p.Handle(ctx, se2.Action(), sm) require.NoError(t, err) @@ -404,14 +420,21 @@ func TestProtocol_Handle(t *testing.T) { claimBuilder := action.ClaimFromRewardingFundBuilder{} claim := claimBuilder.SetAmount(big.NewInt(1000000)).Build() eb3 := action.EnvelopeBuilder{} - e3 := eb3.SetNonce(0). + e3 := eb3.SetNonce(4). SetGasPrice(big.NewInt(0)). SetGasLimit(claim.GasLimit()). SetAction(&claim). Build() se3, err := action.Sign(e3, identityset.PrivateKey(0)) require.NoError(t, err) - + ctx = protocol.WithActionCtx( + ctx, + protocol.ActionCtx{ + Caller: identityset.Address(0), + GasPrice: big.NewInt(0), + Nonce: 2, + }, + ) _, err = p.Handle(ctx, se3.Action(), sm) require.NoError(t, err) balance, _, err = p.TotalBalance(ctx, sm) diff --git a/action/protocol/rewarding/reward.go b/action/protocol/rewarding/reward.go index 5640c9f0a9..2e22bbcd87 100644 --- a/action/protocol/rewarding/reward.go +++ b/action/protocol/rewarding/reward.go @@ -388,13 +388,18 @@ func (p *Protocol) claimFromAccount(ctx context.Context, sm protocol.StateManage return err } } - + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } // Update primary account - primAcc, err := accountutil.LoadOrCreateAccount(sm, addr) + primAcc, err := accountutil.LoadOrCreateAccount(sm, addr, accountCreationOpts...) if err != nil { return err } - primAcc.Balance = big.NewInt(0).Add(primAcc.Balance, amount) + if err := primAcc.AddBalance(amount); err != nil { + return err + } return accountutil.StoreAccount(sm, addr, primAcc) } diff --git a/action/protocol/staking/handlers.go b/action/protocol/staking/handlers.go index 2c15ac6bda..9a9ad805b0 100644 --- a/action/protocol/staking/handlers.go +++ b/action/protocol/staking/handlers.go @@ -254,7 +254,9 @@ func (p *Protocol) handleWithdrawStake(ctx context.Context, act *action.Withdraw } // update withdrawer balance - withdrawer.AddBalance(bucket.StakedAmount) + if err := withdrawer.AddBalance(bucket.StakedAmount); err != nil { + return log, nil, errors.Wrapf(err, "failed to add balance %s", bucket.StakedAmount) + } // put updated withdrawer's account state to trie if err := accountutil.StoreAccount(csm.SM(), actionCtx.Caller, withdrawer); err != nil { return log, nil, errors.Wrapf(err, "failed to store account %s", actionCtx.Caller.String()) @@ -805,8 +807,11 @@ func (p *Protocol) fetchBucket( func fetchCaller(ctx context.Context, csm CandidateStateManager, amount *big.Int) (*state.Account, ReceiptError) { actionCtx := protocol.MustGetActionCtx(ctx) - - caller, err := accountutil.LoadAccount(csm.SM(), actionCtx.Caller) + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } + caller, err := accountutil.LoadAccount(csm.SM(), actionCtx.Caller, accountCreationOpts...) if err != nil { return nil, &handleError{ err: errors.Wrapf(err, "failed to load the account of caller %s", actionCtx.Caller.String()), @@ -815,7 +820,7 @@ func fetchCaller(ctx context.Context, csm CandidateStateManager, amount *big.Int } gasFee := big.NewInt(0).Mul(actionCtx.GasPrice, big.NewInt(0).SetUint64(actionCtx.IntrinsicGas)) // check caller's balance - if gasFee.Add(amount, gasFee).Cmp(caller.Balance) == 1 { + if !caller.HasSufficientBalance(new(big.Int).Add(amount, gasFee)) { return nil, &handleError{ err: errors.Wrapf(state.ErrNotEnoughBalance, "caller %s balance not enough", actionCtx.Caller.String()), failureStatus: iotextypes.ReceiptStatus_ErrNotEnoughBalance, diff --git a/action/protocol/staking/handlers_test.go b/action/protocol/staking/handlers_test.go index 5b29076dd7..8f5231c0db 100644 --- a/action/protocol/staking/handlers_test.go +++ b/action/protocol/staking/handlers_test.go @@ -27,6 +27,7 @@ import ( accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/pkg/unit" + "github.com/iotexproject/iotex-core/state" "github.com/iotexproject/iotex-core/test/identityset" "github.com/iotexproject/iotex-core/testutil/testdb" ) @@ -128,7 +129,7 @@ func TestProtocol_HandleCreateStake(t *testing.T) { false, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -143,7 +144,7 @@ func TestProtocol_HandleCreateStake(t *testing.T) { false, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -158,7 +159,7 @@ func TestProtocol_HandleCreateStake(t *testing.T) { false, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -232,7 +233,7 @@ func TestProtocol_HandleCreateStake(t *testing.T) { actCost, err := act.Cost() require.NoError(err) require.Equal(unit.ConvertIotxToRau(test.initBalance), big.NewInt(0).Add(caller.Balance, actCost)) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+1, caller.PendingNonce()) } } } @@ -266,7 +267,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1200000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -287,7 +288,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -308,7 +309,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 2, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -329,7 +330,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -350,7 +351,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "!invalid", identityset.Address(28).String(), identityset.Address(29).String(), @@ -371,7 +372,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -392,7 +393,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 2, "test2", identityset.Address(10).String(), identityset.Address(10).String(), @@ -411,9 +412,10 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { // act.OwnerAddress() is not nil,existing candidate, collide with existing name,this case cannot happen,b/c if ownerExist,it will return ReceiptStatus_ErrCandidateAlreadyExist // act.OwnerAddress() is not nil,existing candidate, collide with existing operator,this case cannot happen,b/c if ownerExist,it will return ReceiptStatus_ErrCandidateAlreadyExist // act.OwnerAddress() is not nil,new candidate, collide with existing name - {1201000, + { + 1201000, identityset.Address(27), - uint64(10), + 3, "test", identityset.Address(10).String(), identityset.Address(10).String(), @@ -431,9 +433,10 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { iotextypes.ReceiptStatus_ErrCandidateConflict, }, // act.OwnerAddress() is not nil,new candidate, collide with existing operator - {1201000, + { + 1201000, identityset.Address(27), - uint64(10), + 4, "test2", identityset.Address(28).String(), identityset.Address(10).String(), @@ -451,9 +454,10 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { iotextypes.ReceiptStatus_ErrCandidateConflict, }, // act.OwnerAddress() is nil,existing owner, but selfstake is not 0 - {1201000, + { + 1201000, identityset.Address(30), - uint64(10), + 1, "test2", identityset.Address(28).String(), identityset.Address(10).String(), @@ -473,9 +477,10 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { // act.OwnerAddress() is nil,existing candidate, collide with existing name,this case cannot happen,b/c if ownerExist,it will return ReceiptStatus_ErrCandidateAlreadyExist // act.OwnerAddress() is nil,existing candidate, collide with existing operator,this case cannot happen,b/c if ownerExist,it will return ReceiptStatus_ErrCandidateAlreadyExist // act.OwnerAddress() is nil,new candidate, collide with existing name - {1201000, + { + 1201000, identityset.Address(21), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(10).String(), @@ -493,9 +498,10 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { iotextypes.ReceiptStatus_ErrCandidateConflict, }, // act.OwnerAddress() is nil,new candidate, collide with existing operator - {1201000, + { + 1201000, identityset.Address(21), - uint64(10), + 2, "test2", identityset.Address(28).String(), identityset.Address(10).String(), @@ -593,7 +599,7 @@ func TestProtocol_HandleCandidateRegister(t *testing.T) { require.NoError(err) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, p.config.RegistrationConsts.Fee)) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+1, caller.PendingNonce()) } } } @@ -629,7 +635,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1200101, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -653,7 +659,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -677,7 +683,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(28).String(), identityset.Address(29).String(), @@ -701,7 +707,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(29).String(), identityset.Address(30).String(), @@ -725,7 +731,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(27).String(), identityset.Address(29).String(), @@ -749,7 +755,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { { 1201000, identityset.Address(27), - uint64(10), + 1, "test", identityset.Address(27).String(), identityset.Address(29).String(), @@ -842,14 +848,14 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { _, err = p.Handle(ctx, act, sm) require.NoError(err) - cu, err := action.NewCandidateUpdate(test.nonce, test.updateName, test.updateOperator, test.updateReward, test.gasLimit, test.gasPrice) + cu, err := action.NewCandidateUpdate(test.nonce+1, test.updateName, test.updateOperator, test.updateReward, test.gasLimit, test.gasPrice) require.NoError(err) intrinsic, _ = cu.IntrinsicGas() ctx = protocol.WithActionCtx(ctx, protocol.ActionCtx{ Caller: test.caller, GasPrice: test.gasPrice, IntrinsicGas: intrinsic, - Nonce: test.nonce, + Nonce: test.nonce + 1, }) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: 1, @@ -909,7 +915,7 @@ func TestProtocol_HandleCandidateUpdate(t *testing.T) { require.NoError(err) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, cuCost).Add(total, p.config.RegistrationConsts.Fee)) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+2, caller.PendingNonce()) } } } @@ -1077,8 +1083,9 @@ func TestProtocol_HandleUnstake(t *testing.T) { var createCost *big.Int ctx, createCost = initCreateStake(t, sm, test.caller, test.initBalance, big.NewInt(unit.Qev), gasLimit, nonce, blkHeight, test.blkTimestamp, gasLimit, p, candidate, test.amount, test.autoStake) - act, err := action.NewUnstake(nonce, test.index, - nil, gasLimit, gasPrice) + act, err := action.NewUnstake(nonce+1, test.index, nil, gasLimit, gasPrice) + require.NoError(err) + intrinsicGas, err := act.IntrinsicGas() require.NoError(err) if test.blkTimestamp != test.ctxTimestamp { blkCtx := protocol.MustGetBlockCtx(ctx) @@ -1086,6 +1093,12 @@ func TestProtocol_HandleUnstake(t *testing.T) { ctx = protocol.WithBlockCtx(ctx, blkCtx) } ctx = protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(ctx)) + ctx = protocol.WithActionCtx(ctx, protocol.ActionCtx{ + Caller: test.caller, + GasPrice: gasPrice, + IntrinsicGas: intrinsicGas, + Nonce: nonce + 1, + }) var r *action.Receipt if test.clear { csm, err := NewCandidateStateManager(sm, false) @@ -1137,7 +1150,7 @@ func TestProtocol_HandleUnstake(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(nonce, caller.Nonce) + require.Equal(nonce+2, caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, createCost)) } @@ -1148,13 +1161,13 @@ func TestProtocol_HandleUnstake(t *testing.T) { require.NoError(err) require.True(vb.isUnstaked()) - unstake, err := action.NewUnstake(nonce+1, 0, nil, gasLimit, gasPrice) + unstake, err := action.NewUnstake(nonce+2, 0, nil, gasLimit, gasPrice) require.NoError(err) - changeCand, err := action.NewChangeCandidate(nonce+1, candidate2.Name, 0, nil, gasLimit, gasPrice) + changeCand, err := action.NewChangeCandidate(nonce+2, candidate2.Name, 0, nil, gasLimit, gasPrice) require.NoError(err) - deposit, err := action.NewDepositToStake(nonce+1, 0, "10000", nil, gasLimit, gasPrice) + deposit, err := action.NewDepositToStake(nonce+2, 0, "10000", nil, gasLimit, gasPrice) require.NoError(err) - restake, err := action.NewRestake(nonce+1, 0, 0, false, nil, gasLimit, gasPrice) + restake, err := action.NewRestake(nonce+2, 0, 0, false, nil, gasLimit, gasPrice) require.NoError(err) unstakedBucketTests := []struct { @@ -1173,15 +1186,23 @@ func TestProtocol_HandleUnstake(t *testing.T) { // restake an unstaked bucket is allowed pre-Greenland {restake, false, iotextypes.ReceiptStatus_ErrNotEnoughBalance}, } - - for _, v := range unstakedBucketTests { + for i, v := range unstakedBucketTests { greenland := genesis.Default if v.greenland { blkCtx := protocol.MustGetBlockCtx(ctx) greenland.GreenlandBlockHeight = blkCtx.BlockHeight } + actCtx := protocol.MustGetActionCtx(ctx) + actCtx.Nonce = nonce + 2 + uint64(i) + ctx = protocol.WithActionCtx(ctx, actCtx) ctx = genesis.WithGenesisContext(ctx, greenland) ctx = protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(ctx)) + ctx = protocol.WithFeatureCtx(protocol.WithFeatureWithHeightCtx(ctx)) + ctx = protocol.WithActionCtx(ctx, protocol.ActionCtx{ + Caller: callerAddr, + GasPrice: gasPrice, + Nonce: nonce + 2 + uint64(i), + }) _, err = p.Start(ctx, sm) require.NoError(err) r, err := p.Handle(ctx, v.act, sm) @@ -1353,7 +1374,7 @@ func TestProtocol_HandleWithdrawStake(t *testing.T) { require.NoError(err) withdrawCost, err := withdraw.Cost() require.NoError(err) - require.EqualValues(3, caller.Nonce) + require.Equal(uint64(4), caller.PendingNonce()) total := big.NewInt(0) withdrawAmount, ok := new(big.Int).SetString(test.amount, 10) require.True(ok) @@ -1581,7 +1602,7 @@ func TestProtocol_HandleChangeCandidate(t *testing.T) { // candidate vote self,index 1 _, createCost := initCreateStake(t, sm, candidate.Owner, test.initBalance, big.NewInt(unit.Qev), test.gasLimit, test.nonce, test.blkHeight, test.blkTimestamp, test.blkGasLimit, p, candidate, test.amount, false) - act, err := action.NewChangeCandidate(test.nonce, test.candidateName, test.index, nil, test.gasLimit, test.gasPrice) + act, err := action.NewChangeCandidate(test.nonce+1, test.candidateName, test.index, nil, test.gasLimit, test.gasPrice) require.NoError(err) intrinsic, err := act.IntrinsicGas() require.NoError(err) @@ -1589,7 +1610,7 @@ func TestProtocol_HandleChangeCandidate(t *testing.T) { Caller: test.caller, GasPrice: test.gasPrice, IntrinsicGas: intrinsic, - Nonce: test.nonce, + Nonce: test.nonce + 1, }) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: test.blkHeight, @@ -1658,7 +1679,7 @@ func TestProtocol_HandleChangeCandidate(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+2, caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, createCost)) } @@ -1701,7 +1722,7 @@ func TestProtocol_HandleTransferStake(t *testing.T) { 0, big.NewInt(unit.Qev), 1000000000, - 1, + 2, 1, time.Now(), 10000, @@ -1757,7 +1778,7 @@ func TestProtocol_HandleTransferStake(t *testing.T) { 0, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -1776,7 +1797,7 @@ func TestProtocol_HandleTransferStake(t *testing.T) { 0, big.NewInt(unit.Qev), 10000, - 1, + 2, genesis.Default.HawaiiBlockHeight, time.Now(), 10000, @@ -1791,14 +1812,21 @@ func TestProtocol_HandleTransferStake(t *testing.T) { for _, test := range tests { sm, p, candi, candidate2 := initAll(t, ctrl) csr := newCandidateStateReader(sm) + nonce := uint64(1) + if test.caller.String() == candidate2.Owner.String() { + nonce++ + } ctx, createCost := initCreateStake(t, sm, candidate2.Owner, test.initBalance, big.NewInt(unit.Qev), 10000, 1, 1, time.Now(), 10000, p, candidate2, test.amount, false) if test.init { initCreateStake(t, sm, candi.Owner, test.initBalance, test.gasPrice, test.gasLimit, test.nonce, test.blkHeight, test.blkTimestamp, test.blkGasLimit, p, candi, test.amount, false) + if test.caller.String() == candi.Owner.String() { + nonce++ + } } else { require.NoError(setupAccount(sm, identityset.Address(1), 1)) } - act, err := action.NewTransferStake(test.nonce, test.to.String(), test.index, nil, test.gasLimit, test.gasPrice) + act, err := action.NewTransferStake(nonce, test.to.String(), test.index, nil, test.gasLimit, test.gasPrice) require.NoError(err) intrinsic, err := act.IntrinsicGas() require.NoError(err) @@ -1807,7 +1835,7 @@ func TestProtocol_HandleTransferStake(t *testing.T) { Caller: test.caller, GasPrice: test.gasPrice, IntrinsicGas: intrinsic, - Nonce: test.nonce, + Nonce: nonce, }) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: test.blkHeight, @@ -1859,7 +1887,7 @@ func TestProtocol_HandleTransferStake(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+1, caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, createCost)) } @@ -2092,7 +2120,7 @@ func TestProtocol_HandleConsignmentTransfer(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(uint64(1), caller.Nonce) + require.Equal(uint64(2), caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(initBalance), total.Add(total, caller.Balance).Add(total, actCost)) } @@ -2284,15 +2312,19 @@ func TestProtocol_HandleRestake(t *testing.T) { for _, test := range tests { sm, p, candidate, candidate2 := initAll(t, ctrl) csr := newCandidateStateReader(sm) - ctx, createCost := initCreateStake(t, sm, candidate2.Owner, test.initBalance, big.NewInt(unit.Qev), 10000, 1, 1, time.Now(), 10000, p, candidate2, test.amount, test.autoStake) + ctx, createCost := initCreateStake(t, sm, candidate2.Owner, test.initBalance, big.NewInt(unit.Qev), 10000, test.nonce, 1, time.Now(), 10000, p, candidate2, test.amount, test.autoStake) if test.newAccount { require.NoError(setupAccount(sm, test.caller, test.initBalance)) } else { candidate = candidate2 } + nonce := test.nonce + if test.caller.String() == candidate2.Owner.String() { + nonce++ + } - act, err := action.NewRestake(test.nonce, test.index, test.duration, test.autoStake, nil, test.gasLimit, test.gasPrice) + act, err := action.NewRestake(nonce, test.index, test.duration, test.autoStake, nil, test.gasLimit, test.gasPrice) require.NoError(err) intrinsic, err := act.IntrinsicGas() require.NoError(err) @@ -2300,7 +2332,7 @@ func TestProtocol_HandleRestake(t *testing.T) { Caller: test.caller, GasPrice: test.gasPrice, IntrinsicGas: intrinsic, - Nonce: test.nonce, + Nonce: nonce, }) ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ BlockHeight: 1, @@ -2358,7 +2390,7 @@ func TestProtocol_HandleRestake(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+2, caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, createCost)) } @@ -2403,7 +2435,7 @@ func TestProtocol_HandleDepositToStake(t *testing.T) { 0, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -2463,7 +2495,7 @@ func TestProtocol_HandleDepositToStake(t *testing.T) { 0, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -2483,7 +2515,7 @@ func TestProtocol_HandleDepositToStake(t *testing.T) { 0, big.NewInt(unit.Qev), 10000, - 1, + 2, 1, time.Now(), 10000, @@ -2580,7 +2612,7 @@ func TestProtocol_HandleDepositToStake(t *testing.T) { require.NoError(err) actCost, err := act.Cost() require.NoError(err) - require.Equal(test.nonce, caller.Nonce) + require.Equal(test.nonce+1, caller.PendingNonce()) total := big.NewInt(0) require.Equal(unit.ConvertIotxToRau(test.initBalance), total.Add(total, caller.Balance).Add(total, actCost).Add(total, createCost)) } @@ -2656,11 +2688,16 @@ func setupAccount(sm protocol.StateManager, addr address.Address, balance int64) if balance < 0 { return errors.New("balance cannot be negative") } - account, err := accountutil.LoadOrCreateAccount(sm, addr) + account, err := accountutil.LoadOrCreateAccount(sm, addr, state.LegacyNonceAccountTypeOption()) if err != nil { return err } - account.Balance = unit.ConvertIotxToRau(balance) + if err := account.SubBalance(account.Balance); err != nil { + return err + } + if err := account.AddBalance(unit.ConvertIotxToRau(balance)); err != nil { + return err + } return accountutil.StoreAccount(sm, addr, account) } @@ -2671,6 +2708,7 @@ func depositGas(ctx context.Context, sm protocol.StateManager, gasFee *big.Int) if err != nil { return nil, err } + // TODO: replace with SubBalance, and then change `Balance` to a function acc.Balance = big.NewInt(0).Sub(acc.Balance, gasFee) return nil, accountutil.StoreAccount(sm, actionCtx.Caller, acc) } diff --git a/action/protocol/staking/protocol.go b/action/protocol/staking/protocol.go index d00fcb5406..69c10fa304 100644 --- a/action/protocol/staking/protocol.go +++ b/action/protocol/staking/protocol.go @@ -517,13 +517,16 @@ func (p *Protocol) settleAction( if err != nil { return nil, errors.Wrap(err, "failed to deposit gas") } - acc, err := accountutil.LoadAccount(sm, actionCtx.Caller) + accountCreationOpts := []state.AccountCreationOption{} + if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount { + accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption()) + } + acc, err := accountutil.LoadAccount(sm, actionCtx.Caller, accountCreationOpts...) if err != nil { return nil, err } - // TODO: this check shouldn't be necessary - if actionCtx.Nonce > acc.Nonce { - acc.Nonce = actionCtx.Nonce + if err := acc.SetPendingNonce(actionCtx.Nonce + 1); err != nil { + return nil, errors.Wrap(err, "failed to set nonce") } if err := accountutil.StoreAccount(sm, actionCtx.Caller, acc); err != nil { return nil, errors.Wrap(err, "failed to update nonce") diff --git a/actpool/actpool.go b/actpool/actpool.go index 0fb18fe902..9d3018ec3a 100644 --- a/actpool/actpool.go +++ b/actpool/actpool.go @@ -24,6 +24,7 @@ import ( "github.com/iotexproject/iotex-core/action/protocol" accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/pkg/log" "github.com/iotexproject/iotex-core/pkg/prometheustimer" @@ -94,6 +95,7 @@ func EnableExperimentalActions() Option { type actPool struct { mutex sync.RWMutex cfg config.ActPool + g genesis.Genesis sf protocol.StateReader accountActs map[string]ActQueue accountDesActs map[string]map[hash.Hash256]action.SealedEnvelope @@ -106,7 +108,7 @@ type actPool struct { } // NewActPool constructs a new actpool -func NewActPool(sf protocol.StateReader, cfg config.ActPool, opts ...Option) (ActPool, error) { +func NewActPool(g genesis.Genesis, sf protocol.StateReader, cfg config.ActPool, opts ...Option) (ActPool, error) { if sf == nil { return nil, errors.New("Try to attach a nil state reader") } @@ -118,6 +120,7 @@ func NewActPool(sf protocol.StateReader, cfg config.ActPool, opts ...Option) (Ac ap := &actPool{ cfg: cfg, + g: g, sf: sf, senderBlackList: senderBlackList, accountActs: make(map[string]ActQueue), @@ -177,9 +180,10 @@ func (ap *actPool) PendingActionMap() map[string][]action.SealedEnvelope { // Remove the actions that are already timeout ap.reset() + ctx := ap.context(context.Background()) actionMap := make(map[string][]action.SealedEnvelope) for from, queue := range ap.accountActs { - actionMap[from] = append(actionMap[from], queue.PendingActs()...) + actionMap[from] = append(actionMap[from], queue.PendingActs(ctx)...) } return actionMap } @@ -188,7 +192,7 @@ func (ap *actPool) Add(ctx context.Context, act action.SealedEnvelope) error { ap.mutex.Lock() defer ap.mutex.Unlock() - ctx, span := tracer.NewSpan(ctx, "actPool.Add") + ctx, span := tracer.NewSpan(ap.context(ctx), "actPool.Add") defer span.End() // Reject action if pool space is full @@ -246,11 +250,12 @@ func (ap *actPool) GetPendingNonce(addr string) (uint64, error) { if queue, ok := ap.accountActs[addr]; ok { return queue.PendingNonce(), nil } - confirmedState, err := accountutil.AccountState(ap.sf, addrStr) + ctx := ap.context(context.Background()) + confirmedState, err := accountutil.AccountState(ctx, ap.sf, addrStr) if err != nil { return 0, err } - return confirmedState.Nonce + 1, err + return confirmedState.PendingNonce(), err } // GetUnconfirmedActs returns unconfirmed actions in pool given an account address @@ -363,13 +368,13 @@ func (ap *actPool) validate(ctx context.Context, selp action.SealedEnvelope) err func (ap *actPool) enqueueAction(ctx context.Context, addr address.Address, act action.SealedEnvelope, actHash hash.Hash256, actNonce uint64) error { span := tracer.SpanFromContext(ctx) defer span.End() - confirmedState, err := accountutil.AccountState(ap.sf, addr) + confirmedState, err := accountutil.AccountState(ctx, ap.sf, addr) if err != nil { _actpoolMtc.WithLabelValues("failedToGetNonce").Inc() return errors.Wrapf(err, "failed to get sender's nonce for action %x", actHash) } - confirmedNonce := confirmedState.Nonce - if actNonce <= confirmedNonce { + pendingNonce := confirmedState.PendingNonce() + if actNonce < pendingNonce { return action.ErrNonceTooLow } sender := addr.String() @@ -379,15 +384,15 @@ func (ap *actPool) enqueueAction(ctx context.Context, addr address.Address, act queue = NewActQueue(ap, sender, WithTimeOut(ap.cfg.ActionExpiry)) ap.accountActs[sender] = queue // Initialize pending nonce and balance for new account - queue.SetPendingNonce(confirmedNonce + 1) + queue.SetPendingNonce(pendingNonce) queue.SetPendingBalance(confirmedState.Balance) } - if actNonce-confirmedNonce >= ap.cfg.MaxNumActsPerAcct+1 { + if actNonce-pendingNonce >= ap.cfg.MaxNumActsPerAcct { // Nonce exceeds current range log.L().Debug("Rejecting action because nonce is too large.", log.Hex("hash", actHash[:]), - zap.Uint64("startNonce", confirmedNonce+1), + zap.Uint64("startNonce", pendingNonce), zap.Uint64("actNonce", actNonce)) _actpoolMtc.WithLabelValues("nonceTooLarge").Inc() return action.ErrNonceTooHigh @@ -444,15 +449,15 @@ func (ap *actPool) enqueueAction(ctx context.Context, addr address.Address, act } // removeConfirmedActs removes processed (committed to block) actions from pool -func (ap *actPool) removeConfirmedActs() { +func (ap *actPool) removeConfirmedActs(ctx context.Context) { for from, queue := range ap.accountActs { addr, _ := address.FromString(from) - confirmedState, err := accountutil.AccountState(ap.sf, addr) + confirmedState, err := accountutil.AccountState(ctx, ap.sf, addr) if err != nil { log.L().Error("Error when removing confirmed actions", zap.Error(err)) return } - pendingNonce := confirmedState.Nonce + 1 + pendingNonce := confirmedState.PendingNonce() // Remove all actions that are committed to new block acts := queue.FilterNonce(pendingNonce) ap.removeInvalidActs(acts) @@ -512,16 +517,21 @@ func (ap *actPool) updateAccount(sender string) { } } +func (ap *actPool) context(ctx context.Context) context.Context { + return genesis.WithGenesisContext(ctx, ap.g) +} + func (ap *actPool) reset() { timer := ap.timerFactory.NewTimer("reset") defer timer.End() + ctx := ap.context(context.Background()) // Remove confirmed actions in actpool - ap.removeConfirmedActs() + ap.removeConfirmedActs(ctx) for from, queue := range ap.accountActs { // Reset pending balance for each account addr, _ := address.FromString(from) - state, err := accountutil.AccountState(ap.sf, addr) + state, err := accountutil.AccountState(ctx, ap.sf, addr) if err != nil { log.L().Error("Error when resetting actpool state.", zap.Error(err)) return @@ -529,9 +539,7 @@ func (ap *actPool) reset() { queue.SetPendingBalance(state.Balance) // Reset pending nonce and remove invalid actions for each account - confirmedNonce := state.Nonce - pendingNonce := confirmedNonce + 1 - queue.SetPendingNonce(pendingNonce) + queue.SetPendingNonce(state.PendingNonce()) ap.updateAccount(from) } } diff --git a/actpool/actpool_test.go b/actpool/actpool_test.go index 8a6ab1a765..539fa89a85 100644 --- a/actpool/actpool_test.go +++ b/actpool/actpool_test.go @@ -64,25 +64,25 @@ func TestActPool_NewActPool(t *testing.T) { cfg := config.Default //error caused by nil blockchain - _, err := NewActPool(nil, cfg.ActPool, nil) + _, err := NewActPool(cfg.Genesis, nil, cfg.ActPool, nil) require.Error(err) // all good opt := EnableExperimentalActions() require.Panics(func() { blockchain.NewBlockchain(cfg, nil, nil, nil) }, "option is nil") sf := mock_chainmanager.NewMockStateReader(ctrl) - act, err := NewActPool(sf, cfg.ActPool, opt) + act, err := NewActPool(cfg.Genesis, sf, cfg.ActPool, opt) require.NoError(err) require.NotNil(act) // panic caused by option is nil - require.Panics(func() { NewActPool(sf, cfg.ActPool, nil) }, "option is nil") + require.Panics(func() { NewActPool(cfg.Genesis, sf, cfg.ActPool, nil) }, "option is nil") // error caused by option opt2 := func(pool *actPool) error { return errors.New("test error") } - _, err = NewActPool(sf, cfg.ActPool, opt2) + _, err = NewActPool(cfg.Genesis, sf, cfg.ActPool, opt2) require.Error(err) // test AddAction nil @@ -106,7 +106,7 @@ func TestValidate(t *testing.T) { mockError := errors.New("mock error") sev.EXPECT().Validate(gomock.Any(), gomock.Any()).Return(mockError).Times(1) apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(cfg.Genesis, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -129,21 +129,21 @@ func TestActPool_AddActs(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 cfg := &protocol.StateConfig{} for _, opt := range opts { opt(cfg) } if bytes.Equal(cfg.Key, identityset.Address(28).Bytes()) { - acct.Balance = big.NewInt(100) + require.NoError(acct.AddBalance(big.NewInt(100))) } else { - acct.Balance = big.NewInt(10) + require.NoError(acct.AddBalance(big.NewInt(10))) } return 0, nil }).AnyTimes() + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -166,7 +166,7 @@ func TestActPool_AddActs(t *testing.T) { tsf8, err := action.SignedTransfer(_addr2, _priKey2, uint64(4), big.NewInt(5), []byte{}, uint64(100000), big.NewInt(0)) require.NoError(err) - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) require.NoError(ap.Add(ctx, tsf1)) require.NoError(ap.Add(ctx, tsf2)) require.NoError(ap.Add(ctx, tsf3)) @@ -203,7 +203,7 @@ func TestActPool_AddActs(t *testing.T) { require.Error(ap.Add(ctx, tsf1)) require.Error(ap.Add(ctx, tsf4)) // Case III: Pool space/gas space is full - Ap2, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap2, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap2, ok := Ap2.(*actPool) require.True(ok) @@ -219,7 +219,7 @@ func TestActPool_AddActs(t *testing.T) { err = ap2.Add(ctx, tsf4) require.Equal(action.ErrTxPoolOverflow, errors.Cause(err)) - Ap3, err := NewActPool(sf, apConfig) + Ap3, err := NewActPool(genesis.Default, sf, apConfig) require.NoError(err) ap3, ok := Ap3.(*actPool) require.True(ok) @@ -294,9 +294,10 @@ func TestActPool_PickActs(t *testing.T) { ctrl := gomock.NewController(t) require := require.New(t) sf := mock_chainmanager.NewMockStateReader(ctrl) + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) createActPool := func(cfg config.ActPool) (*actPool, []action.SealedEnvelope, []action.SealedEnvelope, []action.SealedEnvelope) { // Create actpool - Ap, err := NewActPool(sf, cfg, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, cfg, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -326,29 +327,29 @@ func TestActPool_PickActs(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 cfg := &protocol.StateConfig{} for _, opt := range opts { opt(cfg) } if bytes.Equal(cfg.Key, identityset.Address(28).Bytes()) { - acct.Balance = big.NewInt(100) + require.NoError(acct.AddBalance(big.NewInt(100))) } else { - acct.Balance = big.NewInt(10) + require.NoError(acct.AddBalance(big.NewInt(10))) } return 0, nil }).AnyTimes() - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf2)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) - require.Equal(action.ErrInsufficientFunds, errors.Cause(ap.Add(context.Background(), tsf5))) - require.Error(ap.Add(context.Background(), tsf6)) - - require.Error(ap.Add(context.Background(), tsf7)) - require.NoError(ap.Add(context.Background(), tsf8)) - require.NoError(ap.Add(context.Background(), tsf9)) - require.NoError(ap.Add(context.Background(), tsf10)) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf2)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) + require.Equal(action.ErrInsufficientFunds, errors.Cause(ap.Add(ctx, tsf5))) + require.Error(ap.Add(ctx, tsf6)) + + require.Error(ap.Add(ctx, tsf7)) + require.NoError(ap.Add(ctx, tsf8)) + require.NoError(ap.Add(ctx, tsf9)) + require.NoError(ap.Add(ctx, tsf10)) return ap, []action.SealedEnvelope{tsf1, tsf2, tsf3, tsf4}, []action.SealedEnvelope{}, []action.SealedEnvelope{} } @@ -376,7 +377,7 @@ func TestActPool_removeConfirmedActs(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -394,27 +395,30 @@ func TestActPool_removeConfirmedActs(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 - acct.Balance = big.NewInt(100000000000000000) + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(8) - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf2)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf2)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) require.Equal(4, len(ap.allActions)) require.NotNil(ap.accountActs[_addr1]) sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 4 - acct.Balance = big.NewInt(100000000000000000) + for i := uint64(1); i <= 4; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(1) - ap.removeConfirmedActs() + ap.removeConfirmedActs(ctx) require.Equal(0, len(ap.allActions)) require.Nil(ap.accountActs[_addr1]) } @@ -441,31 +445,42 @@ func TestActPool_Reset(t *testing.T) { } switch { case bytes.Equal(cfg.Key, identityset.Address(28).Bytes()): - acct.Balance = new(big.Int).Set(balances[0]) - acct.Nonce = nonces[0] + require.NoError(acct.AddBalance(new(big.Int).Set(balances[0]))) + for i := uint64(1); i <= nonces[0]; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } case bytes.Equal(cfg.Key, identityset.Address(29).Bytes()): - acct.Balance = new(big.Int).Set(balances[1]) - acct.Nonce = nonces[1] + require.NoError(acct.AddBalance(new(big.Int).Set(balances[1]))) + for i := uint64(1); i <= nonces[1]; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } case bytes.Equal(cfg.Key, identityset.Address(30).Bytes()): - acct.Balance = new(big.Int).Set(balances[2]) - acct.Nonce = nonces[2] + require.NoError(acct.AddBalance(new(big.Int).Set(balances[2]))) + for i := uint64(1); i <= nonces[2]; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } case bytes.Equal(cfg.Key, identityset.Address(31).Bytes()): - acct.Balance = new(big.Int).Set(balances[3]) - acct.Nonce = nonces[3] + require.NoError(acct.AddBalance(new(big.Int).Set(balances[3]))) + for i := uint64(1); i <= nonces[3]; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } case bytes.Equal(cfg.Key, identityset.Address(32).Bytes()): - acct.Balance = new(big.Int).Set(balances[4]) - acct.Nonce = nonces[4] + require.NoError(acct.AddBalance(new(big.Int).Set(balances[4]))) + for i := uint64(1); i <= nonces[4]; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } } return 0, nil }).AnyTimes() + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() apConfig := getActPoolCfg() - Ap1, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap1, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap1, ok := Ap1.(*actPool) require.True(ok) ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) - Ap2, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap2, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap2, ok := Ap2.(*actPool) require.True(ok) @@ -491,7 +506,7 @@ func TestActPool_Reset(t *testing.T) { tsf9, err := action.SignedTransfer(_addr1, _priKey3, uint64(4), big.NewInt(100), []byte{}, uint64(20000), big.NewInt(0)) require.NoError(err) - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) require.NoError(ap1.Add(ctx, tsf1)) require.NoError(ap1.Add(ctx, tsf2)) err = ap1.Add(ctx, tsf3) @@ -778,7 +793,7 @@ func TestActPool_removeInvalidActs(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -795,15 +810,16 @@ func TestActPool_removeInvalidActs(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 - acct.Balance = big.NewInt(100000000000000000) + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(8) - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf2)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf2)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) hash1, err := tsf1.Hash() require.NoError(err) @@ -823,7 +839,7 @@ func TestActPool_GetPendingNonce(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -840,15 +856,16 @@ func TestActPool_GetPendingNonce(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 - acct.Balance = big.NewInt(100000000000000000) + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(10) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) nonce, err := ap.GetPendingNonce(_addr2) require.NoError(err) @@ -858,7 +875,7 @@ func TestActPool_GetPendingNonce(t *testing.T) { require.NoError(err) require.Equal(uint64(2), nonce) - require.NoError(ap.Add(context.Background(), tsf2)) + require.NoError(ap.Add(ctx, tsf2)) nonce, err = ap.GetPendingNonce(_addr1) require.NoError(err) require.Equal(uint64(5), nonce) @@ -870,7 +887,7 @@ func TestActPool_GetUnconfirmedActs(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -888,15 +905,16 @@ func TestActPool_GetUnconfirmedActs(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 - acct.Balance = big.NewInt(100000000000000000) + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(10) - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) - require.NoError(ap.Add(context.Background(), tsf5)) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) + require.NoError(ap.Add(ctx, tsf5)) acts := ap.GetUnconfirmedActs(_addr3) require.Equal([]action.SealedEnvelope(nil), acts) @@ -920,7 +938,7 @@ func TestActPool_GetActionByHash(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -954,7 +972,7 @@ func TestActPool_GetCapacity(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -968,7 +986,7 @@ func TestActPool_GetSize(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -988,26 +1006,29 @@ func TestActPool_GetSize(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 - acct.Balance = big.NewInt(100000000000000000) + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(8) - require.NoError(ap.Add(context.Background(), tsf1)) - require.NoError(ap.Add(context.Background(), tsf2)) - require.NoError(ap.Add(context.Background(), tsf3)) - require.NoError(ap.Add(context.Background(), tsf4)) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + require.NoError(ap.Add(ctx, tsf1)) + require.NoError(ap.Add(ctx, tsf2)) + require.NoError(ap.Add(ctx, tsf3)) + require.NoError(ap.Add(ctx, tsf4)) require.Equal(uint64(4), ap.GetSize()) require.Equal(uint64(40000), ap.GetGasSize()) sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 4 - acct.Balance = big.NewInt(100000000000000000) + for i := uint64(1); i <= 4; i++ { + require.NoError(acct.SetPendingNonce(i + 1)) + } + require.NoError(acct.AddBalance(big.NewInt(100000000000000000))) return 0, nil }).Times(1) - ap.removeConfirmedActs() + ap.removeConfirmedActs(ctx) require.Equal(uint64(0), ap.GetSize()) require.Equal(uint64(0), ap.GetGasSize()) } @@ -1017,7 +1038,7 @@ func TestActPool_AddActionNotEnoughGasPrice(t *testing.T) { sf := mock_chainmanager.NewMockStateReader(ctrl) apConfig := config.Default.ActPool - ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(t, err) tsf, err := action.SignedTransfer( identityset.Address(0).String(), @@ -1031,6 +1052,7 @@ func TestActPool_AddActionNotEnoughGasPrice(t *testing.T) { require.NoError(t, err) ctx := protocol.WithBlockchainCtx(context.Background(), protocol.BlockchainCtx{}) + ctx = genesis.WithGenesisContext(ctx, config.Default.Genesis) require.Error(t, ap.Add(ctx, tsf)) } @@ -1041,18 +1063,18 @@ func TestActPool_SpeedUpAction(t *testing.T) { sf.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(func(account interface{}, opts ...protocol.StateOption) (uint64, error) { acct, ok := account.(*state.Account) require.True(ok) - acct.Nonce = 0 cfg := &protocol.StateConfig{} for _, opt := range opts { opt(cfg) } - acct.Balance = big.NewInt(10000000) + require.NoError(acct.AddBalance(big.NewInt(10000000))) return 0, nil }).AnyTimes() + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() // Create actpool apConfig := getActPoolCfg() - Ap, err := NewActPool(sf, apConfig, EnableExperimentalActions()) + Ap, err := NewActPool(genesis.Default, sf, apConfig, EnableExperimentalActions()) require.NoError(err) ap, ok := Ap.(*actPool) require.True(ok) @@ -1066,7 +1088,7 @@ func TestActPool_SpeedUpAction(t *testing.T) { require.NoError(err) // A send action tsf1 with nonce 1, B send action tsf2 with nonce 1 - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) require.NoError(ap.Add(ctx, tsf1)) require.NoError(ap.Add(ctx, tsf2)) @@ -1117,8 +1139,15 @@ func (ap *actPool) getPendingNonce(addr string) (uint64, error) { if err != nil { return 0, err } - committedState, err := accountutil.AccountState(ap.sf, _addr1) - return committedState.Nonce + 1, err + committedState, err := accountutil.AccountState( + genesis.WithGenesisContext(context.Background(), config.Default.Genesis), + ap.sf, + _addr1, + ) + if err != nil { + return 0, err + } + return committedState.PendingNonce(), nil } // Helper function to return the correct pending balance just in case of empty queue @@ -1130,7 +1159,11 @@ func (ap *actPool) getPendingBalance(addr string) (*big.Int, error) { if err != nil { return nil, err } - state, err := accountutil.AccountState(ap.sf, _addr1) + state, err := accountutil.AccountState( + genesis.WithGenesisContext(context.Background(), config.Default.Genesis), + ap.sf, + _addr1, + ) if err != nil { return nil, err } diff --git a/actpool/actqueue.go b/actpool/actqueue.go index 7600b25893..c72af9cbb8 100644 --- a/actpool/actqueue.go +++ b/actpool/actqueue.go @@ -8,6 +8,7 @@ package actpool import ( "container/heap" + "context" "math/big" "sort" "time" @@ -68,7 +69,7 @@ type ActQueue interface { PendingBalance() *big.Int Len() int Empty() bool - PendingActs() []action.SealedEnvelope + PendingActs(context.Context) []action.SealedEnvelope AllActs() []action.SealedEnvelope } @@ -250,7 +251,7 @@ func (q *actQueue) Empty() bool { } // PendingActs creates a consecutive nonce-sorted slice of actions -func (q *actQueue) PendingActs() []action.SealedEnvelope { +func (q *actQueue) PendingActs(ctx context.Context) []action.SealedEnvelope { if q.Len() == 0 { return nil } @@ -260,12 +261,12 @@ func (q *actQueue) PendingActs() []action.SealedEnvelope { log.L().Error("Error when getting the address", zap.String("address", q.address), zap.Error(err)) return nil } - confirmedState, err := accountutil.AccountState(q.ap.sf, addr) + confirmedState, err := accountutil.AccountState(ctx, q.ap.sf, addr) if err != nil { log.L().Error("Error when getting the nonce", zap.String("address", q.address), zap.Error(err)) return nil } - nonce := confirmedState.Nonce + 1 + nonce := confirmedState.PendingNonce() for ; ; nonce++ { if _, exist := q.items[nonce]; !exist { break diff --git a/actpool/actqueue_test.go b/actpool/actqueue_test.go index 74e515826f..3e52da2b5e 100644 --- a/actpool/actqueue_test.go +++ b/actpool/actqueue_test.go @@ -7,6 +7,7 @@ package actpool import ( "container/heap" + "context" "fmt" "math/big" "math/rand" @@ -20,6 +21,7 @@ import ( "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/action/protocol" + "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/state" "github.com/iotexproject/iotex-core/test/identityset" @@ -129,9 +131,11 @@ func TestActQueuePendingActs(t *testing.T) { cfg := config.Default sf := mock_chainmanager.NewMockStateReader(ctrl) sf.EXPECT().State(gomock.Any(), gomock.Any()).Do(func(accountState *state.Account, _ protocol.StateOption) { - accountState.Nonce = uint64(1) + require.NoError(accountState.SetPendingNonce(accountState.PendingNonce() + 1)) }).Return(uint64(0), nil).Times(1) - ap, err := NewActPool(sf, cfg.ActPool, EnableExperimentalActions()) + sf.EXPECT().Height().Return(uint64(1), nil).AnyTimes() + ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis) + ap, err := NewActPool(cfg.Genesis, sf, cfg.ActPool, EnableExperimentalActions()) require.NoError(err) q := NewActQueue(ap.(*actPool), identityset.Address(0).String()).(*actQueue) tsf1, err := action.SignedTransfer(_addr2, _priKey1, 2, big.NewInt(100), nil, uint64(0), big.NewInt(0)) @@ -150,7 +154,7 @@ func TestActQueuePendingActs(t *testing.T) { require.NoError(q.Put(tsf4)) require.NoError(q.Put(tsf5)) q.pendingNonce = 4 - actions := q.PendingActs() + actions := q.PendingActs(ctx) require.Equal([]action.SealedEnvelope{tsf1, tsf2}, actions) } diff --git a/api/coreservice.go b/api/coreservice.go index 815ec411d4..7bd8cf1703 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -251,7 +251,8 @@ func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, return core.getProtocolAccount(ctx, addrStr) } span.AddEvent("accountutil.AccountStateWithHeight") - state, tipHeight, err := accountutil.AccountStateWithHeight(core.sf, addr) + ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis()) + state, tipHeight, err := accountutil.AccountStateWithHeight(ctx, core.sf, addr) if err != nil { return nil, nil, status.Error(codes.NotFound, err.Error()) } @@ -268,10 +269,10 @@ func (core *coreService) Account(addr address.Address) (*iotextypes.AccountMeta, if err != nil { return nil, nil, status.Error(codes.NotFound, err.Error()) } + // TODO: deprecate nonce field in account meta accountMeta := &iotextypes.AccountMeta{ Address: addrStr, Balance: state.Balance.String(), - Nonce: state.Nonce, PendingNonce: pendingNonce, NumActions: numActions, IsContract: state.IsContract(), @@ -453,14 +454,15 @@ func (core *coreService) ReadContract(ctx context.Context, callerAddr address.Ad return res.Data, res.Receipt, nil } } - state, err := accountutil.AccountState(core.sf, callerAddr) + ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis()) + state, err := accountutil.AccountState(ctx, core.sf, callerAddr) if err != nil { return "", nil, status.Error(codes.InvalidArgument, err.Error()) } if ctx, err = core.bc.Context(ctx); err != nil { return "", nil, err } - sc.SetNonce(state.Nonce + 1) + sc.SetNonce(state.PendingNonce()) blockGasLimit := core.bc.Genesis().BlockGasLimit if sc.GasLimit() == 0 || blockGasLimit < sc.GasLimit() { sc.SetGasLimit(blockGasLimit) @@ -1366,11 +1368,12 @@ func (core *coreService) EstimateGasForNonExecution(actType action.Action) (uint // EstimateExecutionGasConsumption estimate gas consumption for execution action func (core *coreService) EstimateExecutionGasConsumption(ctx context.Context, sc *action.Execution, callerAddr address.Address) (uint64, error) { - state, err := accountutil.AccountState(core.sf, callerAddr) + ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis()) + state, err := accountutil.AccountState(ctx, core.sf, callerAddr) if err != nil { return 0, status.Error(codes.InvalidArgument, err.Error()) } - sc.SetNonce(state.Nonce + 1) + sc.SetNonce(state.PendingNonce()) sc.SetGasPrice(big.NewInt(0)) blockGasLimit := core.bc.Genesis().BlockGasLimit sc.SetGasLimit(blockGasLimit) @@ -1557,7 +1560,8 @@ func (core *coreService) ReceiveBlock(blk *block.Block) error { } func (core *coreService) SimulateExecution(ctx context.Context, addr address.Address, exec *action.Execution) ([]byte, *action.Receipt, error) { - state, err := accountutil.AccountState(core.sf, addr) + ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis()) + state, err := accountutil.AccountState(ctx, core.sf, addr) if err != nil { return nil, nil, err } @@ -1566,7 +1570,7 @@ func (core *coreService) SimulateExecution(ctx context.Context, addr address.Add return nil, nil, err } // TODO (liuhaai): Use original nonce and gas limit properly - exec.SetNonce(state.Nonce + 1) + exec.SetNonce(state.PendingNonce()) if err != nil { return nil, nil, err } diff --git a/api/grpcserver_integrity_test.go b/api/grpcserver_integrity_test.go index 5ea1787bc9..426011048c 100644 --- a/api/grpcserver_integrity_test.go +++ b/api/grpcserver_integrity_test.go @@ -141,7 +141,7 @@ var ( {identityset.Address(30).String(), "io1d4c5lp4ea4754wy439g2t99ue7wryu5r2lslh2", "3", - 8, + 0, 9, 9, }, @@ -149,7 +149,7 @@ var ( identityset.Address(27).String(), "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms", "9999999999999999999999898950", - 5, + 0, 6, 6, }, @@ -2404,7 +2404,7 @@ func TestGrpcServer_GetEvmTransfersByBlockHeightIntegrity(t *testing.T) { func TestGrpcServer_GetActPoolActionsIntegrity(t *testing.T) { require := require.New(t) cfg := newConfig() - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) svr, _, _, _, _, actPool, bfIndexFile, err := createServerV2(cfg, false) require.NoError(err) diff --git a/api/serverV2_integrity_test.go b/api/serverV2_integrity_test.go index e580e05e82..180daed27a 100644 --- a/api/serverV2_integrity_test.go +++ b/api/serverV2_integrity_test.go @@ -285,7 +285,7 @@ func setupChain(cfg config.Config) (blockchain.Blockchain, blockdao.BlockDAO, bl if err != nil { return nil, nil, nil, nil, nil, nil, nil, "", err } - ap, err := setupActPool(sf, cfg.ActPool) + ap, err := setupActPool(cfg.Genesis, sf, cfg.ActPool) if err != nil { return nil, nil, nil, nil, nil, nil, nil, "", err } @@ -354,8 +354,8 @@ func setupChain(cfg config.Config) (blockchain.Blockchain, blockdao.BlockDAO, bl return bc, dao, indexer, bfIndexer, sf, ap, registry, testPath, nil } -func setupActPool(sf factory.Factory, cfg config.ActPool) (actpool.ActPool, error) { - ap, err := actpool.NewActPool(sf, cfg, actpool.EnableExperimentalActions()) +func setupActPool(g genesis.Genesis, sf factory.Factory, cfg config.ActPool) (actpool.ActPool, error) { + ap, err := actpool.NewActPool(g, sf, cfg, actpool.EnableExperimentalActions()) if err != nil { return nil, err } diff --git a/blockchain/block/validator_test.go b/blockchain/block/validator_test.go index ed4920a75b..8ddf9ff387 100644 --- a/blockchain/block/validator_test.go +++ b/blockchain/block/validator_test.go @@ -33,13 +33,16 @@ func TestValidator(t *testing.T) { v := NewValidator(nil) require.NoError(v.Validate(ctx, blk)) - valid := protocol.NewGenericValidator(nil, func(sr protocol.StateReader, addr address.Address) (*state.Account, error) { + valid := protocol.NewGenericValidator(nil, func(ctx context.Context, sr protocol.StateReader, addr address.Address) (*state.Account, error) { pk := identityset.PrivateKey(27).PublicKey() eAddr := pk.Address() if strings.EqualFold(eAddr.String(), addr.String()) { return nil, errors.New("MockChainManager nonce error") } - return &state.Account{Nonce: 2}, nil + account, err := state.NewAccount() + require.NoError(err) + require.NoError(account.SetPendingNonce(3)) + return account, nil }) tsf1, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(27), 1, big.NewInt(20), []byte{}, 100000, big.NewInt(10)) diff --git a/blockchain/integrity/benchmark_test.go b/blockchain/integrity/benchmark_test.go index eaf0d2a62d..cdba4e2e27 100644 --- a/blockchain/integrity/benchmark_test.go +++ b/blockchain/integrity/benchmark_test.go @@ -232,7 +232,7 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { return nil, nil, err } - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) if err != nil { return nil, nil, err } diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index 07ee66cc1c..40f6096395 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -191,10 +191,10 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block // Add block 8 // test store out of gas var ( - caller state.Account + caller = &state.Account{} callerAddr = hash.BytesToHash160(identityset.Address(27).Bytes()) ) - _, err = sf.State(&caller, protocol.LegacyKeyOption(callerAddr)) + _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) if err != nil { return err } @@ -216,7 +216,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block // Add block 9 // test store out of gas - _, err = sf.State(&caller, protocol.LegacyKeyOption(callerAddr)) + _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) if err != nil { return err } @@ -236,7 +236,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block } } - _, err = sf.State(&caller, protocol.LegacyKeyOption(callerAddr)) + _, err = sf.State(caller, protocol.LegacyKeyOption(callerAddr)) if err != nil { return err } @@ -245,7 +245,7 @@ func addTestingConstantinopleBlocks(bc blockchain.Blockchain, dao blockdao.Block } func addTestingTsfBlocks(cfg config.Config, bc blockchain.Blockchain, dao blockdao.BlockDAO, ap actpool.ActPool) error { - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) addOneTsf := func(recipientAddr string, senderPriKey iotexcrypto.PrivateKey, nonce uint64, amount *big.Int, payload []byte, gasLimit uint64, gasPrice *big.Int) error { tx, err := action.SignedTransfer(recipientAddr, senderPriKey, nonce, amount, payload, gasLimit, gasPrice) if err != nil { @@ -318,7 +318,7 @@ func addTestingTsfBlocks(cfg config.Config, bc blockchain.Blockchain, dao blockd if err != nil { return err } - if err := ap.Add(context.Background(), ex1); err != nil { + if err := ap.Add(ctx, ex1); err != nil { return err } _deployHash, err = ex1.Hash() @@ -481,7 +481,7 @@ func TestCreateBlockchain(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( @@ -532,7 +532,7 @@ func TestGetBlockHash(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( @@ -577,11 +577,12 @@ func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Block } } */ + ctx := genesis.WithGenesisContext(context.Background(), g) data, _ := hex.DecodeString("6080604052348015600f57600080fd5b5060de8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ee82ac5e14602d575b600080fd5b605660048036036020811015604157600080fd5b8101908080359060200190929190505050606c565b6040518082815260200191505060405180910390f35b60008082409050807f2d93f7749862d33969fb261757410b48065a1bc86a56da5c47820bd063e2338260405160405180910390a28091505091905056fea265627a7a723158200a258cd08ea99ee11aa68c78b6d2bf7ea912615a1e64a81b90a2abca2dd59cfa64736f6c634300050c0032") ex1, err := action.SignedExecution(action.EmptyAddress, priKey0, 1, big.NewInt(0), 500000, big.NewInt(testutil.TestGasPriceInt64), data) require.NoError(err) - require.NoError(ap.Add(context.Background(), ex1)) + require.NoError(ap.Add(ctx, ex1)) _deployHash, err = ex1.Hash() require.NoError(err) blk, err := bc.MintNewBlock(testutil.TimestampNow()) @@ -603,7 +604,7 @@ func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Block return hash.ZeroHash256, err } blockTime = blockTime.Add(time.Second) - if err := ap.Add(context.Background(), ex1); err != nil { + if err := ap.Add(ctx, ex1); err != nil { return hash.ZeroHash256, err } blk, err = bc.MintNewBlock(blockTime) @@ -680,11 +681,11 @@ func addTestingGetBlockHash(t *testing.T, g genesis.Genesis, bc blockchain.Block } func TestBlockchain_MintNewBlock(t *testing.T) { - ctx := context.Background() cfg := config.Default cfg.Genesis.BlockGasLimit = uint64(100000) cfg.Genesis.EnableGravityChainVoting = false cfg.ActPool.MinGasPriceStr = "0" + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) registry := protocol.NewRegistry() acc := account.NewProtocol(rewarding.DepositGas) require.NoError(t, acc.Register(registry)) @@ -692,7 +693,7 @@ func TestBlockchain_MintNewBlock(t *testing.T) { require.NoError(t, rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(t, err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( @@ -733,7 +734,7 @@ func TestBlockchain_MintNewBlock(t *testing.T) { SetGasPrice(big.NewInt(10)).Build() selp1, err := action.Sign(elp1, identityset.PrivateKey(0)) require.NoError(t, err) - require.NoError(t, ap.Add(context.Background(), selp1)) + require.NoError(t, ap.Add(ctx, selp1)) // This execution should not be included in block because block is out of gas elp2 := bd.SetAction(execution). SetNonce(2). @@ -741,7 +742,7 @@ func TestBlockchain_MintNewBlock(t *testing.T) { SetGasPrice(big.NewInt(10)).Build() selp2, err := action.Sign(elp2, identityset.PrivateKey(0)) require.NoError(t, err) - require.NoError(t, ap.Add(context.Background(), selp2)) + require.NoError(t, ap.Add(ctx, selp2)) blk, err := bc.MintNewBlock(testutil.TimestampNow()) require.NoError(t, err) @@ -755,16 +756,16 @@ func TestBlockchain_MintNewBlock(t *testing.T) { } func TestBlockchain_MintNewBlock_PopAccount(t *testing.T) { - ctx := context.Background() cfg := config.Default cfg.Genesis.EnableGravityChainVoting = false cfg.ActPool.MinGasPriceStr = "0" + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) registry := protocol.NewRegistry() acc := account.NewProtocol(rewarding.DepositGas) require.NoError(t, acc.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(t, err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( @@ -801,12 +802,12 @@ func TestBlockchain_MintNewBlock_PopAccount(t *testing.T) { tsf, err := action.SignedTransfer(addr1, priKey0, i+7, big.NewInt(2), bytes, 19000, big.NewInt(testutil.TestGasPriceInt64)) require.NoError(t, err) - require.NoError(t, ap.Add(context.Background(), tsf)) + require.NoError(t, ap.Add(ctx, tsf)) } transfer1, err := action.SignedTransfer(addr1, priKey3, 7, big.NewInt(2), []byte{}, 10000, big.NewInt(testutil.TestGasPriceInt64)) require.NoError(t, err) - require.NoError(t, ap.Add(context.Background(), transfer1)) + require.NoError(t, ap.Add(ctx, transfer1)) blk, err := bc.MintNewBlock(testutil.TimestampNow()) require.NoError(t, err) @@ -854,7 +855,7 @@ func TestConstantinople(t *testing.T) { // Create a blockchain from scratch sf, err := factory.NewFactory(cfg, factory.DefaultTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) acc := account.NewProtocol(rewarding.DepositGas) require.NoError(acc.Register(registry)) @@ -1088,13 +1089,13 @@ func TestConstantinople(t *testing.T) { func TestLoadBlockchainfromDB(t *testing.T) { require := require.New(t) testValidateBlockchain := func(cfg config.Config, t *testing.T) { - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) registry := protocol.NewRegistry() // Create a blockchain from scratch sf, err := factory.NewFactory(cfg, factory.DefaultTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) acc := account.NewProtocol(rewarding.DepositGas) require.NoError(acc.Register(registry)) @@ -1226,9 +1227,9 @@ func TestLoadBlockchainfromDB(t *testing.T) { // valid but unused address should return empty account addr, err := address.FromString("io1066kus4vlyvk0ljql39fzwqw0k22h7j8wmef3n") require.NoError(err) - act, err := accountutil.AccountState(sf, addr) + act, err := accountutil.AccountState(ctx, sf, addr) require.NoError(err) - require.Equal(uint64(0), act.Nonce) + require.Equal(uint64(1), act.PendingNonce()) require.Equal(big.NewInt(0), act.Balance) _, gateway := cfg.Plugins[config.GatewayPlugin] @@ -1405,7 +1406,7 @@ func TestBlockchainInitialCandidate(t *testing.T) { registry := protocol.NewRegistry() sf, err := factory.NewFactory(cfg, factory.DefaultTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) accountProtocol := account.NewProtocol(rewarding.DepositGas) require.NoError(accountProtocol.Register(registry)) @@ -1449,20 +1450,21 @@ func TestBlockchain_AccountState(t *testing.T) { // disable account-based testing // create chain cfg.Genesis.InitBalanceMap[identityset.Address(0).String()] = "100" + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) registry := protocol.NewRegistry() acc := account.NewProtocol(rewarding.DepositGas) require.NoError(acc.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) require.NoError(bc.Start(context.Background())) require.NotNil(bc) - s, err := accountutil.AccountState(sf, identityset.Address(0)) + s, err := accountutil.AccountState(ctx, sf, identityset.Address(0)) require.NoError(err) - require.Equal(uint64(0), s.Nonce) + require.Equal(uint64(1), s.PendingNonce()) require.Equal(big.NewInt(100), s.Balance) require.Equal(hash.ZeroHash256, s.Root) require.Equal([]byte(nil), s.CodeHash) @@ -1497,7 +1499,7 @@ func TestBlocks(t *testing.T) { require.NoError(acc.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath @@ -1570,7 +1572,7 @@ func TestActions(t *testing.T) { sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath @@ -1633,7 +1635,7 @@ func TestBlockchain_AddRemoveSubscriber(t *testing.T) { registry := protocol.NewRegistry() sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) req.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) req.NoError(err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain(cfg, dao, factory.NewMinter(sf, ap)) @@ -1658,11 +1660,12 @@ func testHistoryForAccount(t *testing.T, statetx bool) { a := identityset.Address(28) priKeyA := identityset.PrivateKey(28) b := identityset.Address(29) + ctx := genesis.WithGenesisContext(context.Background(), bc.Genesis()) // check the original balance a and b before transfer - AccountA, err := accountutil.AccountState(sf, a) + AccountA, err := accountutil.AccountState(ctx, sf, a) require.NoError(err) - AccountB, err := accountutil.AccountState(sf, b) + AccountB, err := accountutil.AccountState(ctx, sf, b) require.NoError(err) require.Equal(big.NewInt(100), AccountA.Balance) require.Equal(big.NewInt(100), AccountB.Balance) @@ -1679,23 +1682,23 @@ func testHistoryForAccount(t *testing.T, statetx bool) { require.NoError(bc.CommitBlock(blk)) // check balances after transfer - AccountA, err = accountutil.AccountState(sf, a) + AccountA, err = accountutil.AccountState(ctx, sf, a) require.NoError(err) - AccountB, err = accountutil.AccountState(sf, b) + AccountB, err = accountutil.AccountState(ctx, sf, b) require.NoError(err) require.Equal(big.NewInt(90), AccountA.Balance) require.Equal(big.NewInt(110), AccountB.Balance) // check history account's balance if statetx { - _, err = accountutil.AccountState(factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) + _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) require.Equal(factory.ErrNotSupported, errors.Cause(err)) - _, err = accountutil.AccountState(factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) + _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) require.Equal(factory.ErrNotSupported, errors.Cause(err)) } else { - AccountA, err = accountutil.AccountState(factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) + AccountA, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), a) require.NoError(err) - AccountB, err = accountutil.AccountState(factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) + AccountB, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), b) require.NoError(err) require.Equal(big.NewInt(100), AccountA.Balance) require.Equal(big.NewInt(100), AccountB.Balance) @@ -1710,13 +1713,14 @@ func TestHistoryForContract(t *testing.T) { func testHistoryForContract(t *testing.T, statetx bool) { require := require.New(t) bc, sf, _, dao, ap := newChain(t, statetx) + ctx := genesis.WithGenesisContext(context.Background(), bc.Genesis()) genesisAccount := identityset.Address(27).String() // deploy and get contract address contract := deployXrc20(bc, dao, ap, t) contractAddr, err := address.FromString(contract) require.NoError(err) - account, err := accountutil.AccountState(sf, contractAddr) + account, err := accountutil.AccountState(ctx, sf, contractAddr) require.NoError(err) // check the original balance balance := BalanceOfContract(contract, genesisAccount, sf, t, account.Root) @@ -1725,7 +1729,7 @@ func testHistoryForContract(t *testing.T, statetx bool) { require.Equal(expect, balance) // make a transfer for contract makeTransfer(contract, bc, ap, t) - account, err = accountutil.AccountState(sf, contractAddr) + account, err = accountutil.AccountState(ctx, sf, contractAddr) require.NoError(err) // check the balance after transfer balance = BalanceOfContract(contract, genesisAccount, sf, t, account.Root) @@ -1735,11 +1739,11 @@ func testHistoryForContract(t *testing.T, statetx bool) { // check the the original balance again if statetx { - _, err = accountutil.AccountState(factory.NewHistoryStateReader(sf, bc.TipHeight()-1), contractAddr) + _, err = accountutil.AccountState(ctx, factory.NewHistoryStateReader(sf, bc.TipHeight()-1), contractAddr) require.True(errors.Cause(err) == factory.ErrNotSupported) } else { sr := factory.NewHistoryStateReader(sf, bc.TipHeight()-1) - account, err = accountutil.AccountState(sr, contractAddr) + account, err = accountutil.AccountState(ctx, sr, contractAddr) require.NoError(err) balance = BalanceOfContract(contract, genesisAccount, sr, t, account.Root) expect, ok = new(big.Int).SetString("2000000000000000000000000000", 10) @@ -1842,7 +1846,7 @@ func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factor sf, err = factory.NewFactory(cfg, factory.PrecreatedTrieDBOption(kv), factory.RegistryOption(registry)) require.NoError(err) } - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) acc := account.NewProtocol(rewarding.DepositGas) require.NoError(acc.Register(registry)) diff --git a/blocksync/blocksync_test.go b/blocksync/blocksync_test.go index a788046d65..3e33a68a6c 100644 --- a/blocksync/blocksync_test.go +++ b/blocksync/blocksync_test.go @@ -179,7 +179,7 @@ func TestBlockSyncerProcessBlockTipHeight(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) @@ -241,7 +241,7 @@ func TestBlockSyncerProcessBlockOutOfOrder(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap1, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap1, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap1) require.NoError(err) ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) @@ -265,7 +265,7 @@ func TestBlockSyncerProcessBlockOutOfOrder(t *testing.T) { require.NoError(rp.Register(registry2)) sf2, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry2)) require.NoError(err) - ap2, err := actpool.NewActPool(sf2, cfg.ActPool, actpool.EnableExperimentalActions()) + ap2, err := actpool.NewActPool(cfg.Genesis, sf2, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap2) require.NoError(err) ap2.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf2, accountutil.AccountState)) @@ -336,7 +336,7 @@ func TestBlockSyncerProcessBlock(t *testing.T) { require.NoError(rolldposProtocol.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap1, err := actpool.NewActPool(sf, cfg.ActPool) + ap1, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NotNil(ap1) require.NoError(err) ap1.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) @@ -359,7 +359,7 @@ func TestBlockSyncerProcessBlock(t *testing.T) { require.NoError(rolldposProtocol.Register(registry2)) sf2, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry2)) require.NoError(err) - ap2, err := actpool.NewActPool(sf2, cfg.ActPool, actpool.EnableExperimentalActions()) + ap2, err := actpool.NewActPool(cfg.Genesis, sf2, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap2) require.NoError(err) ap2.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf2, accountutil.AccountState)) @@ -423,7 +423,7 @@ func TestBlockSyncerSync(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) @@ -508,7 +508,7 @@ func TestBlockSyncerPeerBlockList(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) diff --git a/blocksync/buffer_test.go b/blocksync/buffer_test.go index b9e159e1ac..cae44c0e7c 100644 --- a/blocksync/buffer_test.go +++ b/blocksync/buffer_test.go @@ -42,7 +42,7 @@ func TestBlockBufferFlush(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) ap.AddActionEnvelopeValidators(protocol.NewGenericValidator(sf, accountutil.AccountState)) @@ -133,7 +133,7 @@ func TestBlockBufferGetBlocksIntervalsToSync(t *testing.T) { require.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NotNil(ap) require.NoError(err) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) diff --git a/chainservice/builder.go b/chainservice/builder.go index 8c704983ee..e346b5e197 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -218,7 +218,7 @@ func (builder *Builder) createElectionCommittee() (committee.Committee, error) { func (builder *Builder) buildActionPool() error { if builder.cs.actpool == nil { - ac, err := actpool.NewActPool(builder.cs.factory, builder.cfg.ActPool) + ac, err := actpool.NewActPool(builder.cfg.Genesis, builder.cs.factory, builder.cfg.ActPool) if err != nil { return errors.Wrap(err, "failed to create actpool") } diff --git a/consensus/scheme/rolldpos/rolldpos_test.go b/consensus/scheme/rolldpos/rolldpos_test.go index c0450e8363..047f88a43c 100644 --- a/consensus/scheme/rolldpos/rolldpos_test.go +++ b/consensus/scheme/rolldpos/rolldpos_test.go @@ -411,7 +411,7 @@ func TestRollDPoSConsensus(t *testing.T) { protocol.WithRegistry(ctx, registry), cfg.Genesis, ))) - actPool, err := actpool.NewActPool(sf, cfg.ActPool, actpool.EnableExperimentalActions()) + actPool, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool, actpool.EnableExperimentalActions()) require.NoError(t, err) require.NoError(t, err) acc := account.NewProtocol(rewarding.DepositGas) diff --git a/consensus/scheme/rolldpos/roundcalculator_test.go b/consensus/scheme/rolldpos/roundcalculator_test.go index 72cada0d85..4959ad8328 100644 --- a/consensus/scheme/rolldpos/roundcalculator_test.go +++ b/consensus/scheme/rolldpos/roundcalculator_test.go @@ -182,7 +182,7 @@ func makeChain(t *testing.T) (blockchain.Blockchain, factory.Factory, actpool.Ac registry := protocol.NewRegistry() sf, err := factory.NewFactory(cfg, factory.DefaultTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath diff --git a/e2etest/bigint_test.go b/e2etest/bigint_test.go index 978eff251e..0bf82de6e4 100644 --- a/e2etest/bigint_test.go +++ b/e2etest/bigint_test.go @@ -44,15 +44,16 @@ func TestTransfer_Negative(t *testing.T) { ctx := context.Background() bc, sf, ap := prepareBlockchain(ctx, _executor, r) defer r.NoError(bc.Stop(ctx)) + ctx = genesis.WithGenesisContext(ctx, bc.Genesis()) addr, err := address.FromString(_executor) r.NoError(err) - stateBeforeTransfer, err := accountutil.AccountState(sf, addr) + stateBeforeTransfer, err := accountutil.AccountState(ctx, sf, addr) r.NoError(err) blk, err := prepareTransfer(bc, sf, ap, r) r.NoError(err) - r.Equal(2, len(blk.Actions)) - r.Error(bc.ValidateBlock(blk)) - state, err := accountutil.AccountState(sf, addr) + r.Equal(1, len(blk.Actions)) + r.NoError(bc.ValidateBlock(blk)) + state, err := accountutil.AccountState(ctx, sf, addr) r.NoError(err) r.Equal(0, state.Balance.Cmp(stateBeforeTransfer.Balance)) } @@ -64,14 +65,15 @@ func TestAction_Negative(t *testing.T) { defer r.NoError(bc.Stop(ctx)) addr, err := address.FromString(_executor) r.NoError(err) - stateBeforeTransfer, err := accountutil.AccountState(sf, addr) + ctx = genesis.WithGenesisContext(ctx, bc.Genesis()) + stateBeforeTransfer, err := accountutil.AccountState(ctx, sf, addr) r.NoError(err) blk, err := prepareAction(bc, sf, ap, r) r.NoError(err) r.NotNil(blk) - r.Equal(2, len(blk.Actions)) - r.Error(bc.ValidateBlock(blk)) - state, err := accountutil.AccountState(sf, addr) + r.Equal(1, len(blk.Actions)) + r.NoError(bc.ValidateBlock(blk)) + state, err := accountutil.AccountState(ctx, sf, addr) r.NoError(err) r.Equal(0, state.Balance.Cmp(stateBeforeTransfer.Balance)) } @@ -88,8 +90,10 @@ func prepareBlockchain(ctx context.Context, _executor string, r *require.Asserti r.NoError(rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) r.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + genericValidator := protocol.NewGenericValidator(sf, accountutil.AccountState) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) r.NoError(err) + ap.AddActionEnvelopeValidators(genericValidator) dao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( cfg, @@ -97,7 +101,7 @@ func prepareBlockchain(ctx context.Context, _executor string, r *require.Asserti factory.NewMinter(sf, ap), blockchain.BlockValidatorOption(block.NewValidator( sf, - protocol.NewGenericValidator(sf, accountutil.AccountState), + genericValidator, )), ) r.NotNil(bc) @@ -141,7 +145,7 @@ func prepare(bc blockchain.Blockchain, sf factory.Factory, ap actpool.ActPool, e r.NoError(err) selp, err := action.Sign(elp, priKey) r.NoError(err) - r.NoError(ap.Add(context.Background(), selp)) + r.Error(ap.Add(context.Background(), selp)) blk, err := bc.MintNewBlock(testutil.TimestampNow()) r.NoError(err) // when validate/commit a blk, the workingset and receipts of blk should be nil diff --git a/e2etest/local_test.go b/e2etest/local_test.go index b5ca659a6a..ec5cd15d17 100644 --- a/e2etest/local_test.go +++ b/e2etest/local_test.go @@ -71,7 +71,7 @@ func TestLocalCommit(t *testing.T) { }() // create server - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) svr, err := itx.NewServer(cfg) require.NoError(err) require.NoError(svr.Start(ctx)) @@ -86,7 +86,7 @@ func TestLocalCommit(t *testing.T) { require.NotNil(sf) require.NotNil(ap) - i27State, err := accountutil.AccountState(sf, identityset.Address(27)) + i27State, err := accountutil.AccountState(ctx, sf, identityset.Address(27)) require.NoError(err) require.NoError(addTestingTsfBlocks(bc, ap)) require.EqualValues(5, bc.TipHeight()) @@ -104,12 +104,12 @@ func TestLocalCommit(t *testing.T) { {32, "100"}, {33, "5242883"}, } { - s, err := accountutil.AccountState(sf, identityset.Address(v.addrIndex)) + s, err := accountutil.AccountState(ctx, sf, identityset.Address(v.addrIndex)) require.NoError(err) require.Equal(v.balance, s.Balance.String()) change.Add(change, s.Balance) } - s, err := accountutil.AccountState(sf, identityset.Address(27)) + s, err := accountutil.AccountState(ctx, sf, identityset.Address(27)) require.NoError(err) change.Add(change, s.Balance) change.Sub(change, i27State.Balance) @@ -157,7 +157,7 @@ func TestLocalCommit(t *testing.T) { registry := protocol.NewRegistry() sf2, err := factory.NewStateDB(cfg, factory.CachedStateDBOption(), factory.RegistryStateDBOption(registry)) require.NoError(err) - ap2, err := actpool.NewActPool(sf2, cfg.ActPool) + ap2, err := actpool.NewActPool(cfg.Genesis, sf2, cfg.ActPool) require.NoError(err) dbcfg := cfg.DB dbcfg.DbPath = cfg.Chain.ChainDBPath @@ -190,8 +190,8 @@ func TestLocalCommit(t *testing.T) { // transfer 1 // C --> A - s, _ = accountutil.AccountState(sf, identityset.Address(30)) - tsf1, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(30), s.Nonce+1, big.NewInt(1), []byte{}, 100000, big.NewInt(0)) + s, _ = accountutil.AccountState(ctx, sf, identityset.Address(30)) + tsf1, err := action.SignedTransfer(identityset.Address(28).String(), identityset.PrivateKey(30), s.PendingNonce(), big.NewInt(1), []byte{}, 100000, big.NewInt(0)) require.NoError(err) require.NoError(ap2.Add(context.Background(), tsf1)) @@ -211,8 +211,8 @@ func TestLocalCommit(t *testing.T) { // transfer 2 // F --> D - s, _ = accountutil.AccountState(sf, identityset.Address(33)) - tsf2, err := action.SignedTransfer(identityset.Address(31).String(), identityset.PrivateKey(33), s.Nonce+1, big.NewInt(1), []byte{}, 100000, big.NewInt(0)) + s, _ = accountutil.AccountState(ctx, sf, identityset.Address(33)) + tsf2, err := action.SignedTransfer(identityset.Address(31).String(), identityset.PrivateKey(33), s.PendingNonce(), big.NewInt(1), []byte{}, 100000, big.NewInt(0)) require.NoError(err) require.NoError(ap2.Add(context.Background(), tsf2)) @@ -232,8 +232,8 @@ func TestLocalCommit(t *testing.T) { // transfer 3 // B --> B - s, _ = accountutil.AccountState(sf, identityset.Address(29)) - tsf3, err := action.SignedTransfer(identityset.Address(29).String(), identityset.PrivateKey(29), s.Nonce+1, big.NewInt(1), []byte{}, 100000, big.NewInt(0)) + s, _ = accountutil.AccountState(ctx, sf, identityset.Address(29)) + tsf3, err := action.SignedTransfer(identityset.Address(29).String(), identityset.PrivateKey(29), s.PendingNonce(), big.NewInt(1), []byte{}, 100000, big.NewInt(0)) require.NoError(err) require.NoError(ap2.Add(context.Background(), tsf3)) @@ -253,8 +253,8 @@ func TestLocalCommit(t *testing.T) { // transfer 4 // test --> E - s, _ = accountutil.AccountState(sf, identityset.Address(27)) - tsf4, err := action.SignedTransfer(identityset.Address(32).String(), identityset.PrivateKey(27), s.Nonce+1, big.NewInt(1), []byte{}, 100000, big.NewInt(0)) + s, _ = accountutil.AccountState(ctx, sf, identityset.Address(27)) + tsf4, err := action.SignedTransfer(identityset.Address(32).String(), identityset.PrivateKey(27), s.PendingNonce(), big.NewInt(1), []byte{}, 100000, big.NewInt(0)) require.NoError(err) require.NoError(ap2.Add(context.Background(), tsf4)) @@ -296,12 +296,12 @@ func TestLocalCommit(t *testing.T) { {32, "101"}, {33, "5242882"}, } { - s, err = accountutil.AccountState(sf, identityset.Address(v.addrIndex)) + s, err = accountutil.AccountState(ctx, sf, identityset.Address(v.addrIndex)) require.NoError(err) require.Equal(v.balance, s.Balance.String()) change.Add(change, s.Balance) } - s, err = accountutil.AccountState(sf, identityset.Address(27)) + s, err = accountutil.AccountState(ctx, sf, identityset.Address(27)) require.NoError(err) change.Add(change, s.Balance) change.Sub(change, i27State.Balance) diff --git a/e2etest/local_transfer_test.go b/e2etest/local_transfer_test.go index 5488414a5d..acc948f6bd 100644 --- a/e2etest/local_transfer_test.go +++ b/e2etest/local_transfer_test.go @@ -34,6 +34,7 @@ import ( "github.com/iotexproject/iotex-core/actpool" "github.com/iotexproject/iotex-core/blockchain" "github.com/iotexproject/iotex-core/blockchain/blockdao" + "github.com/iotexproject/iotex-core/blockchain/genesis" "github.com/iotexproject/iotex-core/config" "github.com/iotexproject/iotex-core/pkg/probe" "github.com/iotexproject/iotex-core/pkg/unit" @@ -348,7 +349,7 @@ func TestLocalTransfer(t *testing.T) { require.NoError(err) // Create and start probe server - ctx := context.Background() + ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis) probeSvr := probe.New(7788) require.NoError(probeSvr.Start(ctx)) @@ -418,7 +419,7 @@ func TestLocalTransfer(t *testing.T) { senderAddr1, err := address.FromString(senderAddr) require.NoError(err) - newSenderState, _ := accountutil.AccountState(sf, senderAddr1) + newSenderState, _ := accountutil.AccountState(ctx, sf, senderAddr1) minusAmount := big.NewInt(0).Sub(tsfTest.senderBalance, tsfTest.amount) gasUnitPayloadConsumed := big.NewInt(0).Mul(big.NewInt(int64(action.TransferPayloadGas)), big.NewInt(int64(len(tsfTest.payload)))) @@ -430,7 +431,7 @@ func TestLocalTransfer(t *testing.T) { recvAddr1, err := address.FromString(recvAddr) require.NoError(err) - newRecvState, err := accountutil.AccountState(sf, recvAddr1) + newRecvState, err := accountutil.AccountState(ctx, sf, recvAddr1) require.NoError(err) expectedRecvrBalance := big.NewInt(0) if tsfTest.recvAcntState == AcntNotRegistered { @@ -480,7 +481,7 @@ func TestLocalTransfer(t *testing.T) { if tsfTest.senderAcntState == AcntCreate || tsfTest.senderAcntState == AcntExist { senderAddr1, err := address.FromString(senderAddr) require.NoError(err) - newSenderState, _ := accountutil.AccountState(sf, senderAddr1) + newSenderState, _ := accountutil.AccountState(ctx, sf, senderAddr1) require.Equal(tsfTest.senderBalance.String(), newSenderState.Balance.String()) } @@ -543,7 +544,8 @@ func initStateKeyAddr( return nil, "", errors.New("failed to get address") } retAddr = addr.String() - existState, err := accountutil.AccountState(sf, addr) + ctx := genesis.WithGenesisContext(context.Background(), bc.Genesis()) + existState, err := accountutil.AccountState(ctx, sf, addr) if err != nil { return nil, "", err } @@ -647,7 +649,7 @@ func TestEnforceChainID(t *testing.T) { require.NoError(acc.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(err) blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( diff --git a/e2etest/rewarding_test.go b/e2etest/rewarding_test.go index 9154a1808e..55bdf05eef 100644 --- a/e2etest/rewarding_test.go +++ b/e2etest/rewarding_test.go @@ -264,13 +264,14 @@ func TestBlockEpochReward(t *testing.T) { rewardAddr := identityset.Address(i + numNodes) rewardAddrStr := identityset.Address(i + numNodes).String() exptUnclaimed[rewardAddrStr] = big.NewInt(0) - initState, err := accountutil.AccountState(sfs[i], rewardAddr) + ctx := genesis.WithGenesisContext(context.Background(), configs[i].Genesis) + initState, err := accountutil.AccountState(ctx, sfs[i], rewardAddr) require.NoError(t, err) initBalances[rewardAddrStr] = initState.Balance operatorAddr := identityset.Address(i) operatorAddrStr := identityset.Address(i).String() - initState, err = accountutil.AccountState(sfs[i], operatorAddr) + initState, err = accountutil.AccountState(ctx, sfs[i], operatorAddr) require.NoError(t, err) initBalances[operatorAddrStr] = initState.Balance @@ -456,7 +457,11 @@ func TestBlockEpochReward(t *testing.T) { //Check Reward address balance rewardAddr := identityset.Address(i + numNodes) rewardAddrStr := rewardAddr.String() - endState, err := accountutil.AccountState(sfs[0], rewardAddr) + endState, err := accountutil.AccountState( + genesis.WithGenesisContext(context.Background(), configs[0].Genesis), + sfs[0], + rewardAddr, + ) require.NoError(t, err) fmt.Println("Server ", i, " ", rewardAddrStr, " Closing Balance ", endState.Balance.String()) expectBalance := big.NewInt(0).Add(initBalances[rewardAddrStr], claimedAmount[rewardAddrStr]) @@ -466,7 +471,11 @@ func TestBlockEpochReward(t *testing.T) { //Make sure the non-reward addresses have not received money operatorAddr := identityset.Address(i) operatorAddrStr := identityset.Address(i).String() - operatorState, err := accountutil.AccountState(sfs[i], operatorAddr) + operatorState, err := accountutil.AccountState( + genesis.WithGenesisContext(context.Background(), configs[i].Genesis), + sfs[i], + operatorAddr, + ) require.NoError(t, err) require.Equal(t, initBalances[operatorAddrStr], operatorState.Balance) } diff --git a/e2etest/staking_test.go b/e2etest/staking_test.go index afbd16c8fc..46f5236cda 100644 --- a/e2etest/staking_test.go +++ b/e2etest/staking_test.go @@ -58,8 +58,8 @@ func TestStakingContract(t *testing.T) { require.NotNil(registry) admin := identityset.PrivateKey(26) state0 := hash.BytesToHash160(identityset.Address(26).Bytes()) - var s state.Account - _, err = sf.State(&s, protocol.LegacyKeyOption(state0)) + s := &state.Account{} + _, err = sf.State(s, protocol.LegacyKeyOption(state0)) require.NoError(err) require.Equal(unit.ConvertIotxToRau(100000000), s.Balance) @@ -101,7 +101,7 @@ func TestStakingContract(t *testing.T) { require.NoError(bc.CommitBlock(blk)) state0 = hash.BytesToHash160(identityset.Address(i).Bytes()) - _, err = sf.State(&s, protocol.LegacyKeyOption(state0)) + _, err = sf.State(s, protocol.LegacyKeyOption(state0)) require.NoError(err) require.Equal(unit.ConvertIotxToRau(100000000-int64(numBucket)*200), s.Balance) } diff --git a/gasstation/gasstattion_test.go b/gasstation/gasstattion_test.go index 30bf3295af..f55882be76 100644 --- a/gasstation/gasstattion_test.go +++ b/gasstation/gasstattion_test.go @@ -48,7 +48,7 @@ func TestSuggestGasPriceForUserAction(t *testing.T) { require.NoError(t, rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(t, err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( @@ -124,7 +124,7 @@ func TestSuggestGasPriceForSystemAction(t *testing.T) { require.NoError(t, rp.Register(registry)) sf, err := factory.NewFactory(cfg, factory.InMemTrieOption(), factory.RegistryOption(registry)) require.NoError(t, err) - ap, err := actpool.NewActPool(sf, cfg.ActPool) + ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool) require.NoError(t, err) blkMemDao := blockdao.NewBlockDAOInMemForTest([]blockdao.BlockIndexer{sf}) bc := blockchain.NewBlockchain( diff --git a/go.mod b/go.mod index 073442b341..5cae8afb25 100644 --- a/go.mod +++ b/go.mod @@ -184,6 +184,6 @@ require ( gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) -replace github.com/ethereum/go-ethereum => github.com/iotexproject/go-ethereum v0.4.0 +replace github.com/ethereum/go-ethereum => github.com/iotexproject/go-ethereum v1.7.4-0.20220515212948-4dae4279da68 replace golang.org/x/xerrors => golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 diff --git a/go.sum b/go.sum index 08fc6e57af..3df956ea5f 100644 --- a/go.sum +++ b/go.sum @@ -438,8 +438,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/iotexproject/go-ethereum v0.4.0 h1:3GX+vZTI6KeazPabaw3oyLpPl1dOuyJyqqGpWspi1Gs= -github.com/iotexproject/go-ethereum v0.4.0/go.mod h1:pJNuIUYfX5+JKzSD/BTdNsvJSZ1TJqmz0dVyXMAbf6M= +github.com/iotexproject/go-ethereum v1.7.4-0.20220515212948-4dae4279da68 h1:UGqAXDT1euYeb6hQvXXKRP49f5sC4Dv/cW/CjvOC4Hc= +github.com/iotexproject/go-ethereum v1.7.4-0.20220515212948-4dae4279da68/go.mod h1:pJNuIUYfX5+JKzSD/BTdNsvJSZ1TJqmz0dVyXMAbf6M= github.com/iotexproject/go-fsm v1.0.0 h1:Zrg9JnNDUZg4Anpj6oa0Tk4+sXbHTpJzI0v5/Cj5N6A= github.com/iotexproject/go-fsm v1.0.0/go.mod h1:t3aYXtCCcQxyS7oduQZyuUpPnVI4ddFTwbAagHN7fT0= github.com/iotexproject/go-p2p v0.3.3 h1:qDGwaHu1oYG93PIcJAnY5Hl2iK0GoeAQewB0QtvhOXs= diff --git a/state/account.go b/state/account.go index dfd519b61c..8b128caea9 100644 --- a/state/account.go +++ b/state/account.go @@ -19,26 +19,58 @@ import ( var ( // ErrNotEnoughBalance is the error that the balance is not enough ErrNotEnoughBalance = errors.New("not enough balance") + // ErrInvalidAmount is the error that the amount to add is negative + ErrInvalidAmount = errors.New("invalid amount") // ErrAccountCollision is the error that the account already exists ErrAccountCollision = errors.New("account already exists") + // ErrInvalidNonce is the error that the nonce to set is invalid + ErrInvalidNonce = errors.New("invalid nonce") + // ErrUnknownAccountType is the error that the account type is unknown + ErrUnknownAccountType = errors.New("unknown account type") ) -// Account is the canonical representation of an account. -type Account struct { - // 0 is reserved from actions in genesis block and coinbase transfers nonces - // other actions' nonces start from 1 - Nonce uint64 - Balance *big.Int - Root hash.Hash256 // storage trie root for contract account - CodeHash []byte // hash of the smart contract byte-code for contract account - IsCandidate bool - VotingWeight *big.Int +// LegacyNonceAccountTypeOption is an option to create account with new account type +func LegacyNonceAccountTypeOption() AccountCreationOption { + return func(account *Account) error { + account.accountType = 0 + return nil + } } +// DelegateCandidateOption is an option to create a delegate candidate account +func DelegateCandidateOption() AccountCreationOption { + return func(account *Account) error { + account.isCandidate = true + return nil + } +} + +type ( + // AccountCreationOption is to create new account with specific settings + AccountCreationOption func(*Account) error + + // Account is the canonical representation of an account. + Account struct { + // for Type 0, nonce 0 is reserved from actions in genesis block and coinbase transfers nonces + // other actions' nonces start from 1 + nonce uint64 + Balance *big.Int + Root hash.Hash256 // storage trie root for contract account + CodeHash []byte // hash of the smart contract byte-code for contract account + isCandidate bool + votingWeight *big.Int + accountType int32 + } +) + // ToProto converts to protobuf's Account func (st *Account) ToProto() *accountpb.Account { acPb := &accountpb.Account{} - acPb.Nonce = st.Nonce + acPb.Nonce = st.nonce + if _, ok := accountpb.AccountType_name[st.accountType]; !ok { + panic("unknown account type") + } + acPb.Type = accountpb.AccountType(st.accountType) if st.Balance != nil { acPb.Balance = st.Balance.String() } @@ -46,9 +78,9 @@ func (st *Account) ToProto() *accountpb.Account { copy(acPb.Root, st.Root[:]) acPb.CodeHash = make([]byte, len(st.CodeHash)) copy(acPb.CodeHash, st.CodeHash) - acPb.IsCandidate = st.IsCandidate - if st.VotingWeight != nil { - acPb.VotingWeight = st.VotingWeight.Bytes() + acPb.IsCandidate = st.isCandidate + if st.votingWeight != nil { + acPb.VotingWeight = st.votingWeight.Bytes() } return acPb } @@ -60,7 +92,11 @@ func (st Account) Serialize() ([]byte, error) { // FromProto converts from protobuf's Account func (st *Account) FromProto(acPb *accountpb.Account) { - st.Nonce = acPb.Nonce + st.nonce = acPb.Nonce + if _, ok := accountpb.AccountType_name[int32(acPb.Type.Number())]; !ok { + panic("unknown account type") + } + st.accountType = int32(acPb.Type.Number()) if acPb.Balance == "" { st.Balance = big.NewInt(0) } else { @@ -76,10 +112,10 @@ func (st *Account) FromProto(acPb *accountpb.Account) { st.CodeHash = make([]byte, len(acPb.CodeHash)) copy(st.CodeHash, acPb.CodeHash) } - st.IsCandidate = acPb.IsCandidate - st.VotingWeight = big.NewInt(0) + st.isCandidate = acPb.IsCandidate + st.votingWeight = big.NewInt(0) if acPb.VotingWeight != nil { - st.VotingWeight.SetBytes(acPb.VotingWeight) + st.votingWeight.SetBytes(acPb.VotingWeight) } } @@ -93,13 +129,79 @@ func (st *Account) Deserialize(buf []byte) error { return nil } +// IsNewbieAccount returns true if the account has not sent any actions +func (st *Account) IsNewbieAccount() bool { + return st.nonce == 0 +} + +// AccountType returns the account type +func (st *Account) AccountType() int32 { + return st.accountType +} + +// SetPendingNonce sets the pending nonce +func (st *Account) SetPendingNonce(nonce uint64) error { + switch st.accountType { + case 1: + if nonce != st.nonce+1 { + return errors.Wrapf(ErrInvalidNonce, "actual value %d, %d expected", nonce, st.nonce+1) + } + st.nonce++ + case 0: + if nonce != st.nonce+2 { + return errors.Wrapf(ErrInvalidNonce, "actual value %d, %d expected", nonce, st.nonce+2) + } + st.nonce++ + default: + return errors.Wrapf(ErrUnknownAccountType, "account type %d", st.accountType) + } + + return nil +} + +// PendingNonce returns the pending nonce of the account +func (st *Account) PendingNonce() uint64 { + switch st.accountType { + case 1: + return st.nonce + case 0: + return st.nonce + 1 + default: + panic(errors.Wrapf(ErrUnknownAccountType, "account type %d", st.accountType)) + } +} + +// MarkAsCandidate marks the account as a candidate +func (st *Account) MarkAsCandidate() { + st.isCandidate = true +} + +// HasSufficientBalance returns true if balance is larger than amount +func (st *Account) HasSufficientBalance(amount *big.Int) bool { + if amount == nil { + return true + } + return amount.Cmp(st.Balance) <= 0 +} + // AddBalance adds balance for account state -func (st *Account) AddBalance(amount *big.Int) { - st.Balance.Add(st.Balance, amount) +func (st *Account) AddBalance(amount *big.Int) error { + if amount == nil || amount.Sign() < 0 { + return errors.Wrapf(ErrInvalidAmount, "amount %s shouldn't be negative", amount.String()) + } + if st.Balance != nil { + st.Balance = new(big.Int).Add(st.Balance, amount) + } else { + st.Balance = new(big.Int).Set(amount) + } + return nil } // SubBalance subtracts balance for account state func (st *Account) SubBalance(amount *big.Int) error { + if amount == nil || amount.Cmp(big.NewInt(0)) < 0 { + return errors.Wrapf(ErrInvalidAmount, "amount %s shouldn't be negative", amount.String()) + } // make sure there's enough fund to spend if amount.Cmp(st.Balance) == 1 { return ErrNotEnoughBalance @@ -118,9 +220,9 @@ func (st *Account) Clone() *Account { s := *st s.Balance = nil s.Balance = new(big.Int).Set(st.Balance) - s.VotingWeight = nil - if st.VotingWeight != nil { - s.VotingWeight = new(big.Int).Set(st.VotingWeight) + s.votingWeight = nil + if st.votingWeight != nil { + s.votingWeight = new(big.Int).Set(st.votingWeight) } if st.CodeHash != nil { s.CodeHash = nil @@ -130,10 +232,17 @@ func (st *Account) Clone() *Account { return &s } -// EmptyAccount returns an empty account -func EmptyAccount() Account { - return Account{ +// NewAccount creates a new account with options +func NewAccount(opts ...AccountCreationOption) (*Account, error) { + account := &Account{ Balance: big.NewInt(0), - VotingWeight: big.NewInt(0), + votingWeight: big.NewInt(0), + accountType: 1, + } + for _, opt := range opts { + if err := opt(account); err != nil { + return nil, errors.Wrap(err, "failed to apply account creation option") + } } + return account, nil } diff --git a/state/account_test.go b/state/account_test.go index a9eecc794f..73e164e716 100644 --- a/state/account_test.go +++ b/state/account_test.go @@ -17,24 +17,48 @@ import ( "github.com/stretchr/testify/require" ) +func TestNonce(t *testing.T) { + require := require.New(t) + t.Run("legacy account type", func(t *testing.T) { + acct, err := NewAccount(LegacyNonceAccountTypeOption()) + require.NoError(err) + require.Equal(uint64(1), acct.PendingNonce()) + require.Error(acct.SetPendingNonce(0)) + require.Error(acct.SetPendingNonce(1)) + require.Error(acct.SetPendingNonce(3)) + require.NoError(acct.SetPendingNonce(2)) + require.Equal(uint64(2), acct.PendingNonce()) + }) + t.Run("zero nonce account type", func(t *testing.T) { + acct, err := NewAccount() + require.NoError(err) + require.Equal(uint64(0), acct.PendingNonce()) + require.Error(acct.SetPendingNonce(2)) + require.NoError(acct.SetPendingNonce(1)) + require.Equal(uint64(1), acct.PendingNonce()) + }) +} + func TestEncodeDecode(t *testing.T) { require := require.New(t) s1 := Account{ - Nonce: 0x10, - Balance: big.NewInt(20000000), - CodeHash: []byte("testing codehash"), + accountType: 1, + nonce: 0x10, + Balance: big.NewInt(20000000), + CodeHash: []byte("testing codehash"), } ss, err := s1.Serialize() require.NoError(err) require.NotEmpty(ss) - require.Equal(64, len(ss)) + require.Equal(66, len(ss)) s2 := Account{} require.NoError(s2.Deserialize(ss)) - require.Equal(big.NewInt(20000000), s2.Balance) - require.Equal(uint64(0x10), s2.Nonce) + require.Equal(s1.accountType, s2.accountType) + require.Equal(s1.Balance, s2.Balance) + require.Equal(s1.nonce, s2.nonce) require.Equal(hash.ZeroHash256, s2.Root) - require.Equal([]byte("testing codehash"), s2.CodeHash) + require.Equal(s1.CodeHash, s2.CodeHash) } func TestProto(t *testing.T) { @@ -55,7 +79,7 @@ func TestBalance(t *testing.T) { state := &Account{Balance: big.NewInt(20)} // Add 10 to the balance - state.AddBalance(big.NewInt(10)) + require.NoError(state.AddBalance(big.NewInt(10))) // Balance should == 30 now require.Equal(0, state.Balance.Cmp(big.NewInt(30))) // Sub 40 to the balance @@ -65,13 +89,13 @@ func TestBalance(t *testing.T) { func TestClone(t *testing.T) { require := require.New(t) ss := &Account{ - Nonce: 0x10, + nonce: 0x10, Balance: big.NewInt(200), } account := ss.Clone() require.Equal(big.NewInt(200), account.Balance) - account.AddBalance(big.NewInt(100)) + require.NoError(account.AddBalance(big.NewInt(100))) require.Equal(big.NewInt(200), ss.Balance) require.Equal(big.NewInt(200+100), account.Balance) } diff --git a/state/factory/factory_test.go b/state/factory/factory_test.go index df5046569f..499bd670c6 100644 --- a/state/factory/factory_test.go +++ b/state/factory/factory_test.go @@ -130,7 +130,7 @@ func testRevert(ws *workingSet, t *testing.T) { s0 := ws.Snapshot() require.Equal(1, s0) - s.Balance.Add(s.Balance, big.NewInt(5)) + require.NoError(s.AddBalance(big.NewInt(5))) require.Equal(big.NewInt(10), s.Balance) _, err = ws.PutState(s, protocol.LegacyKeyOption(sHash)) require.NoError(err) @@ -151,7 +151,7 @@ func testSDBRevert(ws *workingSet, t *testing.T) { s0 := ws.Snapshot() require.Equal(1, s0) - s.Balance.Add(s.Balance, big.NewInt(5)) + require.NoError(s.AddBalance(big.NewInt(5))) require.Equal(big.NewInt(10), s.Balance) _, err = ws.PutState(s, protocol.LegacyKeyOption(sHash)) require.NoError(err) @@ -177,13 +177,13 @@ func testSnapshot(ws *workingSet, t *testing.T) { require.Equal(big.NewInt(5), s.Balance) s0 := ws.Snapshot() require.Zero(s0) - s.Balance.Add(s.Balance, big.NewInt(5)) + require.NoError(s.AddBalance(big.NewInt(5))) require.Equal(big.NewInt(10), s.Balance) _, err = ws.PutState(s, protocol.LegacyKeyOption(sHash)) require.NoError(err) s1 := ws.Snapshot() require.Equal(1, s1) - s.Balance.Add(s.Balance, big.NewInt(5)) + require.NoError(s.AddBalance(big.NewInt(5))) require.Equal(big.NewInt(15), s.Balance) _, err = ws.PutState(s, protocol.LegacyKeyOption(sHash)) require.NoError(err) @@ -193,7 +193,7 @@ func testSnapshot(ws *workingSet, t *testing.T) { require.Equal(big.NewInt(7), s.Balance) s2 := ws.Snapshot() require.Equal(2, s2) - s.AddBalance(big.NewInt(6)) + require.NoError(s.AddBalance(big.NewInt(6))) require.Equal(big.NewInt(13), s.Balance) _, err = ws.PutState(s, protocol.LegacyKeyOption(tHash)) require.NoError(err) @@ -447,7 +447,7 @@ func testState(sf Factory, t *testing.T) { tsf, err := action.NewTransfer(1, big.NewInt(10), identityset.Address(31).String(), nil, uint64(20000), big.NewInt(0)) require.NoError(t, err) bd := &action.EnvelopeBuilder{} - elp := bd.SetAction(tsf).SetGasLimit(20000).Build() + elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build() selp, err := action.Sign(elp, priKeyA) require.NoError(t, err) ctx = protocol.WithBlockCtx( @@ -468,13 +468,13 @@ func testState(sf Factory, t *testing.T) { require.NoError(t, sf.PutBlock(ctx, &blk)) //test AccountState() & State() - var testAccount state.Account - accountA, err := accountutil.AccountState(sf, a) + testAccount := &state.Account{} + accountA, err := accountutil.AccountState(ctx, sf, a) require.NoError(t, err) sHash := hash.BytesToHash160(identityset.Address(28).Bytes()) - _, err = sf.State(&testAccount, protocol.LegacyKeyOption(sHash)) + _, err = sf.State(testAccount, protocol.LegacyKeyOption(sHash)) require.NoError(t, err) - require.Equal(t, accountA, &testAccount) + require.Equal(t, accountA, testAccount) require.Equal(t, big.NewInt(90), accountA.Balance) } @@ -502,16 +502,16 @@ func testHistoryState(sf Factory, t *testing.T, statetx, archive bool) { defer func() { require.NoError(t, sf.Stop(ctx)) }() - accountA, err := accountutil.AccountState(sf, a) + accountA, err := accountutil.AccountState(ctx, sf, a) require.NoError(t, err) - accountB, err := accountutil.AccountState(sf, b) + accountB, err := accountutil.AccountState(ctx, sf, b) require.NoError(t, err) require.Equal(t, big.NewInt(100), accountA.Balance) require.Equal(t, big.NewInt(0), accountB.Balance) tsf, err := action.NewTransfer(1, big.NewInt(10), b.String(), nil, uint64(20000), big.NewInt(0)) require.NoError(t, err) bd := &action.EnvelopeBuilder{} - elp := bd.SetAction(tsf).SetGasLimit(20000).Build() + elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build() selp, err := action.Sign(elp, priKeyA) require.NoError(t, err) ctx = protocol.WithBlockCtx( @@ -535,9 +535,9 @@ func testHistoryState(sf Factory, t *testing.T, statetx, archive bool) { require.NoError(t, sf.PutBlock(ctx, &blk)) // check latest balance - accountA, err = accountutil.AccountState(sf, a) + accountA, err = accountutil.AccountState(ctx, sf, a) require.NoError(t, err) - accountB, err = accountutil.AccountState(sf, b) + accountB, err = accountutil.AccountState(ctx, sf, b) require.NoError(t, err) require.Equal(t, big.NewInt(90), accountA.Balance) require.Equal(t, big.NewInt(10), accountB.Balance) @@ -545,20 +545,20 @@ func testHistoryState(sf Factory, t *testing.T, statetx, archive bool) { // check archive data if statetx { // statetx not support archive mode - _, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), a) + _, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a) require.Equal(t, ErrNotSupported, errors.Cause(err)) - _, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), b) + _, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b) require.Equal(t, ErrNotSupported, errors.Cause(err)) } else { if !archive { - _, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), a) + _, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a) require.Equal(t, ErrNoArchiveData, errors.Cause(err)) - _, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), b) + _, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b) require.Equal(t, ErrNoArchiveData, errors.Cause(err)) } else { - accountA, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), a) + accountA, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), a) require.NoError(t, err) - accountB, err = accountutil.AccountState(NewHistoryStateReader(sf, 0), b) + accountB, err = accountutil.AccountState(ctx, NewHistoryStateReader(sf, 0), b) require.NoError(t, err) require.Equal(t, big.NewInt(100), accountA.Balance) require.Equal(t, big.NewInt(0), accountB.Balance) @@ -595,7 +595,7 @@ func testFactoryStates(sf Factory, t *testing.T) { tsf, err := action.NewTransfer(1, big.NewInt(10), b, nil, uint64(20000), big.NewInt(0)) require.NoError(t, err) bd := &action.EnvelopeBuilder{} - elp := bd.SetAction(tsf).SetGasLimit(20000).Build() + elp := bd.SetAction(tsf).SetGasLimit(20000).SetNonce(1).Build() selp, err := action.Sign(elp, priKeyA) require.NoError(t, err) ctx = protocol.WithBlockCtx( @@ -780,9 +780,9 @@ func testNonce(sf Factory, t *testing.T) { }) _, err = ws.runAction(ctx, selp) require.NoError(t, err) - state, err := accountutil.AccountState(sf, a) + state, err := accountutil.AccountState(ctx, sf, a) require.NoError(t, err) - require.Equal(t, uint64(0), state.Nonce) + require.Equal(t, uint64(1), state.PendingNonce()) tx, err = action.NewTransfer(1, big.NewInt(2), b, nil, uint64(20000), big.NewInt(0)) require.NoError(t, err) @@ -800,9 +800,9 @@ func testNonce(sf Factory, t *testing.T) { require.NoError(t, err) require.NoError(t, sf.PutBlock(ctx, &blk)) - state, err = accountutil.AccountState(sf, a) + state, err = accountutil.AccountState(ctx, sf, a) require.NoError(t, err) - require.Equal(t, uint64(1), state.Nonce) + require.Equal(t, uint64(2), state.PendingNonce()) } func TestLoadStoreHeight(t *testing.T) { @@ -1206,14 +1206,15 @@ func testCachedBatch(ws *workingSet, t *testing.T) { // test PutState() hashA := hash.BytesToHash160(identityset.Address(28).Bytes()) - accountA := state.EmptyAccount() - accountA.Balance = big.NewInt(70) - _, err := ws.PutState(accountA, protocol.LegacyKeyOption(hashA)) + accountA, err := state.NewAccount() + require.NoError(err) + require.NoError(accountA.AddBalance(big.NewInt(70))) + _, err = ws.PutState(accountA, protocol.LegacyKeyOption(hashA)) require.NoError(err) // test State() - testAccount := state.EmptyAccount() - _, err = ws.State(&testAccount, protocol.LegacyKeyOption(hashA)) + testAccount := &state.Account{} + _, err = ws.State(testAccount, protocol.LegacyKeyOption(hashA)) require.NoError(err) require.Equal(accountA, testAccount) @@ -1222,7 +1223,7 @@ func testCachedBatch(ws *workingSet, t *testing.T) { require.NoError(err) // can't state account "alfa" anymore - _, err = ws.State(&testAccount, protocol.LegacyKeyOption(hashA)) + _, err = ws.State(testAccount, protocol.LegacyKeyOption(hashA)) require.Error(err) } @@ -1355,16 +1356,17 @@ func TestStateDBPatch(t *testing.T) { func TestDeleteAndPutSameKey(t *testing.T) { testDeleteAndPutSameKey := func(t *testing.T, ws *workingSet) { key := hash.Hash160b([]byte("test")) - acc := state.Account{ - Nonce: 1, - } - _, err := ws.PutState(acc, protocol.LegacyKeyOption(key)) + acc, err := state.NewAccount() + require.NoError(t, err) + require.NoError(t, acc.SetPendingNonce(1)) + require.NoError(t, acc.SetPendingNonce(2)) + _, err = ws.PutState(acc, protocol.LegacyKeyOption(key)) require.NoError(t, err) _, err = ws.DelState(protocol.LegacyKeyOption(key)) require.NoError(t, err) - _, err = ws.State(&acc, protocol.LegacyKeyOption(key)) + _, err = ws.State(acc, protocol.LegacyKeyOption(key)) require.Equal(t, state.ErrStateNotExist, errors.Cause(err)) - _, err = ws.State(&acc, protocol.LegacyKeyOption(hash.Hash160b([]byte("other")))) + _, err = ws.State(acc, protocol.LegacyKeyOption(hash.Hash160b([]byte("other")))) require.Equal(t, state.ErrStateNotExist, errors.Cause(err)) } ctx := genesis.WithGenesisContext( @@ -1380,6 +1382,7 @@ func TestDeleteAndPutSameKey(t *testing.T) { }) t.Run("stateTx", func(t *testing.T) { sdb, err := NewStateDB(config.Default, InMemStateDBOption()) + require.NoError(t, err) ws, err := sdb.(workingSetCreator).newWorkingSet(ctx, 0) require.NoError(t, err) testDeleteAndPutSameKey(t, ws) @@ -1678,7 +1681,7 @@ func benchState(sf Factory, b *testing.B) { if err != nil { b.Fatal(err) } - _, err = accountutil.AccountState(sf, addr) + _, err = accountutil.AccountState(zctx, sf, addr) if err != nil { b.Fatal(err) } diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 150ca110ab..379902a4d8 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -323,7 +323,7 @@ func (ws *workingSet) CreateGenesisStates(ctx context.Context) error { return ws.finalize() } -func (ws *workingSet) validateNonce(blk *block.Block) error { +func (ws *workingSet) validateNonce(ctx context.Context, blk *block.Block) error { accountNonceMap := make(map[string][]uint64) for _, selp := range blk.Actions { caller := selp.SenderAddress() @@ -340,21 +340,22 @@ func (ws *workingSet) validateNonce(blk *block.Block) error { // Verify each account's Nonce for srcAddr, receivedNonces := range accountNonceMap { addr, _ := address.FromString(srcAddr) - confirmedState, err := accountutil.AccountState(ws, addr) + confirmedState, err := accountutil.AccountState(ctx, ws, addr) if err != nil { return errors.Wrapf(err, "failed to get the confirmed nonce of address %s", srcAddr) } receivedNonces := receivedNonces sort.Slice(receivedNonces, func(i, j int) bool { return receivedNonces[i] < receivedNonces[j] }) + pendingNonce := confirmedState.PendingNonce() for i, nonce := range receivedNonces { - if nonce != confirmedState.Nonce+uint64(i+1) { + if nonce != pendingNonce+uint64(i) { return errors.Wrapf( action.ErrNonceTooHigh, - "the %d nonce %d of address %s (confirmed nonce %d) is not continuously increasing", + "the %d nonce %d of address %s (init pending nonce %d) is not continuously increasing", i, nonce, srcAddr, - confirmedState.Nonce, + pendingNonce, ) } } @@ -515,7 +516,7 @@ func updateReceiptIndex(receipts []*action.Receipt) { } func (ws *workingSet) ValidateBlock(ctx context.Context, blk *block.Block) error { - if err := ws.validateNonce(blk); err != nil { + if err := ws.validateNonce(ctx, blk); err != nil { return errors.Wrap(err, "failed to validate nonce") } if err := ws.process(ctx, blk.RunnableActions().Actions()); err != nil { diff --git a/tools/actioninjector.v2/internal/client/client_test.go b/tools/actioninjector.v2/internal/client/client_test.go index 4705a93516..575b3937d3 100644 --- a/tools/actioninjector.v2/internal/client/client_test.go +++ b/tools/actioninjector.v2/internal/client/client_test.go @@ -56,7 +56,6 @@ func TestClient(t *testing.T) { ap := mock_actpool.NewMockActPool(mockCtrl) sf.EXPECT().State(gomock.Any(), gomock.Any()).Do(func(accountState *state.Account, _ protocol.StateOption) { - *accountState = state.EmptyAccount() }) sf.EXPECT().Height().Return(uint64(10), nil).AnyTimes() bc.EXPECT().Genesis().Return(cfg.Genesis).AnyTimes()