From bcb14e5744fc15efd766a403c2843888563c69ee Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Fri, 10 Feb 2023 17:05:24 +0800 Subject: [PATCH 1/6] Fix gocycle in chain.go --- go.mod | 151 +++++- go.sum | 3 +- kernel/contract/context.go | 5 + kernel/contract/context_test.go | 50 ++ .../xuperos/asyncworker/asyncworker_test.go | 3 +- kernel/engines/xuperos/chain.go | 250 ++++++---- kernel/engines/xuperos/chain_test.go | 436 +++++++++++++++++- kernel/engines/xuperos/engine.go | 4 +- kernel/evm/eth_bench_test.go | 12 +- 9 files changed, 787 insertions(+), 127 deletions(-) create mode 100644 kernel/contract/context_test.go diff --git a/go.mod b/go.mod index 4d5541eb..66bd1c48 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,12 @@ module github.com/xuperchain/xupercore -go 1.14 +go 1.18 require ( - github.com/ChainSafe/go-schnorrkel v0.0.0-20200626160457-b38283118816 // indirect + github.com/agiledragon/gomonkey/v2 v2.9.0 github.com/aws/aws-sdk-go v1.32.4 github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/dgraph-io/badger/v3 v3.2103.1 - github.com/docker/go-connections v0.4.1-0.20180821093606-97c2040d34df // indirect github.com/docker/go-units v0.4.0 github.com/emirpasic/gods v1.12.1-0.20201118132343-79df803e554c github.com/fsouza/go-dockerclient v1.6.0 @@ -15,7 +14,6 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.4.3 github.com/golang/snappy v0.0.3 - github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/hashicorp/golang-lru v0.5.4 github.com/hyperledger/burrow v0.30.5 @@ -45,4 +43,149 @@ require ( google.golang.org/grpc v1.35.0 ) +require ( + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200626160457-b38283118816 // indirect + github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect + github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd v0.20.1-beta // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/consensys/gnark v0.5.2 // indirect + github.com/consensys/gnark-crypto v0.5.3 // indirect + github.com/containerd/containerd v1.3.0 // indirect + github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 // indirect + github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 // indirect + github.com/docker/go-connections v0.4.1-0.20180821093606-97c2040d34df // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/edsrzf/mmap-go v1.0.0 // indirect + github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/fxamacker/cbor/v2 v2.2.0 // indirect + github.com/go-kit/kit v0.9.0 // indirect + github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect + github.com/google/flatbuffers v1.12.0 // indirect + github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa // indirect + github.com/google/gopacket v1.1.17 // indirect + github.com/google/uuid v1.1.2 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/huin/goupnp v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect + github.com/ipfs/go-datastore v0.4.4 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/ipfs/go-ipns v0.0.2 // indirect + github.com/ipfs/go-log v1.0.4 // indirect + github.com/ipfs/go-log/v2 v2.1.1 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect + github.com/jmespath/go-jmespath v0.3.0 // indirect + github.com/klauspost/compress v1.12.3 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect + github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d // indirect + github.com/libp2p/go-addr-util v0.0.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/libp2p/go-conn-security-multistream v0.2.0 // indirect + github.com/libp2p/go-eventbus v0.2.1 // indirect + github.com/libp2p/go-flow-metrics v0.0.3 // indirect + github.com/libp2p/go-libp2p-autonat v0.3.2 // indirect + github.com/libp2p/go-libp2p-blankhost v0.2.0 // indirect + github.com/libp2p/go-libp2p-crypto v0.1.0 // indirect + github.com/libp2p/go-libp2p-discovery v0.5.0 // indirect + github.com/libp2p/go-libp2p-loggables v0.1.0 // indirect + github.com/libp2p/go-libp2p-mplex v0.2.4 // indirect + github.com/libp2p/go-libp2p-nat v0.0.6 // indirect + github.com/libp2p/go-libp2p-noise v0.1.1 // indirect + github.com/libp2p/go-libp2p-peer v0.2.0 // indirect + github.com/libp2p/go-libp2p-peerstore v0.2.6 // indirect + github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect + github.com/libp2p/go-libp2p-tls v0.1.3 // indirect + github.com/libp2p/go-libp2p-transport-upgrader v0.3.0 // indirect + github.com/libp2p/go-libp2p-yamux v0.2.8 // indirect + github.com/libp2p/go-mplex v0.1.2 // indirect + github.com/libp2p/go-msgio v0.0.6 // indirect + github.com/libp2p/go-nat v0.0.5 // indirect + github.com/libp2p/go-netroute v0.1.3 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect + github.com/libp2p/go-reuseport v0.0.2 // indirect + github.com/libp2p/go-reuseport-transport v0.0.4 // indirect + github.com/libp2p/go-sockaddr v0.0.2 // indirect + github.com/libp2p/go-stream-muxer-multistream v0.3.0 // indirect + github.com/libp2p/go-tcp-transport v0.2.1 // indirect + github.com/libp2p/go-ws-transport v0.3.1 // indirect + github.com/libp2p/go-yamux v1.3.7 // indirect + github.com/magiconair/properties v1.8.1 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v0.1.1 // indirect + github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.2.0 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multiaddr-net v0.2.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multihash v0.0.14 // indirect + github.com/multiformats/go-multistream v0.1.2 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect + github.com/opencontainers/go-digest v1.0.0-rc1 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/runc v0.1.1 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect + github.com/prometheus/common v0.6.0 // indirect + github.com/prometheus/procfs v0.0.5 // indirect + github.com/sirupsen/logrus v1.4.2 // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.1.2 // indirect + github.com/spf13/cast v1.3.0 // indirect + github.com/spf13/jwalterweatherman v1.0.0 // indirect + github.com/spf13/pflag v1.0.3 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/tendermint/go-amino v0.14.1 // indirect + github.com/tendermint/tendermint v0.33.1 // indirect + github.com/tmthrgd/atomics v0.0.0-20190904060638-dc7a5fcc7e0d // indirect + github.com/tmthrgd/go-bitset v0.0.0-20190904054048-394d9a556c05 // indirect + github.com/tmthrgd/go-bitwise v0.0.0-20190904053232-1430ee983fca // indirect + github.com/tmthrgd/go-byte-test v0.0.0-20190904060354-2794345b9929 // indirect + github.com/tmthrgd/go-memset v0.0.0-20190904060434-6fb7a21f88f1 // indirect + github.com/tmthrgd/go-popcount v0.0.0-20190904054823-afb1ace8b04f // indirect + github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc // indirect + github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect + github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/xuperchain/wagon v0.6.1-0.20200313164333-db544e251599 // indirect + go.opencensus.io v0.22.5 // indirect + go.uber.org/atomic v1.6.0 // indirect + go.uber.org/multierr v1.5.0 // indirect + go.uber.org/zap v1.15.0 // indirect + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect + golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 // indirect + golang.org/x/text v0.3.3 // indirect + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + google.golang.org/protobuf v1.25.0 // indirect + gopkg.in/ini.v1 v1.51.0 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect +) + replace github.com/hyperledger/burrow => github.com/xuperchain/burrow v0.30.6-0.20211229032028-fbee6a05ab0f diff --git a/go.sum b/go.sum index 614e9a17..70669d97 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/agiledragon/gomonkey/v2 v2.9.0 h1:PDiKKybR596O6FHW+RVSG0Z7uGCBNbmbUXh3uCNQ7Hc= +github.com/agiledragon/gomonkey/v2 v2.9.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/alecthomas/jsonschema v0.0.0-20190122210438-a6952de1bbe6/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -96,7 +98,6 @@ github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQY github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg= github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= github.com/dgraph-io/badger/v3 v3.2103.1 h1:zaX53IRg7ycxVlkd5pYdCeFp1FynD6qBGQoQql3R3Hk= github.com/dgraph-io/badger/v3 v3.2103.1/go.mod h1:dULbq6ehJ5K0cGW/1TQ9iSfUk0gbSiToDWmWmTsJ53E= diff --git a/kernel/contract/context.go b/kernel/contract/context.go index 87aa864e..aea8b687 100644 --- a/kernel/contract/context.go +++ b/kernel/contract/context.go @@ -26,6 +26,11 @@ type Response struct { Body []byte `json:"body"` } +// HasError checked by status +func (r *Response) HasError() bool { + return r.Status >= StatusErrorThreshold +} + // ContextConfig define the config of context type ContextConfig struct { State StateSandbox diff --git a/kernel/contract/context_test.go b/kernel/contract/context_test.go new file mode 100644 index 00000000..1a5efb3e --- /dev/null +++ b/kernel/contract/context_test.go @@ -0,0 +1,50 @@ +package contract + +import "testing" + +func TestResponse_HasError(t *testing.T) { + type fields struct { + Status int + Message string + Body []byte + } + tests := []struct { + name string + fields fields + want bool + }{ + { + name: "no error", + fields: fields{ + Status: StatusOK, + }, + want: false, + }, + { + name: "threshold error", + fields: fields{ + Status: StatusErrorThreshold, + }, + want: true, + }, + { + name: "normal error", + fields: fields{ + Status: StatusError, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := &Response{ + Status: tt.fields.Status, + Message: tt.fields.Message, + Body: tt.fields.Body, + } + if got := r.HasError(); got != tt.want { + t.Errorf("Response.HasError() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/kernel/engines/xuperos/asyncworker/asyncworker_test.go b/kernel/engines/xuperos/asyncworker/asyncworker_test.go index cdf17024..185c541f 100644 --- a/kernel/engines/xuperos/asyncworker/asyncworker_test.go +++ b/kernel/engines/xuperos/asyncworker/asyncworker_test.go @@ -2,7 +2,6 @@ package asyncworker import ( "encoding/json" - "io/ioutil" "os" "path/filepath" "testing" @@ -222,7 +221,7 @@ type TestHelper struct { } func NewTestHelper() (*TestHelper, error) { - basedir, err := ioutil.TempDir("", "asyncworker-test") + basedir, err := os.MkdirTemp("", "asyncworker-test") if err != nil { return nil, err } diff --git a/kernel/engines/xuperos/chain.go b/kernel/engines/xuperos/chain.go index 85cc59d0..6086e62c 100644 --- a/kernel/engines/xuperos/chain.go +++ b/kernel/engines/xuperos/chain.go @@ -2,6 +2,7 @@ package xuperos import ( "fmt" + "math/big" "strings" "time" @@ -115,24 +116,18 @@ func (t *Chain) Context() *common.ChainCtx { } // 交易预执行 -func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiator string, authRequires []string) (*protos.InvokeResponse, error) { +func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiator string, + authRequires []string) (*protos.InvokeResponse, error) { + if ctx == nil || ctx.GetLog() == nil { return nil, common.ErrParameter } - reservedRequests, err := t.ctx.State.GetReservedContractRequests(reqs, true) - if err != nil { - t.log.Error("PreExec get reserved contract request error", "error", err) - return nil, common.ErrParameter.More("%v", err) - } - - transContractName, transAmount, err := tx.ParseContractTransferRequest(reqs) + reqCtx, err := t.reqContext(ctx, reqs) if err != nil { - return nil, common.ErrParameter.More("%v", err) + return nil, err } - - reqs = append(reservedRequests, reqs...) - if len(reqs) <= 0 { + if len(reqCtx.requests) <= 0 { return &protos.InvokeResponse{}, nil } @@ -146,7 +141,7 @@ func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiat return nil, common.ErrContractNewSandboxFailed } - contextConfig := &contract.ContextConfig{ + contractCtx := &contract.ContextConfig{ State: sandbox, Initiator: initiator, AuthRequire: authRequires, @@ -154,18 +149,44 @@ func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiat ChainName: t.ctx.BCName, } - gasPrice := t.ctx.State.GetMeta().GetGasPrice() - gasUsed := int64(0) - responseBodes := make([][]byte, 0, len(reqs)) - requests := make([]*protos.InvokeRequest, 0, len(reqs)) - responses := make([]*protos.ContractResponse, 0, len(reqs)) - for i, req := range reqs { + invokeResp, err := t.preExecWithReservedReqs(reqCtx, contractCtx) + if err != nil { + return nil, err + } + + err = sandbox.Flush() + if err != nil { + return nil, err + } + rwSet := sandbox.RWSet() + utxoRWSet := sandbox.UTXORWSet() + + invokeResp.Inputs = xmodel.GetTxInputs(rwSet.RSet) + invokeResp.Outputs = xmodel.GetTxOutputs(rwSet.WSet) + invokeResp.UtxoInputs = utxoRWSet.Rset + invokeResp.UtxoOutputs = utxoRWSet.WSet + + return invokeResp, nil +} + +func (t *Chain) preExecWithReservedReqs(reqCtx *reqContext, + contractCtx *contract.ContextConfig) (*protos.InvokeResponse, error) { + + reqCnt := len(reqCtx.requests) + invokeResp := &protos.InvokeResponse{ + Response: make([][]byte, 0, reqCnt), + Requests: make([]*protos.InvokeRequest, 0, reqCnt), + Responses: make([]*protos.ContractResponse, 0, reqCnt), + } + logger := reqCtx.logger + + for idx, req := range reqCtx.requests { if req == nil { continue } if req.ModuleName == "" && req.ContractName == "" && req.MethodName == "" { - ctx.GetLog().Warn("PreExec req empty", "req", req) + logger.GetLog().Warn("PreExec req empty", "req", req) continue } if req.ModuleName == "" { @@ -175,91 +196,84 @@ func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiat if err != nil { return nil, err } - contextConfig.Module = desc.GetContractType() + contractCtx.Module = desc.GetContractType() } else { - contextConfig.Module = req.ModuleName + contractCtx.Module = req.ModuleName } - beginTime := time.Now() + contractCtx.ContractName = req.ContractName + contractCtx.TransferAmount = reqCtx.GetTransAmount(req.ContractName) + isReservedReq := reqCtx.IsReservedReq(idx) - contextConfig.ContractName = req.ContractName - if transContractName == req.ContractName { - contextConfig.TransferAmount = transAmount.String() - } else { - contextConfig.TransferAmount = "" - } - - context, err := t.ctx.Contract.NewContext(contextConfig) + err := t.preExecOnce(logger, contractCtx, req, isReservedReq, invokeResp) if err != nil { - ctx.GetLog().Error("PreExec NewContext error", "error", err, "contractName", req.ContractName) - if i < len(reservedRequests) && strings.HasSuffix(err.Error(), "not found") { - requests = append(requests, req) - continue - } - return nil, common.ErrContractNewCtxFailed.More("%v", err) - } - - resp, err := context.Invoke(req.MethodName, req.Args) - if err != nil { - // TODO: deal with error - _ = context.Release() - ctx.GetLog().Error("PreExec Invoke error", "error", err, "contractName", req.ContractName) - metrics.ContractInvokeCounter.WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError").Inc() - return nil, common.ErrContractInvokeFailed.More("%v", err) - } - - if resp.Status >= 400 && i < len(reservedRequests) { - // TODO: deal with error - _ = context.Release() - ctx.GetLog().Error("PreExec Invoke error", "status", resp.Status, "contractName", req.ContractName) - metrics.ContractInvokeCounter.WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError").Inc() - return nil, common.ErrContractInvokeFailed.More("%v", resp.Message) + return nil, err } + } + return invokeResp, nil +} - metrics.ContractInvokeCounter.WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "OK").Inc() - resourceUsed := context.ResourceUsed() - if i >= len(reservedRequests) { - gasUsed += resourceUsed.TotalGas(gasPrice) - } +// preExecOnce preExec one request with metrics +func (t *Chain) preExecOnce(logger xctx.XContext, contractCtx *contract.ContextConfig, + req *protos.InvokeRequest, isReservedReq bool, invokeResp *protos.InvokeResponse) error { - // request - request := *req - request.ResourceLimits = contract.ToPbLimits(resourceUsed) - requests = append(requests, &request) + gasPrice := t.ctx.State.GetMeta().GetGasPrice() + beginTime := time.Now() - // response - response := &protos.ContractResponse{ - Status: int32(resp.Status), - Message: resp.Message, - Body: resp.Body, + context, err := t.ctx.Contract.NewContext(contractCtx) + if err != nil { + logger.GetLog().Error("PreExec NewContext error", "error", err, "contractName", req.ContractName) + if isReservedReq && strings.HasSuffix(err.Error(), "not found") { + invokeResp.Requests = append(invokeResp.Requests, req) + return nil } - responses = append(responses, response) - responseBodes = append(responseBodes, resp.Body) - - // TODO: deal with error - _ = context.Release() - metrics.ContractInvokeHistogram.WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName).Observe(time.Since(beginTime).Seconds()) + return common.ErrContractNewCtxFailed.More("%v", err) } + defer func() { _ = context.Release() }() // TODO: deal with error - err = sandbox.Flush() + resp, err := context.Invoke(req.MethodName, req.Args) if err != nil { - return nil, err - } - rwSet := sandbox.RWSet() - utxoRWSet := sandbox.UTXORWSet() - - invokeResponse := &protos.InvokeResponse{ - GasUsed: gasUsed, - Response: responseBodes, - Inputs: xmodel.GetTxInputs(rwSet.RSet), - Outputs: xmodel.GetTxOutputs(rwSet.WSet), - Requests: requests, - Responses: responses, - UtxoInputs: utxoRWSet.Rset, - UtxoOutputs: utxoRWSet.WSet, - } - - return invokeResponse, nil + logger.GetLog().Error("PreExec Invoke error", "error", err, "contractName", req.ContractName) + metrics.ContractInvokeCounter. + WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError"). + Inc() + return common.ErrContractInvokeFailed.More("%v", err) + } + + if resp.HasError() && isReservedReq { + logger.GetLog().Error("PreExec Invoke error", "status", resp.Status, "contractName", req.ContractName) + metrics.ContractInvokeCounter. + WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError"). + Inc() + return common.ErrContractInvokeFailed.More("%v", resp.Message) + } + + metrics.ContractInvokeCounter. + WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "OK"). + Inc() + resourceUsed := context.ResourceUsed() + if !isReservedReq { + invokeResp.GasUsed += resourceUsed.TotalGas(gasPrice) + } + + // request + request := *req + request.ResourceLimits = contract.ToPbLimits(resourceUsed) + invokeResp.Requests = append(invokeResp.Requests, &request) + + // response + response := &protos.ContractResponse{ + Status: int32(resp.Status), + Message: resp.Message, + Body: resp.Body, + } + invokeResp.Responses = append(invokeResp.Responses, response) + invokeResp.Response = append(invokeResp.Response, resp.Body) + + metrics.ContractInvokeHistogram. + WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName). + Observe(time.Since(beginTime).Seconds()) + return nil } // 提交交易到交易池(xuperos引擎同时更新到状态机和交易池) @@ -474,3 +488,55 @@ func (t *Chain) CreateParaChain() error { } return nil } + +// reqContext is context for PreExec requests +type reqContext struct { + + // trans info + + transContractName string + transAmount *big.Int + + // requests contains [reservedReqs..., preExecReqs...] + requests []*protos.InvokeRequest + reservedReqCnt int + + logger xctx.XContext +} + +// GetTransAmount get trans amount by contranct name +func (c *reqContext) GetTransAmount(contractName string) string { + if contractName == c.transContractName { + return c.transAmount.String() + } + return "" +} + +// IsReservedReq judges reserved request by index +func (c *reqContext) IsReservedReq(index int) bool { + return index < c.reservedReqCnt +} + +// reqContext creates context with chain reserved requests and PreExec requests +func (t *Chain) reqContext(logger xctx.XContext, reqs []*protos.InvokeRequest) (*reqContext, error) { + reqCtx := new(reqContext) + var err error + + // parse trans info from PreExec requests + reqCtx.transContractName, reqCtx.transAmount, err = tx.ParseContractTransferRequest(reqs) + if err != nil { + return nil, common.ErrParameter.More("%v", err) + } + + // pack reserved requests and PreExec requests + reservedRequests, err := t.ctx.State.GetReservedContractRequests(reqs, true) + if err != nil { + t.log.Error("PreExec get reserved contract request error", "error", err) + return nil, common.ErrParameter.More("%v", err) + } + reqCtx.reservedReqCnt = len(reservedRequests) + reqCtx.requests = append(reservedRequests, reqs...) + + reqCtx.logger = logger + return reqCtx, nil +} diff --git a/kernel/engines/xuperos/chain_test.go b/kernel/engines/xuperos/chain_test.go index e44a6df8..1113e711 100644 --- a/kernel/engines/xuperos/chain_test.go +++ b/kernel/engines/xuperos/chain_test.go @@ -4,13 +4,25 @@ import ( "encoding/hex" "fmt" "math/big" + "os" + "os/exec" + "path/filepath" + "reflect" + "runtime" "testing" "time" + "github.com/agiledragon/gomonkey/v2" + "github.com/patrickmn/go-cache" "github.com/xuperchain/xupercore/bcs/ledger/xledger/state/utxo/txhash" lpb "github.com/xuperchain/xupercore/bcs/ledger/xledger/xldgpb" "github.com/xuperchain/xupercore/kernel/common/xaddress" + xctx "github.com/xuperchain/xupercore/kernel/common/xcontext" + "github.com/xuperchain/xupercore/kernel/contract" "github.com/xuperchain/xupercore/kernel/engines/xuperos/common" + "github.com/xuperchain/xupercore/kernel/engines/xuperos/miner" + "github.com/xuperchain/xupercore/lib/logs" + "github.com/xuperchain/xupercore/lib/timer" "github.com/xuperchain/xupercore/lib/utils" "github.com/xuperchain/xupercore/protos" ) @@ -89,31 +101,30 @@ func mockTransferTx(chain common.Chain) (*lpb.Transaction, error) { return tx, nil } -func TestChain_SubmitTx(t *testing.T) { +func TestChain_SubmitTx_case_transfer(t *testing.T) { + patch := setup(t) + defer patch.Reset() + engine, err := MockEngine("p2pv2/node1/conf/env.yaml") if err != nil { - t.Logf("%v", err) - return + t.Fatalf("%v", err) } - // go engine.Run() - // defer engine.Exit() + go engine.Run() + defer engine.Exit() chain, err := engine.Get("xuper") if err != nil { - t.Errorf("get chain error: %v", err) - return + t.Fatalf("get chain error: %v", err) } tx, err := mockTransferTx(chain) if err != nil { - t.Errorf("mock tx error: %v", err) - return + t.Fatalf("mock tx error: %v", err) } err = chain.SubmitTx(chain.Context(), tx) if err != nil { - t.Errorf("submit tx error: %v", err) - return + t.Fatalf("submit tx error: %v", err) } } @@ -196,30 +207,415 @@ func mockContractTx(chain common.Chain) (*lpb.Transaction, error) { return tx, nil } -func TestChain_PreExec(t *testing.T) { +func TestChain_SubmitTx_case_contract(t *testing.T) { + patch := setup(t) + defer patch.Reset() + engine, err := MockEngine("p2pv2/node1/conf/env.yaml") if err != nil { - t.Logf("%v", err) - return + t.Fatalf("%v", err) } - // go engine.Run() - // defer engine.Exit() + go engine.Run() + defer engine.Exit() chain, err := engine.Get("xuper") if err != nil { - t.Errorf("get chain error: %v", err) + t.Fatalf("get chain error: %v", err) return } tx, err := mockContractTx(chain) if err != nil { - t.Errorf("mock tx error: %v", err) - return + t.Fatalf("mock tx error: %v", err) } err = chain.SubmitTx(chain.Context(), tx) if err != nil { - t.Errorf("submit tx error: %v", err) + t.Fatalf("submit tx error: %v", err) + } +} + +func setup(t *testing.T) *gomonkey.Patches { + if runtime.GOOS == "darwin" { + t.Skip() + } + mockLookPath := func(arg string) (string, error) { + if arg == "wasm2c" { + wasm2cPath := filepath.Join(filepath.Dir(os.Args[0]), "wasm2c") + fmt.Println(filepath.Dir(os.Args[0])) + return filepath.Abs(wasm2cPath) + } + return exec.LookPath(arg) + } + patch := gomonkey.ApplyFunc(exec.LookPath, mockLookPath) + return patch +} + +func TestChain_PreExec(t *testing.T) { + patch := setup(t) + defer patch.Reset() + + engine, err := MockEngine("p2pv2/node1/conf/env.yaml") + if err != nil { + t.Fatalf("%v", err) + } + go engine.Run() + defer engine.Exit() + + chain, err := engine.Get("xuper") + if err != nil { + t.Fatalf("get chain error: %v", err) return } + + type fields struct { + log logs.Logger + miner *miner.Miner + relyAgent common.ChainRelyAgent + txIdCache *cache.Cache + } + type args struct { + ctx xctx.XContext + reqs []*protos.InvokeRequest + initiator string + authRequires []string + } + tests := []struct { + name string + fields fields + args args + // don't care much about the specific content returned, so simply judge gasUsed + want *protos.InvokeResponse + wantErr bool + }{ + { + name: "normal", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("kernel")}, + }, + want: &protos.InvokeResponse{GasUsed: 1000}, + }, + { + name: "contract method with invalid args", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("invalid args")}, + }, + wantErr: true, + }, + { + name: "method not exist", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("method not exist")}, + }, + wantErr: true, + }, + { + name: "contract not exist", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("contract not exist")}, + }, + wantErr: true, + }, + { + name: "no request", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + }, + want: &protos.InvokeResponse{}, + }, + { + name: "no logger", + args: args{ + ctx: &mockXContext{}, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tr := &Chain{ + ctx: chain.Context(), + log: tt.fields.log, + miner: tt.fields.miner, + relyAgent: tt.fields.relyAgent, + txIdCache: tt.fields.txIdCache, + } + got, err := tr.PreExec(tt.args.ctx, tt.args.reqs, tt.args.initiator, tt.args.authRequires) + if (err != nil) != tt.wantErr { + t.Errorf("Chain.PreExec() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !(got == tt.want || got.GasUsed == tt.want.GasUsed) { + t.Errorf("Chain.PreExec() = %v\n"+ + "\twant %v", + got, tt.want) + } + }) + } +} + +func TestChain_preExecWithReservedReqs(t *testing.T) { + type fields struct { + ctx *common.ChainCtx + log logs.Logger + miner *miner.Miner + relyAgent common.ChainRelyAgent + txIdCache *cache.Cache + } + type args struct { + reqCtx *reqContext + contractCtx *contract.ContextConfig + } + tests := []struct { + name string + fields fields + args args + want *protos.InvokeResponse + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tr := &Chain{ + ctx: tt.fields.ctx, + log: tt.fields.log, + miner: tt.fields.miner, + relyAgent: tt.fields.relyAgent, + txIdCache: tt.fields.txIdCache, + } + got, err := tr.preExecWithReservedReqs(tt.args.reqCtx, tt.args.contractCtx) + if (err != nil) != tt.wantErr { + t.Errorf("Chain.preExecWithReservedReqs() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Chain.preExecWithReservedReqs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestChain_preExecOnce(t *testing.T) { + type fields struct { + ctx *common.ChainCtx + log logs.Logger + miner *miner.Miner + relyAgent common.ChainRelyAgent + txIdCache *cache.Cache + } + type args struct { + logger xctx.XContext + contractCtx *contract.ContextConfig + req *protos.InvokeRequest + isReservedReq bool + invokeResp *protos.InvokeResponse + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tr := &Chain{ + ctx: tt.fields.ctx, + log: tt.fields.log, + miner: tt.fields.miner, + relyAgent: tt.fields.relyAgent, + txIdCache: tt.fields.txIdCache, + } + if err := tr.preExecOnce(tt.args.logger, tt.args.contractCtx, tt.args.req, tt.args.isReservedReq, tt.args.invokeResp); (err != nil) != tt.wantErr { + t.Errorf("Chain.preExecOnce() error = %v\n"+ + "\twantErr %v", + err, tt.wantErr) + } + }) + } +} + +type mockXContext struct { + logger logs.Logger +} + +func (m mockXContext) Deadline() (deadline time.Time, ok bool) { + panic("implement me") +} + +func (m mockXContext) Done() <-chan struct{} { + panic("implement me") +} + +func (m mockXContext) Err() error { + panic("implement me") +} + +func (m mockXContext) Value(key any) any { + panic("implement me") +} + +func (m mockXContext) GetLog() logs.Logger { + return m.logger +} + +func (m mockXContext) GetTimer() *timer.XTimer { + panic("implement me") +} + +type mockLogger struct { +} + +func (m mockLogger) GetLogId() string { + panic("implement me") +} + +func (m mockLogger) SetCommField(key string, value interface{}) { + panic("implement me") +} + +func (m mockLogger) SetInfoField(key string, value interface{}) { + panic("implement me") +} + +func (m mockLogger) Error(msg string, ctx ...interface{}) { + fmt.Println(msg, ctx) +} + +func (m mockLogger) Warn(msg string, ctx ...interface{}) { + panic("implement me") +} + +func (m mockLogger) Info(msg string, ctx ...interface{}) { + panic("implement me") +} + +func (m mockLogger) Trace(msg string, ctx ...interface{}) { + panic("implement me") +} + +func (m mockLogger) Debug(msg string, ctx ...interface{}) { + panic("implement me") +} + +func mockReq(req string) *protos.InvokeRequest { + switch req { + case "contract not exist": + return &protos.InvokeRequest{ + ContractName: "notExist", + } + case "method not exist": + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "notExist", + } + case "invalid args": + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "NewAccount", + Args: nil, + } + default: + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "NewAccount", + Args: map[string][]byte{ + "account_name": []byte("1234567890123456"), + "acl": []byte(`{"pm": {"rule": 1,"acceptValue": 1.0},"aksWeight": {"TeyyPLpp9L7QAcxHangtcHTu7HUZ6iydY": 1}}`), + }, + } + } +} + +func Test_reqContext_GetTransAmount(t *testing.T) { + type args struct { + contractName string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "target contract", + args: args{ + contractName: "transfer", + }, + want: "100", + }, + { + name: "not target contract", + args: args{ + contractName: "reserved", + }, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := mockReqCtx() + if got := c.GetTransAmount(tt.args.contractName); got != tt.want { + t.Errorf("reqContext.GetTransAmount() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_reqContext_IsReservedReq(t *testing.T) { + type args struct { + index int + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "reversed req", + args: args{ + index: 0, + }, + want: true, + }, + { + name: "not reversed req", + args: args{ + index: 1, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := mockReqCtx() + if got := c.IsReservedReq(tt.args.index); got != tt.want { + t.Errorf("reqContext.IsReservedReq() = %v, want %v", got, tt.want) + } + }) + } +} + +func mockReqCtx() *reqContext { + return &reqContext{ + transContractName: "transfer", + transAmount: big.NewInt(100), + requests: []*protos.InvokeRequest{ + { + ContractName: "reversed", + }, + { + ContractName: "transfer", + }, + }, + reservedReqCnt: 1, + } } diff --git a/kernel/engines/xuperos/engine.go b/kernel/engines/xuperos/engine.go index 63ef9b2b..b7d16b3b 100644 --- a/kernel/engines/xuperos/engine.go +++ b/kernel/engines/xuperos/engine.go @@ -2,7 +2,7 @@ package xuperos import ( "fmt" - "io/ioutil" + "os" "path/filepath" "sync" @@ -168,7 +168,7 @@ func (t *Engine) loadChains() error { dataDir := envCfg.GenDataAbsPath(envCfg.ChainDir) t.log.Trace("start load chain from blockchain data dir", "dir", dataDir) - dir, err := ioutil.ReadDir(dataDir) + dir, err := os.ReadDir(dataDir) if err != nil { t.log.Error("read blockchain data dir failed", "error", err, "dir", dataDir) return fmt.Errorf("read blockchain data dir failed") diff --git a/kernel/evm/eth_bench_test.go b/kernel/evm/eth_bench_test.go index 5cd15a9b..58e5e791 100644 --- a/kernel/evm/eth_bench_test.go +++ b/kernel/evm/eth_bench_test.go @@ -1,18 +1,18 @@ package evm import ( + "encoding/hex" + "os" + "testing" + _ "github.com/xuperchain/xupercore/bcs/contract/evm" _ "github.com/xuperchain/xupercore/bcs/contract/native" _ "github.com/xuperchain/xupercore/bcs/contract/xvm" - - "encoding/hex" "github.com/xuperchain/xupercore/kernel/contract" _ "github.com/xuperchain/xupercore/kernel/contract" _ "github.com/xuperchain/xupercore/kernel/contract/kernel" _ "github.com/xuperchain/xupercore/kernel/contract/manager" "github.com/xuperchain/xupercore/kernel/contract/mock" - "io/ioutil" - "testing" ) func BenchmarkEVM(b *testing.B) { @@ -35,12 +35,12 @@ func BenchmarkEVM(b *testing.B) { th := mock.NewTestHelper(contractConfig) defer th.Close() - bin, err := ioutil.ReadFile("testdata/counter.bin") + bin, err := os.ReadFile("testdata/counter.bin") if err != nil { b.Error(err) return } - abi, err := ioutil.ReadFile("testdata/counter.abi") + abi, err := os.ReadFile("testdata/counter.abi") if err != nil { b.Error(err) return From 0214a763645880549fb7ca91012edd949679f964 Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Wed, 15 Feb 2023 21:46:25 +0800 Subject: [PATCH 2/6] Fix gofmt --- kernel/engines/xuperos/chain_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/engines/xuperos/chain_test.go b/kernel/engines/xuperos/chain_test.go index 1113e711..4dcae224 100644 --- a/kernel/engines/xuperos/chain_test.go +++ b/kernel/engines/xuperos/chain_test.go @@ -541,9 +541,9 @@ func Test_reqContext_GetTransAmount(t *testing.T) { contractName string } tests := []struct { - name string - args args - want string + name string + args args + want string }{ { name: "target contract", @@ -575,9 +575,9 @@ func Test_reqContext_IsReservedReq(t *testing.T) { index int } tests := []struct { - name string - args args - want bool + name string + args args + want bool }{ { name: "reversed req", From 0f1f0d6467690c7b1fb0bfd1a2a1cf372ac26a60 Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Wed, 15 Feb 2023 22:13:01 +0800 Subject: [PATCH 3/6] Update go version in go.mod --- go.mod | 141 +-------------------------------------------------------- go.sum | 1 + 2 files changed, 2 insertions(+), 140 deletions(-) diff --git a/go.mod b/go.mod index 66bd1c48..94ccc7ce 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/xuperchain/xupercore -go 1.18 +go 1.16 require ( github.com/agiledragon/gomonkey/v2 v2.9.0 @@ -44,148 +44,9 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200626160457-b38283118816 // indirect - github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect - github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.20.1-beta // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/consensys/gnark v0.5.2 // indirect - github.com/consensys/gnark-crypto v0.5.3 // indirect - github.com/containerd/containerd v1.3.0 // indirect - github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect - github.com/coreos/go-semver v0.3.0 // indirect - github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 // indirect - github.com/dgraph-io/ristretto v0.1.0 // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect - github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 // indirect github.com/docker/go-connections v0.4.1-0.20180821093606-97c2040d34df // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/fxamacker/cbor/v2 v2.2.0 // indirect - github.com/go-kit/kit v0.9.0 // indirect - github.com/go-logfmt/logfmt v0.5.0 // indirect - github.com/go-stack/stack v1.8.0 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect - github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect - github.com/google/flatbuffers v1.12.0 // indirect github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa // indirect - github.com/google/gopacket v1.1.17 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/gorilla/websocket v1.4.2 // indirect - github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/huin/goupnp v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/ipfs/go-cid v0.0.7 // indirect - github.com/ipfs/go-datastore v0.4.4 // indirect - github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipns v0.0.2 // indirect - github.com/ipfs/go-log v1.0.4 // indirect - github.com/ipfs/go-log/v2 v2.1.1 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/jbenet/goprocess v0.1.4 // indirect - github.com/jmespath/go-jmespath v0.3.0 // indirect - github.com/klauspost/compress v1.12.3 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect - github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d // indirect - github.com/libp2p/go-addr-util v0.0.2 // indirect - github.com/libp2p/go-buffer-pool v0.0.2 // indirect - github.com/libp2p/go-conn-security-multistream v0.2.0 // indirect - github.com/libp2p/go-eventbus v0.2.1 // indirect - github.com/libp2p/go-flow-metrics v0.0.3 // indirect - github.com/libp2p/go-libp2p-autonat v0.3.2 // indirect - github.com/libp2p/go-libp2p-blankhost v0.2.0 // indirect - github.com/libp2p/go-libp2p-crypto v0.1.0 // indirect - github.com/libp2p/go-libp2p-discovery v0.5.0 // indirect - github.com/libp2p/go-libp2p-loggables v0.1.0 // indirect - github.com/libp2p/go-libp2p-mplex v0.2.4 // indirect - github.com/libp2p/go-libp2p-nat v0.0.6 // indirect - github.com/libp2p/go-libp2p-noise v0.1.1 // indirect - github.com/libp2p/go-libp2p-peer v0.2.0 // indirect - github.com/libp2p/go-libp2p-peerstore v0.2.6 // indirect - github.com/libp2p/go-libp2p-pnet v0.2.0 // indirect - github.com/libp2p/go-libp2p-tls v0.1.3 // indirect - github.com/libp2p/go-libp2p-transport-upgrader v0.3.0 // indirect - github.com/libp2p/go-libp2p-yamux v0.2.8 // indirect - github.com/libp2p/go-mplex v0.1.2 // indirect - github.com/libp2p/go-msgio v0.0.6 // indirect - github.com/libp2p/go-nat v0.0.5 // indirect - github.com/libp2p/go-netroute v0.1.3 // indirect - github.com/libp2p/go-openssl v0.0.7 // indirect - github.com/libp2p/go-reuseport v0.0.2 // indirect - github.com/libp2p/go-reuseport-transport v0.0.4 // indirect - github.com/libp2p/go-sockaddr v0.0.2 // indirect - github.com/libp2p/go-stream-muxer-multistream v0.3.0 // indirect - github.com/libp2p/go-tcp-transport v0.2.1 // indirect - github.com/libp2p/go-ws-transport v0.3.1 // indirect - github.com/libp2p/go-yamux v1.3.7 // indirect - github.com/magiconair/properties v1.8.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect - github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect - github.com/minio/sha256-simd v0.1.1 // indirect - github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.0.3 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.2.0 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multiaddr-net v0.2.0 // indirect - github.com/multiformats/go-multibase v0.0.3 // indirect - github.com/multiformats/go-multihash v0.0.14 // indirect - github.com/multiformats/go-multistream v0.1.2 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/opencontainers/go-digest v1.0.0-rc1 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v0.1.1 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pelletier/go-toml v1.2.0 // indirect - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect - github.com/prometheus/common v0.6.0 // indirect - github.com/prometheus/procfs v0.0.5 // indirect - github.com/sirupsen/logrus v1.4.2 // indirect - github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/afero v1.1.2 // indirect - github.com/spf13/cast v1.3.0 // indirect - github.com/spf13/jwalterweatherman v1.0.0 // indirect - github.com/spf13/pflag v1.0.3 // indirect - github.com/subosito/gotenv v1.2.0 // indirect - github.com/tendermint/go-amino v0.14.1 // indirect - github.com/tendermint/tendermint v0.33.1 // indirect - github.com/tmthrgd/atomics v0.0.0-20190904060638-dc7a5fcc7e0d // indirect - github.com/tmthrgd/go-bitset v0.0.0-20190904054048-394d9a556c05 // indirect - github.com/tmthrgd/go-bitwise v0.0.0-20190904053232-1430ee983fca // indirect - github.com/tmthrgd/go-byte-test v0.0.0-20190904060354-2794345b9929 // indirect - github.com/tmthrgd/go-memset v0.0.0-20190904060434-6fb7a21f88f1 // indirect - github.com/tmthrgd/go-popcount v0.0.0-20190904054823-afb1ace8b04f // indirect - github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc // indirect - github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect - github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect - github.com/x448/float16 v0.8.4 // indirect - github.com/xuperchain/wagon v0.6.1-0.20200313164333-db544e251599 // indirect - go.opencensus.io v0.22.5 // indirect - go.uber.org/atomic v1.6.0 // indirect - go.uber.org/multierr v1.5.0 // indirect - go.uber.org/zap v1.15.0 // indirect - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 // indirect - golang.org/x/text v0.3.3 // indirect - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect - google.golang.org/protobuf v1.25.0 // indirect - gopkg.in/ini.v1 v1.51.0 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect ) replace github.com/hyperledger/burrow => github.com/xuperchain/burrow v0.30.6-0.20211229032028-fbee6a05ab0f diff --git a/go.sum b/go.sum index 70669d97..7f737610 100644 --- a/go.sum +++ b/go.sum @@ -98,6 +98,7 @@ github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQY github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg= github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= github.com/dgraph-io/badger/v3 v3.2103.1 h1:zaX53IRg7ycxVlkd5pYdCeFp1FynD6qBGQoQql3R3Hk= github.com/dgraph-io/badger/v3 v3.2103.1/go.mod h1:dULbq6ehJ5K0cGW/1TQ9iSfUk0gbSiToDWmWmTsJ53E= From b710b0573e9c77c2454e407c28017451164ec53d Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Thu, 16 Feb 2023 10:09:58 +0800 Subject: [PATCH 4/6] Remove any --- kernel/engines/xuperos/chain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/engines/xuperos/chain_test.go b/kernel/engines/xuperos/chain_test.go index 4dcae224..82a22a21 100644 --- a/kernel/engines/xuperos/chain_test.go +++ b/kernel/engines/xuperos/chain_test.go @@ -457,7 +457,7 @@ func (m mockXContext) Err() error { panic("implement me") } -func (m mockXContext) Value(key any) any { +func (m mockXContext) Value(_ interface{}) interface{} { panic("implement me") } From b71ace56b610a4aa2e5e9eb70480c28d9d36f0fa Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Thu, 16 Feb 2023 18:33:20 +0800 Subject: [PATCH 5/6] Refactor transfer amount --- kernel/engines/xuperos/chain.go | 64 +++++------ kernel/engines/xuperos/chain_test.go | 164 ++++++++++++++------------- 2 files changed, 111 insertions(+), 117 deletions(-) diff --git a/kernel/engines/xuperos/chain.go b/kernel/engines/xuperos/chain.go index 6086e62c..712bc6fb 100644 --- a/kernel/engines/xuperos/chain.go +++ b/kernel/engines/xuperos/chain.go @@ -2,7 +2,6 @@ package xuperos import ( "fmt" - "math/big" "strings" "time" @@ -119,10 +118,6 @@ func (t *Chain) Context() *common.ChainCtx { func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiator string, authRequires []string) (*protos.InvokeResponse, error) { - if ctx == nil || ctx.GetLog() == nil { - return nil, common.ErrParameter - } - reqCtx, err := t.reqContext(ctx, reqs) if err != nil { return nil, err @@ -172,13 +167,15 @@ func (t *Chain) PreExec(ctx xctx.XContext, reqs []*protos.InvokeRequest, initiat func (t *Chain) preExecWithReservedReqs(reqCtx *reqContext, contractCtx *contract.ContextConfig) (*protos.InvokeResponse, error) { - reqCnt := len(reqCtx.requests) - invokeResp := &protos.InvokeResponse{ - Response: make([][]byte, 0, reqCnt), - Requests: make([]*protos.InvokeRequest, 0, reqCnt), - Responses: make([]*protos.ContractResponse, 0, reqCnt), - } - logger := reqCtx.logger + var ( + log = reqCtx.logger + reqCnt = len(reqCtx.requests) + invokeResp = &protos.InvokeResponse{ + Response: make([][]byte, 0, reqCnt), + Requests: make([]*protos.InvokeRequest, 0, reqCnt), + Responses: make([]*protos.ContractResponse, 0, reqCnt), + } + ) for idx, req := range reqCtx.requests { if req == nil { @@ -186,7 +183,7 @@ func (t *Chain) preExecWithReservedReqs(reqCtx *reqContext, } if req.ModuleName == "" && req.ContractName == "" && req.MethodName == "" { - logger.GetLog().Warn("PreExec req empty", "req", req) + log.Warn("PreExec req empty", "req", req) continue } if req.ModuleName == "" { @@ -202,10 +199,10 @@ func (t *Chain) preExecWithReservedReqs(reqCtx *reqContext, } contractCtx.ContractName = req.ContractName - contractCtx.TransferAmount = reqCtx.GetTransAmount(req.ContractName) + contractCtx.TransferAmount = req.Amount isReservedReq := reqCtx.IsReservedReq(idx) - err := t.preExecOnce(logger, contractCtx, req, isReservedReq, invokeResp) + err := t.preExecOnce(contractCtx, req, isReservedReq, invokeResp, log) if err != nil { return nil, err } @@ -214,15 +211,14 @@ func (t *Chain) preExecWithReservedReqs(reqCtx *reqContext, } // preExecOnce preExec one request with metrics -func (t *Chain) preExecOnce(logger xctx.XContext, contractCtx *contract.ContextConfig, - req *protos.InvokeRequest, isReservedReq bool, invokeResp *protos.InvokeResponse) error { +func (t *Chain) preExecOnce(contractCtx *contract.ContextConfig, req *protos.InvokeRequest, isReservedReq bool, invokeResp *protos.InvokeResponse, log logs.Logger) error { gasPrice := t.ctx.State.GetMeta().GetGasPrice() beginTime := time.Now() context, err := t.ctx.Contract.NewContext(contractCtx) if err != nil { - logger.GetLog().Error("PreExec NewContext error", "error", err, "contractName", req.ContractName) + log.Error("PreExec NewContext error", "error", err, "contractName", req.ContractName) if isReservedReq && strings.HasSuffix(err.Error(), "not found") { invokeResp.Requests = append(invokeResp.Requests, req) return nil @@ -233,7 +229,7 @@ func (t *Chain) preExecOnce(logger xctx.XContext, contractCtx *contract.ContextC resp, err := context.Invoke(req.MethodName, req.Args) if err != nil { - logger.GetLog().Error("PreExec Invoke error", "error", err, "contractName", req.ContractName) + log.Error("PreExec Invoke error", "error", err, "contractName", req.ContractName) metrics.ContractInvokeCounter. WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError"). Inc() @@ -241,7 +237,7 @@ func (t *Chain) preExecOnce(logger xctx.XContext, contractCtx *contract.ContextC } if resp.HasError() && isReservedReq { - logger.GetLog().Error("PreExec Invoke error", "status", resp.Status, "contractName", req.ContractName) + log.Error("PreExec Invoke error", "status", resp.Status, "contractName", req.ContractName) metrics.ContractInvokeCounter. WithLabelValues(t.ctx.BCName, req.ModuleName, req.ContractName, req.MethodName, "InvokeError"). Inc() @@ -492,24 +488,11 @@ func (t *Chain) CreateParaChain() error { // reqContext is context for PreExec requests type reqContext struct { - // trans info - - transContractName string - transAmount *big.Int - // requests contains [reservedReqs..., preExecReqs...] requests []*protos.InvokeRequest reservedReqCnt int - logger xctx.XContext -} - -// GetTransAmount get trans amount by contranct name -func (c *reqContext) GetTransAmount(contractName string) string { - if contractName == c.transContractName { - return c.transAmount.String() - } - return "" + logger logs.Logger } // IsReservedReq judges reserved request by index @@ -518,12 +501,18 @@ func (c *reqContext) IsReservedReq(index int) bool { } // reqContext creates context with chain reserved requests and PreExec requests -func (t *Chain) reqContext(logger xctx.XContext, reqs []*protos.InvokeRequest) (*reqContext, error) { +func (t *Chain) reqContext(ctx xctx.XContext, reqs []*protos.InvokeRequest) (*reqContext, error) { reqCtx := new(reqContext) var err error - // parse trans info from PreExec requests - reqCtx.transContractName, reqCtx.transAmount, err = tx.ParseContractTransferRequest(reqs) + // check logger + if ctx == nil || ctx.GetLog() == nil { + return nil, common.ErrParameter + } + reqCtx.logger = ctx.GetLog() + + // check transfer info from PreExec requests + _, _, err = tx.ParseContractTransferRequest(reqs) if err != nil { return nil, common.ErrParameter.More("%v", err) } @@ -537,6 +526,5 @@ func (t *Chain) reqContext(logger xctx.XContext, reqs []*protos.InvokeRequest) ( reqCtx.reservedReqCnt = len(reservedRequests) reqCtx.requests = append(reservedRequests, reqs...) - reqCtx.logger = logger return reqCtx, nil } diff --git a/kernel/engines/xuperos/chain_test.go b/kernel/engines/xuperos/chain_test.go index 82a22a21..f4b8e719 100644 --- a/kernel/engines/xuperos/chain_test.go +++ b/kernel/engines/xuperos/chain_test.go @@ -4,16 +4,20 @@ import ( "encoding/hex" "fmt" "math/big" + "math/rand" "os" "os/exec" "path/filepath" "reflect" "runtime" + "strconv" "testing" "time" "github.com/agiledragon/gomonkey/v2" "github.com/patrickmn/go-cache" + + "github.com/xuperchain/xupercore/bcs/ledger/xledger/state" "github.com/xuperchain/xupercore/bcs/ledger/xledger/state/utxo/txhash" lpb "github.com/xuperchain/xupercore/bcs/ledger/xledger/xldgpb" "github.com/xuperchain/xupercore/kernel/common/xaddress" @@ -247,7 +251,11 @@ func setup(t *testing.T) *gomonkey.Patches { } return exec.LookPath(arg) } - patch := gomonkey.ApplyFunc(exec.LookPath, mockLookPath) + patch := gomonkey. + ApplyFunc(exec.LookPath, mockLookPath). + ApplyMethod(reflect.TypeOf(new(state.State)), + "GetReservedContractRequests", + mockGetReservedContractRequests) return patch } @@ -289,13 +297,37 @@ func TestChain_PreExec(t *testing.T) { wantErr bool }{ { - name: "normal", + name: "req without reserved contract", args: args{ ctx: &mockXContext{logger: new(mockLogger)}, reqs: []*protos.InvokeRequest{mockReq("kernel")}, }, want: &protos.InvokeResponse{GasUsed: 1000}, }, + { + name: "req with abnormal reserved contract", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("req with abnormal reserved contract")}, + }, + wantErr: true, + }, + { + name: "req with normal reserved contract", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("req with normal reserved contract")}, + }, + want: &protos.InvokeResponse{GasUsed: 1000}, + }, + { + name: "abnormal req with normal reserved contract", + args: args{ + ctx: &mockXContext{logger: new(mockLogger)}, + reqs: []*protos.InvokeRequest{mockReq("abnormal req with normal reserved contract")}, + }, + wantErr: true, + }, { name: "contract method with invalid args", args: args{ @@ -400,47 +432,6 @@ func TestChain_preExecWithReservedReqs(t *testing.T) { } } -func TestChain_preExecOnce(t *testing.T) { - type fields struct { - ctx *common.ChainCtx - log logs.Logger - miner *miner.Miner - relyAgent common.ChainRelyAgent - txIdCache *cache.Cache - } - type args struct { - logger xctx.XContext - contractCtx *contract.ContextConfig - req *protos.InvokeRequest - isReservedReq bool - invokeResp *protos.InvokeResponse - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tr := &Chain{ - ctx: tt.fields.ctx, - log: tt.fields.log, - miner: tt.fields.miner, - relyAgent: tt.fields.relyAgent, - txIdCache: tt.fields.txIdCache, - } - if err := tr.preExecOnce(tt.args.logger, tt.args.contractCtx, tt.args.req, tt.args.isReservedReq, tt.args.invokeResp); (err != nil) != tt.wantErr { - t.Errorf("Chain.preExecOnce() error = %v\n"+ - "\twantErr %v", - err, tt.wantErr) - } - }) - } -} - type mockXContext struct { logger logs.Logger } @@ -523,51 +514,56 @@ func mockReq(req string) *protos.InvokeRequest { MethodName: "NewAccount", Args: nil, } + case "reserved contract": + return &protos.InvokeRequest{ + ModuleName: "wasm", + ContractName: "unified_check", + MethodName: "verify", + Args: map[string][]byte{ + "contract": []byte("$acl"), + }, + } + case "req with abnormal reserved contract": + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "NewAccount", + Args: mockKernelContractArgs("invalid args"), + } + case "req with normal reserved contract": + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "NewAccount", + Args: mockKernelContractArgs("normal contract"), + } + case "abnormal req with normal reserved contract": + return &protos.InvokeRequest{ + ModuleName: "xkernel", + ContractName: "$acl", + MethodName: "NewAccount", + Args: mockKernelContractArgs("normal contract"), + } default: return &protos.InvokeRequest{ ModuleName: "xkernel", ContractName: "$acl", MethodName: "NewAccount", - Args: map[string][]byte{ - "account_name": []byte("1234567890123456"), - "acl": []byte(`{"pm": {"rule": 1,"acceptValue": 1.0},"aksWeight": {"TeyyPLpp9L7QAcxHangtcHTu7HUZ6iydY": 1}}`), - }, + Args: mockKernelContractArgs(""), } } } -func Test_reqContext_GetTransAmount(t *testing.T) { - type args struct { - contractName string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "target contract", - args: args{ - contractName: "transfer", - }, - want: "100", - }, - { - name: "not target contract", - args: args{ - contractName: "reserved", - }, - want: "", - }, +func mockKernelContractArgs(reservedContractName string) map[string][]byte { + accountNumber := int64(rand.Uint32()) + 1234560000000000 + args := map[string][]byte{ + "account_name": []byte(strconv.FormatInt(accountNumber, 10)), + "acl": []byte(`{"pm": {"rule": 1,"acceptValue": 1.0},"aksWeight": {"TeyyPLpp9L7QAcxHangtcHTu7HUZ6iydY": 1}}`), } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := mockReqCtx() - if got := c.GetTransAmount(tt.args.contractName); got != tt.want { - t.Errorf("reqContext.GetTransAmount() = %v, want %v", got, tt.want) - } - }) + if reservedContractName != "" { + args["reserved"] = []byte(reservedContractName) } + return args } func Test_reqContext_IsReservedReq(t *testing.T) { @@ -606,8 +602,6 @@ func Test_reqContext_IsReservedReq(t *testing.T) { func mockReqCtx() *reqContext { return &reqContext{ - transContractName: "transfer", - transAmount: big.NewInt(100), requests: []*protos.InvokeRequest{ { ContractName: "reversed", @@ -619,3 +613,15 @@ func mockReqCtx() *reqContext { reservedReqCnt: 1, } } + +func mockGetReservedContractRequests(s *state.State, req []*protos.InvokeRequest, + isPreExec bool) ([]*protos.InvokeRequest, error) { + if len(req) > 0 && req[0].Args != nil { + mockReservedContrctName, ok := req[0].Args["reserved"] + if ok { + mockReq := mockReq(string(mockReservedContrctName)) + return []*protos.InvokeRequest{mockReq}, nil + } + } + return nil, nil +} From fe5c388ab99128c44abd05184b83798e7a9e0afb Mon Sep 17 00:00:00 2001 From: zhugelianglongming Date: Fri, 17 Feb 2023 10:44:39 +0800 Subject: [PATCH 6/6] Fix unit text --- kernel/engines/xuperos/chain_test.go | 63 ++++++---------------------- 1 file changed, 13 insertions(+), 50 deletions(-) diff --git a/kernel/engines/xuperos/chain_test.go b/kernel/engines/xuperos/chain_test.go index f4b8e719..dd65e99a 100644 --- a/kernel/engines/xuperos/chain_test.go +++ b/kernel/engines/xuperos/chain_test.go @@ -22,7 +22,6 @@ import ( lpb "github.com/xuperchain/xupercore/bcs/ledger/xledger/xldgpb" "github.com/xuperchain/xupercore/kernel/common/xaddress" xctx "github.com/xuperchain/xupercore/kernel/common/xcontext" - "github.com/xuperchain/xupercore/kernel/contract" "github.com/xuperchain/xupercore/kernel/engines/xuperos/common" "github.com/xuperchain/xupercore/kernel/engines/xuperos/miner" "github.com/xuperchain/xupercore/lib/logs" @@ -292,7 +291,7 @@ func TestChain_PreExec(t *testing.T) { name string fields fields args args - // don't care much about the specific content returned, so simply judge gasUsed + // we don't care much about the specific content returned, so simply judge gasUsed want *protos.InvokeResponse wantErr bool }{ @@ -390,48 +389,6 @@ func TestChain_PreExec(t *testing.T) { } } -func TestChain_preExecWithReservedReqs(t *testing.T) { - type fields struct { - ctx *common.ChainCtx - log logs.Logger - miner *miner.Miner - relyAgent common.ChainRelyAgent - txIdCache *cache.Cache - } - type args struct { - reqCtx *reqContext - contractCtx *contract.ContextConfig - } - tests := []struct { - name string - fields fields - args args - want *protos.InvokeResponse - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tr := &Chain{ - ctx: tt.fields.ctx, - log: tt.fields.log, - miner: tt.fields.miner, - relyAgent: tt.fields.relyAgent, - txIdCache: tt.fields.txIdCache, - } - got, err := tr.preExecWithReservedReqs(tt.args.reqCtx, tt.args.contractCtx) - if (err != nil) != tt.wantErr { - t.Errorf("Chain.preExecWithReservedReqs() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Chain.preExecWithReservedReqs() = %v, want %v", got, tt.want) - } - }) - } -} - type mockXContext struct { logger logs.Logger } @@ -541,10 +498,11 @@ func mockReq(req string) *protos.InvokeRequest { return &protos.InvokeRequest{ ModuleName: "xkernel", ContractName: "$acl", - MethodName: "NewAccount", + MethodName: "notExist", // method not exist Args: mockKernelContractArgs("normal contract"), } default: + // normal contract return &protos.InvokeRequest{ ModuleName: "xkernel", ContractName: "$acl", @@ -561,7 +519,7 @@ func mockKernelContractArgs(reservedContractName string) map[string][]byte { "acl": []byte(`{"pm": {"rule": 1,"acceptValue": 1.0},"aksWeight": {"TeyyPLpp9L7QAcxHangtcHTu7HUZ6iydY": 1}}`), } if reservedContractName != "" { - args["reserved"] = []byte(reservedContractName) + args[mockKeyReserved] = []byte(reservedContractName) } return args } @@ -614,12 +572,17 @@ func mockReqCtx() *reqContext { } } -func mockGetReservedContractRequests(s *state.State, req []*protos.InvokeRequest, - isPreExec bool) ([]*protos.InvokeRequest, error) { +// mockKeyReserved key for test case arguments to implement mockGetReservedContractRequests +// which denote reserved contract test data to be used in its test case +const mockKeyReserved = "reserved" + +func mockGetReservedContractRequests(_ *state.State, req []*protos.InvokeRequest, + _ bool) ([]*protos.InvokeRequest, error) { + if len(req) > 0 && req[0].Args != nil { - mockReservedContrctName, ok := req[0].Args["reserved"] + mockReservedContractName, ok := req[0].Args[mockKeyReserved] if ok { - mockReq := mockReq(string(mockReservedContrctName)) + mockReq := mockReq(string(mockReservedContractName)) return []*protos.InvokeRequest{mockReq}, nil } }