diff --git a/changeLog.md b/changeLog.md index f4b1e43..30aecdc 100644 --- a/changeLog.md +++ b/changeLog.md @@ -1,6 +1,15 @@ Go-conflux-sdk Change Log ============ +v1.6.0 +------------ +- Support 1559 related rpcs +- Return StoragePointProp in cfx_getParamsFromVote, which is introduced by CIP-107. + +v1.5.9 +------------ +- Support circuit breaker when creating client + v1.5.9 ------------ - Support circuit breaker when creating client diff --git a/client.go b/client.go index b327ee8..c357f23 100644 --- a/client.go +++ b/client.go @@ -6,6 +6,7 @@ package sdk import ( "context" + "fmt" "io" "sync/atomic" @@ -732,6 +733,22 @@ func (client *Client) GetPoSRewardByEpoch(epoch types.Epoch) (reward *postypes.E return } +// GetFeeHistory returns transaction base fee per gas and effective priority fee per gas for the requested/supported epoch range. +func (client *Client) GetFeeHistory(blockCount hexutil.Uint64, lastEpoch types.Epoch, rewardPercentiles []float64) (feeHistory *types.FeeHistory, err error) { + err = client.wrappedCallRPC(&feeHistory, "cfx_feeHistory", blockCount, lastEpoch, rewardPercentiles) + return +} + +func (client *Client) GetMaxPriorityFeePerGas() (maxPriorityFeePerGas *hexutil.Big, err error) { + err = client.wrappedCallRPC(&maxPriorityFeePerGas, "cfx_maxPriorityFeePerGas") + return +} + +func (client *Client) GetFeeBurnt(epoch ...*types.Epoch) (info *hexutil.Big, err error) { + err = client.wrappedCallRPC(&info, "cfx_getFeeBurnt", get1stEpochIfy(epoch)) + return +} + // CreateUnsignedTransaction creates an unsigned transaction by parameters, // and the other fields will be set to values fetched from conflux node. func (client *Client) CreateUnsignedTransaction(from types.Address, to types.Address, amount *hexutil.Big, data []byte) (types.UnsignedTransaction, error) { @@ -824,26 +841,125 @@ func (client *Client) ApplyUnsignedTransactionDefault(tx *types.UnsignedTransact } } - if tx.GasPrice == nil { - gasPrice, err := client.GetGasPrice() - if err != nil { - return errors.Wrap(err, "failed to get gas price") + if err := client.populateTxtypeAndGasPrice(tx); err != nil { + return err + } + + tx.ApplyDefault() + } + + return nil +} + +func (client *Client) populateTxtypeAndGasPrice(tx *types.UnsignedTransaction) error { + if tx.GasPrice != nil && (tx.MaxFeePerGas != nil || tx.MaxPriorityFeePerGas != nil) { + return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + } + + if tx.GasPrice != nil && (tx.Type == nil || *tx.Type == types.TRANSACTION_TYPE_LEGACY) { + tx.Type = types.TRANSACTION_TYPE_LEGACY.Ptr() + return nil + } + + has1559 := tx.MaxFeePerGas != nil || tx.MaxPriorityFeePerGas != nil + + gasFeeData, err := client.getFeeData() + if err != nil { + return errors.Wrap(err, "failed to get fee data") + } + + // set the txtype according to feeData + // - if support1559, then set txtype to 2 + // - if not support1559 + // - - if has maxFeePerGas or maxPriorityFeePerGas, then return error + // - - if contains accesslist, set txtype to 1 + // - - else set txtype to 0 + if tx.Type == nil { + if gasFeeData.isSupport1559() { + tx.Type = types.TRANSACTION_TYPE_1559.Ptr() + } else { + if has1559 { + return errors.New("not support 1559 but (maxFeePerGas or maxPriorityFeePerGas) specified") } - // conflux responsed gasprice offen be 0, but the min gasprice is 1 when sending transaction, so do this - if gasPrice.ToInt().Cmp(big.NewInt(constants.MinGasprice)) < 1 { - gasPrice = types.NewBigInt(constants.MinGasprice) + if tx.AccessList == nil { + tx.Type = types.TRANSACTION_TYPE_LEGACY.Ptr() + } else { + tx.Type = types.TRANSACTION_TYPE_2930.Ptr() } - tmp := hexutil.Big(*gasPrice) - tx.GasPrice = &tmp } + } - tx.ApplyDefault() + // if txtype is DynamicFeeTxType that means support 1559, so if gasPrice is not nil, set max... to gasPrice + if *tx.Type == types.TRANSACTION_TYPE_1559 { + if tx.GasPrice != nil { + tx.MaxFeePerGas = tx.GasPrice + tx.MaxPriorityFeePerGas = tx.GasPrice + tx.GasPrice = nil + return nil + } + + if tx.MaxPriorityFeePerGas == nil { + tx.MaxPriorityFeePerGas = (*hexutil.Big)(gasFeeData.maxPriorityFeePerGas) + } + if tx.MaxFeePerGas == nil { + tx.MaxFeePerGas = (*hexutil.Big)(gasFeeData.maxFeePerGas) + } + if tx.MaxFeePerGas.ToInt().Cmp(tx.MaxPriorityFeePerGas.ToInt()) < 0 { + return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", tx.MaxFeePerGas, tx.MaxPriorityFeePerGas) + } + return nil } + if tx.GasPrice != nil { + return nil + } + + tx.GasPrice = (*hexutil.Big)(gasFeeData.gasPrice) return nil } +type gasFeeData struct { + gasPrice *hexutil.Big + maxFeePerGas *hexutil.Big + maxPriorityFeePerGas *hexutil.Big +} + +func (g gasFeeData) isSupport1559() bool { + return g.maxPriorityFeePerGas != nil && g.maxFeePerGas != nil +} + +func (client *Client) getFeeData() (*gasFeeData, error) { + data := &gasFeeData{} + + gasPrice, err := client.GetGasPrice() + if err != nil { + return nil, err + } + data.gasPrice = gasPrice + + block, err := client.GetBlockByEpoch(types.EpochLatestState) + if err != nil { + return nil, err + } + basefee := block.BaseFeePerGas + + if basefee == nil { + return data, nil + } + + priorityFeePerGas, err := client.GetMaxPriorityFeePerGas() + if err != nil { + return nil, err + } + + data.maxPriorityFeePerGas = priorityFeePerGas + maxFeePerGas := new(big.Int).Mul(basefee.ToInt(), big.NewInt(2)) + maxFeePerGas = new(big.Int).Add(maxFeePerGas, data.maxPriorityFeePerGas.ToInt()) + data.maxFeePerGas = types.NewBigIntByRaw(maxFeePerGas) + return data, nil +} + // DeployContract deploys a contract by abiJSON, bytecode and consturctor params. // It returns a ContractDeployState instance which contains 3 channels for notifying when state changed. func (client *Client) DeployContract(option *types.ContractDeployOption, abiJSON []byte, @@ -977,12 +1093,6 @@ func (client *Client) GetCollateralInfo(epoch ...*types.Epoch) (info types.Stora return } -// /// Return information about total token supply. -// #[rpc(name = "cfx_getCollateralInfo")] -// fn get_collateral_info( -// &self, epoch_number: Option, -// ) -> JsonRpcResult; - // =====Debug RPC===== func (client *Client) GetEpochReceipts(epoch types.EpochOrBlockHash, include_eth_recepits ...bool) (receipts [][]types.TransactionReceipt, err error) { diff --git a/client_test.go b/client_test.go index f12af52..fc30efb 100644 --- a/client_test.go +++ b/client_test.go @@ -1,73 +1,18 @@ package sdk -// GoConvey COMPOSER -// Test NewClient -// Subject: New client use rpc client -// Given a node url and retry params -// When rpc dail error -// Return error -// When rpc dail success -// Return client instance import ( "context" - "encoding/json" "fmt" "os" "testing" - "time" - - . "bou.ke/monkey" - // "github.com/ethereum/go-ethereum/rpc" "github.com/Conflux-Chain/go-conflux-sdk/types" "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" - rpc "github.com/openweb3/go-rpc-provider" + "github.com/ethereum/go-ethereum/common" providers "github.com/openweb3/go-rpc-provider/provider_wrapper" - "github.com/pkg/errors" - . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" ) -func _TestNewClient(t *testing.T) { - - Convey("Subject: New client use rpc client", t, func() { - - Convey("Given a node url and retry params", func() { - - Convey("When rpc dail error", func() { - //stub for rpc.Dail - guard := Patch(rpc.Dial, func(_ string) (*rpc.Client, error) { - return nil, errors.New("rpc dail fail") - }) - defer guard.Unpatch() - - client, err := newClientWithOption("", ClientOption{}) - Convey("Return error", func() { - So(err, ShouldNotEqual, nil) - So(client, ShouldEqual, nil) - }) - }) - - Convey("When rpc dail success", func() { - //stub for rpc.Dail - guard := Patch(rpc.Dial, func(_ string) (*rpc.Client, error) { - return &rpc.Client{}, nil - }) - defer guard.Unpatch() - - client, err := newClientWithOption("", ClientOption{}) - // fmt.Printf("client:%+v,err:%+v", client, err) - - Convey("Return client instance", func() { - So(err, ShouldEqual, nil) - So(client, ShouldNotEqual, nil) - }) - }) - }) - }) - -} - func TestInterfaceImplementation(t *testing.T) { var _ ClientOperator = &Client{} } @@ -110,63 +55,33 @@ func callContextMid2(f providers.CallContextFunc) providers.CallContextFunc { } } -func _TestEstimateGasAndCollateralAlwaysWithGaspriceNil(t *testing.T) { - c := MustNewClient("https://test.confluxrpc.com", ClientOption{ +func TestSendTransaction(t *testing.T) { + client := MustNewClient("http://net8888cfx.confluxrpc.com", ClientOption{ KeystorePath: "./keystore", Logger: os.Stdout, }) - c.Provider().HookCallContext(func(f providers.CallContextFunc) providers.CallContextFunc { - return func(ctx context.Context, result interface{}, method string, args ...interface{}) error { - if method == "cfx_estimateGasAndCollateral" { - fmt.Printf("cfx_estimateGasAndCollateral args: %+v\n", args) - if args[0].(types.CallRequest).GasPrice != nil { - t.Fatalf("gasPrice should be nil") - } - } - return f(ctx, result, method, args...) - } + client.AccountManager.ImportKey("0x0ccb34a57c54b3e61effebbc3cf3baaf5a03cd07a90836f38d97e08bcd1662f3", "hello") + // assert.NoError(t, err) + client.AccountManager.UnlockDefault("hello") + + addr, _ := client.AccountManager.GetDefault() + + fmt.Printf("addr %v\n", addr) + + txHash, err := client.SendTransaction(types.UnsignedTransaction{ + UnsignedTransactionBase: types.UnsignedTransactionBase{ + AccessList: types.AccessList{types.AccessTuple{ + Address: *addr, + StorageKeys: []common.Hash{ + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), + }, + }}, + // Gas: types.NewBigInt(30000), + }, + To: addr, }) - c.AccountManager.Create("123456") - defaultAccount, _ := c.AccountManager.GetDefault() - c.EstimateGasAndCollateral( - types.CallRequest{ - GasPrice: types.NewBigInt(1000000000), - To: defaultAccount, - }) -} - -func _TestGetPosTxByNum(t *testing.T) { - c := MustNewClient("https://test-internal.confluxrpc.com", ClientOption{Logger: os.Stdout}) - tx, err := c.Pos().GetTransactionByNumber(*types.NewUint64(0x76657)) assert.NoError(t, err) - fmt.Printf("%v\n", tx) -} -func _TestDeposite(t *testing.T) { - c := MustNewClient("https://test.confluxrpc.com", ClientOption{Logger: os.Stdout}) - di, err := c.GetDepositList(cfxaddress.MustNew("cfxtest:aanhtnrex2nj56kkbws4yx0jeab34ae16pcap53w13")) - assert.NoError(t, err) - fmt.Printf("%v\n", di) -} - -func _TestGetFilterChanges(t *testing.T) { - c := MustNewClient("http://test-internal.confluxrpc.com", ClientOption{Logger: os.Stdout}) - filter := c.Filter() - fID, err := filter.NewFilter(types.LogFilter{}) - assert.NoError(t, err) - - ticker := time.NewTicker(time.Second) - for range ticker.C { - fcg, err := c.Filter().GetFilterChanges(*fID) - assert.NoError(t, err) - j, _ := json.MarshalIndent(fcg, "", " ") - fmt.Printf("new log json: , %s\n", j) - fmt.Printf("new log: %+v\n", fcg) - } -} + fmt.Println(txHash) -func _TestCall(t *testing.T) { - c := MustNewClient("http://net8888cfx.confluxrpc.com", ClientOption{Logger: os.Stdout}) - var result interface{} - c.CallRPC(&result, "pos_getEpochState", "0x1234") } diff --git a/go.mod b/go.mod index e74d8d0..f133ff4 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,8 @@ module github.com/Conflux-Chain/go-conflux-sdk -go 1.17 +go 1.18 require ( - bou.ke/monkey v1.0.2 github.com/ethereum/go-ethereum v1.10.15 github.com/mcuadros/go-defaults v1.2.0 github.com/openweb3/go-rpc-provider v0.3.2 @@ -12,7 +11,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/sirupsen/logrus v1.9.0 - github.com/smartystreets/goconvey v1.6.4 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 github.com/stretchr/testify v1.7.0 gopkg.in/urfave/cli.v1 v1.20.0 @@ -38,7 +36,6 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.7 // indirect github.com/google/uuid v1.1.5 // indirect - github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect @@ -50,7 +47,6 @@ require ( github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/klauspost/compress v1.14.1 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.12 // indirect @@ -66,7 +62,6 @@ require ( github.com/rjeczalik/notify v0.9.1 // indirect github.com/rs/cors v1.7.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect diff --git a/go.sum b/go.sum index ef08986..9f10c58 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= -bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -84,7 +82,6 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash 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 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -208,7 +205,6 @@ github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -261,7 +257,6 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -350,8 +345,7 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openweb3/go-rpc-provider v0.3.0 h1:8D22MVyUG/NrpspwonzOGOhLeWZhxjJdQd4VT5KdJy4= -github.com/openweb3/go-rpc-provider v0.3.0/go.mod h1:DYz40TbzhzyTA06UFqGIKSXp0uFot6ZKh4QarD//eZ0= +github.com/openweb3/go-rpc-provider v0.3.1/go.mod h1:DYz40TbzhzyTA06UFqGIKSXp0uFot6ZKh4QarD//eZ0= github.com/openweb3/go-rpc-provider v0.3.2 h1:njXVEXxM8GegJrdCaSU1o9XtpZNX1v7MnjZdOpHvwCQ= github.com/openweb3/go-rpc-provider v0.3.2/go.mod h1:DYz40TbzhzyTA06UFqGIKSXp0uFot6ZKh4QarD//eZ0= github.com/openweb3/go-sdk-common v0.0.0-20220720074746-a7134e1d372c h1:BrPXZpkTdmZe5bNjSSnxWqL44X9FcZ3xftLcYNkIJ68= @@ -401,9 +395,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= diff --git a/integration_test/client_cfx_test.go b/integration_test/client_cfx_test.go index 9a27507..b65f1d2 100644 --- a/integration_test/client_cfx_test.go +++ b/integration_test/client_cfx_test.go @@ -52,6 +52,8 @@ func genCfxTestConfig() rpctest.RpcTestConfig { "cfx_getAccountPendingTransactions": "GetAccountPendingTransactions", "cfx_getPoSEconomics": "GetPoSEconomics", "cfx_openedMethodGroups": "GetOpenedMethodGroups", + "cfx_maxPriorityFeePerGas": "GetMaxPriorityFeePerGas", + "cfx_feeHistory": "GetFeeHistory", } var rpc2FuncSelector map[string]func(params []interface{}) (string, []interface{}) = map[string]func(params []interface{}) (string, []interface{}){ @@ -95,8 +97,9 @@ func genCfxTestConfig() rpctest.RpcTestConfig { var onlyTestRpc map[string]bool = map[string]bool{} return rpctest.RpcTestConfig{ + ExamplesUrl: "https://raw.githubusercontent.com/Conflux-Chain/jsonrpc-spec/main/src/cfx/examples.json", - Client: sdk.MustNewClient("http://47.93.101.243", sdk.ClientOption{Logger: os.Stdout}), + Client: sdk.MustNewClient("http://39.100.93.109", sdk.ClientOption{Logger: os.Stdout}), Rpc2Func: rpc2Func, Rpc2FuncSelector: rpc2FuncSelector, diff --git a/interface.go b/interface.go index ac18388..fcab0fb 100644 --- a/interface.go +++ b/interface.go @@ -115,6 +115,9 @@ type ClientOperator interface { GetPoSEconomics(epoch ...*types.Epoch) (posEconomics types.PoSEconomics, err error) GetOpenedMethodGroups() (openedGroups []string, err error) GetPoSRewardByEpoch(epoch types.Epoch) (reward *postypes.EpochReward, err error) + GetFeeHistory(blockCount hexutil.Uint64, lastEpoch types.Epoch, rewardPercentiles []float64) (feeHistory *types.FeeHistory, err error) + GetMaxPriorityFeePerGas() (maxPriorityFeePerGas *hexutil.Big, err error) + GetFeeBurnt(epoch ...*types.Epoch) (info *hexutil.Big, err error) GetEpochReceipts(epoch types.EpochOrBlockHash, include_eth_recepits ...bool) (receipts [][]types.TransactionReceipt, err error) GetEpochReceiptsByPivotBlockHash(hash types.Hash) (receipts [][]types.TransactionReceipt, err error) diff --git a/types/access_list.go b/types/access_list.go new file mode 100644 index 0000000..1604b94 --- /dev/null +++ b/types/access_list.go @@ -0,0 +1,35 @@ +package types + +import ( + "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" + "github.com/ethereum/go-ethereum/common" + etypes "github.com/ethereum/go-ethereum/core/types" +) + +type AccessList []AccessTuple + +type AccessTuple struct { + Address cfxaddress.Address `json:"address"` + StorageKeys []common.Hash `json:"storageKeys"` +} + +func (a *AccessList) ToEthType() *etypes.AccessList { + var eValue etypes.AccessList + for _, tuple := range *a { + eValue = append(eValue, etypes.AccessTuple{ + Address: tuple.Address.MustGetCommonAddress(), + StorageKeys: tuple.StorageKeys, + }) + } + return &eValue +} + +func (a *AccessList) FromEthType(raw *etypes.AccessList, networkID uint32) { + *a = AccessList{} + for _, tuple := range *raw { + *a = append(*a, AccessTuple{ + Address: cfxaddress.MustNewFromCommon(tuple.Address, networkID), + StorageKeys: tuple.StorageKeys, + }) + } +} diff --git a/types/block.go b/types/block.go index 684a61e..971eba3 100644 --- a/types/block.go +++ b/types/block.go @@ -28,6 +28,7 @@ type BlockHeader struct { BlockNumber *hexutil.Big `json:"blockNumber"` GasLimit *hexutil.Big `json:"gasLimit"` GasUsed *hexutil.Big `json:"gasUsed"` + BaseFeePerGas *hexutil.Big `json:"baseFeePerGas"` Timestamp *hexutil.Big `json:"timestamp"` Difficulty *hexutil.Big `json:"difficulty"` PowQuality *hexutil.Big `json:"powQuality"` diff --git a/types/block_test.go b/types/block_test.go index 866a9ea..7ff2760 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -46,10 +46,10 @@ func TestRLPMarshalBlockHeader(t *testing.T) { func TestRLPMarshalBlock(t *testing.T) { testJsonStr1 := `{"hash":"0xa6528367a9287ed3a66fc64457db15e2aaa93104a3fd06d4f0a2beb6cc1f26c8","parentHash":"0x5aef321e4e49f430ad6322af8a0133eae83e635f7893c996eb127dcf24a00b14","height":"0x792776","miner":"cfx:aatxetsp0kdarpdb5stdyex11dr3x6sb0jw2gykec0","deferredStateRoot":"0xa979a8c492c44a512aa9529911a7862e1b61ce2aa441645e865def9219d2c68b","deferredReceiptsRoot":"0xd5f7e7960e9b56753868260c280746c01353dcd1b91a20cee2c919d0dc7bf78b","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","epochNumber":"0x792778","blockNumber":"0xf7cf1c","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x6026478e","difficulty":"0xa8b175a4dc","powQuality":"0x2223e36adc5","refereeHashes":["0x4e4fca2593068b1dc83ecae3c1eaf0e4d41623985fd03d7f15fc1d63f653e7d2"],"adaptive":false,"nonce":"0x209fc5fbe719dace","size":"0x0","custom":[],"posReference":null,"transactions":[]}` - testJsonStr2 := `{"hash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","parentHash":"0xa0c5975f77a557ab65eb1a137de52cd9d9a88f4b36add157ec3c0e2edce1351f","height":"0xf7cf1c","miner":"cfx:aamwwx800rcw63n42kbehesuukjdjcnu4ueu84nhp5","deferredStateRoot":"0x085123da2df1ab4d0af41b99396280ea8f7778048f78bc141118ca1b163d0d75","deferredReceiptsRoot":"0x7976c478fc5ae2d2abe95cd7ef488b439fbac961abedf4a1b0cdee4be6bab27e","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xbf9add52641cdeb9fec7fc8bbacfaf71592c37df34b1f36220003af8797dfb41","epochNumber":"0xf7cf1c","blockNumber":"0xf7cf20","gasLimit":"0x1c9c380","gasUsed":"0x2ef98","timestamp":"0x60b853f5","difficulty":"0x1371539f68f","powQuality":"0x204fb171a2c","refereeHashes":["0xd28aeb7aea7012a58d776b89f03bbed85d7ebd75e445323e02dcf28af8753750","0xa20f6152fb3434c0c1c3ce8176044476e4baa2db18d0cea9185932e7072fd0ac"],"adaptive":false,"nonce":"0xf1c5c1596190023b","size":"0x24a","custom":[],"posReference":null,"transactions":[{"hash":"0x740b71de5591fe87bf661d5c4a39cf2a1fbf8cf21b68928033a7382154c78d19","nonce":"0xe033d","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x0","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aan4cta4wa1av51anm00844cg01hf19zw2vufsvk4n","value":"0x3bd913e6c1df4000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x57199fc1aced9c518fb8f2a31978c434fd280173602f38002b7252c02573cb00","s":"0x3d0ef3327d226d46ed0a53aa4f5486666aab2a9423a8261b9456975ba1fde346"},{"hash":"0x536cb069dc9024625c3ae27fef0a32df6733bec0a159f1b4871741b73b0419cb","nonce":"0xe033e","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x1","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aam9ee2tdeajz4akcx3nyhgnmu7zw5hd2u0nnce7j5","value":"0x3ab4b07cc8db8000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x7b5ff9bb9a93bf9d974102a22a6323c86558c1cc776ad93af5f2f1df0f1c9918","s":"0x6aaddd6e3c988bd6b02b37cd8f211a26f6ecd759fb8744f5233a3dfcd2d10183"},{"hash":"0x18e0f546df2f56e8149bb9424d70201feb41f8e2ea7c1a850a03b8a2f508a8f7","nonce":"0x1063","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x2","from":"cfx:aakycdtv194ws11y73tsam7va08ex0ztmjrjaxuds3","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","value":"0x3635c9adc5dea00000","gasPrice":"0x1","gas":"0x28e04","contractCreated":null,"data":"0x5c350838000000000000000000000000000000000000000000000017931cda8bd511fb00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000013410df1bff5275ef4ee5ee02bb105bc49daaf520000000000000000000000000000000000000000000000000000000060b9a56e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000008d7df9316faa0586e175b5e6d03c6bda76e3d9500000000000000000000000008b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27","storageLimit":"0x1cc","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x2e2237b2baf72e80725d0cbd5aee2dd755a606c905e77e45883b2ed8998523ab","s":"0x3f3be41bbfab7d4aca6d8c45887882f61b2ed0cc8f00a4ab2ab197eaad2a8c70"}]}` - testJsonStr3 := `{"hash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","parentHash":"0xa0c5975f77a557ab65eb1a137de52cd9d9a88f4b36add157ec3c0e2edce1351f","height":"0xf7cf1c","miner":"cfx:aamwwx800rcw63n42kbehesuukjdjcnu4ueu84nhp5","deferredStateRoot":"0x085123da2df1ab4d0af41b99396280ea8f7778048f78bc141118ca1b163d0d75","deferredReceiptsRoot":"0x7976c478fc5ae2d2abe95cd7ef488b439fbac961abedf4a1b0cdee4be6bab27e","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xbf9add52641cdeb9fec7fc8bbacfaf71592c37df34b1f36220003af8797dfb41","epochNumber":"0xf7cf1c","blockNumber":"0xf7cf20","gasLimit":"0x1c9c380","gasUsed":"0x2ef98","timestamp":"0x60b853f5","difficulty":"0x1371539f68f","powQuality":"0x204fb171a2c","refereeHashes":["0xd28aeb7aea7012a58d776b89f03bbed85d7ebd75e445323e02dcf28af8753750","0xa20f6152fb3434c0c1c3ce8176044476e4baa2db18d0cea9185932e7072fd0ac"],"adaptive":false,"nonce":"0xf1c5c1596190023b","size":"0x24a","custom":["0x0102","0x0203"],"posReference":null,"transactions":[{"hash":"0x740b71de5591fe87bf661d5c4a39cf2a1fbf8cf21b68928033a7382154c78d19","nonce":"0xe033d","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x0","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aan4cta4wa1av51anm00844cg01hf19zw2vufsvk4n","value":"0x3bd913e6c1df4000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x57199fc1aced9c518fb8f2a31978c434fd280173602f38002b7252c02573cb00","s":"0x3d0ef3327d226d46ed0a53aa4f5486666aab2a9423a8261b9456975ba1fde346"},{"hash":"0x536cb069dc9024625c3ae27fef0a32df6733bec0a159f1b4871741b73b0419cb","nonce":"0xe033e","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x1","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aam9ee2tdeajz4akcx3nyhgnmu7zw5hd2u0nnce7j5","value":"0x3ab4b07cc8db8000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x7b5ff9bb9a93bf9d974102a22a6323c86558c1cc776ad93af5f2f1df0f1c9918","s":"0x6aaddd6e3c988bd6b02b37cd8f211a26f6ecd759fb8744f5233a3dfcd2d10183"},{"hash":"0x18e0f546df2f56e8149bb9424d70201feb41f8e2ea7c1a850a03b8a2f508a8f7","nonce":"0x1063","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x2","from":"cfx:aakycdtv194ws11y73tsam7va08ex0ztmjrjaxuds3","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","value":"0x3635c9adc5dea00000","gasPrice":"0x1","gas":"0x28e04","contractCreated":null,"data":"0x5c350838000000000000000000000000000000000000000000000017931cda8bd511fb00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000013410df1bff5275ef4ee5ee02bb105bc49daaf520000000000000000000000000000000000000000000000000000000060b9a56e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000008d7df9316faa0586e175b5e6d03c6bda76e3d9500000000000000000000000008b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27","storageLimit":"0x1cc","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","v":"0x0","r":"0x2e2237b2baf72e80725d0cbd5aee2dd755a606c905e77e45883b2ed8998523ab","s":"0x3f3be41bbfab7d4aca6d8c45887882f61b2ed0cc8f00a4ab2ab197eaad2a8c70"}]}` + testJsonStr2 := `{"hash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","parentHash":"0xa0c5975f77a557ab65eb1a137de52cd9d9a88f4b36add157ec3c0e2edce1351f","height":"0xf7cf1c","miner":"cfx:aamwwx800rcw63n42kbehesuukjdjcnu4ueu84nhp5","deferredStateRoot":"0x085123da2df1ab4d0af41b99396280ea8f7778048f78bc141118ca1b163d0d75","deferredReceiptsRoot":"0x7976c478fc5ae2d2abe95cd7ef488b439fbac961abedf4a1b0cdee4be6bab27e","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xbf9add52641cdeb9fec7fc8bbacfaf71592c37df34b1f36220003af8797dfb41","epochNumber":"0xf7cf1c","blockNumber":"0xf7cf20","gasLimit":"0x1c9c380","gasUsed":"0x2ef98","baseFeePerGas":null,"timestamp":"0x60b853f5","difficulty":"0x1371539f68f","powQuality":"0x204fb171a2c","refereeHashes":["0xd28aeb7aea7012a58d776b89f03bbed85d7ebd75e445323e02dcf28af8753750","0xa20f6152fb3434c0c1c3ce8176044476e4baa2db18d0cea9185932e7072fd0ac"],"adaptive":false,"nonce":"0xf1c5c1596190023b","size":"0x24a","custom":[],"posReference":null,"transactions":[{"type":"0x0","hash":"0x740b71de5591fe87bf661d5c4a39cf2a1fbf8cf21b68928033a7382154c78d19","nonce":"0xe033d","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x0","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aan4cta4wa1av51anm00844cg01hf19zw2vufsvk4n","value":"0x3bd913e6c1df4000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x57199fc1aced9c518fb8f2a31978c434fd280173602f38002b7252c02573cb00","s":"0x3d0ef3327d226d46ed0a53aa4f5486666aab2a9423a8261b9456975ba1fde346","yParity":"0x0"},{"type":"0x1","hash":"0x536cb069dc9024625c3ae27fef0a32df6733bec0a159f1b4871741b73b0419cb","nonce":"0xe033e","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x1","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aam9ee2tdeajz4akcx3nyhgnmu7zw5hd2u0nnce7j5","value":"0x3ab4b07cc8db8000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x7b5ff9bb9a93bf9d974102a22a6323c86558c1cc776ad93af5f2f1df0f1c9918","s":"0x6aaddd6e3c988bd6b02b37cd8f211a26f6ecd759fb8744f5233a3dfcd2d10183","yParity":"0x0"},{"type":"0x2","hash":"0x18e0f546df2f56e8149bb9424d70201feb41f8e2ea7c1a850a03b8a2f508a8f7","nonce":"0x1063","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x2","from":"cfx:aakycdtv194ws11y73tsam7va08ex0ztmjrjaxuds3","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","value":"0x3635c9adc5dea00000","gasPrice":"0x1","gas":"0x28e04","contractCreated":null,"data":"0x5c350838000000000000000000000000000000000000000000000017931cda8bd511fb00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000013410df1bff5275ef4ee5ee02bb105bc49daaf520000000000000000000000000000000000000000000000000000000060b9a56e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000008d7df9316faa0586e175b5e6d03c6bda76e3d9500000000000000000000000008b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27","storageLimit":"0x1cc","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x2e2237b2baf72e80725d0cbd5aee2dd755a606c905e77e45883b2ed8998523ab","s":"0x3f3be41bbfab7d4aca6d8c45887882f61b2ed0cc8f00a4ab2ab197eaad2a8c70","yParity":"0x0"}]}` + testJsonStr3 := `{"hash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","parentHash":"0xa0c5975f77a557ab65eb1a137de52cd9d9a88f4b36add157ec3c0e2edce1351f","height":"0xf7cf1c","miner":"cfx:aamwwx800rcw63n42kbehesuukjdjcnu4ueu84nhp5","deferredStateRoot":"0x085123da2df1ab4d0af41b99396280ea8f7778048f78bc141118ca1b163d0d75","deferredReceiptsRoot":"0x7976c478fc5ae2d2abe95cd7ef488b439fbac961abedf4a1b0cdee4be6bab27e","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xbf9add52641cdeb9fec7fc8bbacfaf71592c37df34b1f36220003af8797dfb41","epochNumber":"0xf7cf1c","blockNumber":"0xf7cf20","gasLimit":"0x1c9c380","gasUsed":"0x2ef98","baseFeePerGas":null,"timestamp":"0x60b853f5","difficulty":"0x1371539f68f","powQuality":"0x204fb171a2c","refereeHashes":["0xd28aeb7aea7012a58d776b89f03bbed85d7ebd75e445323e02dcf28af8753750","0xa20f6152fb3434c0c1c3ce8176044476e4baa2db18d0cea9185932e7072fd0ac"],"adaptive":false,"nonce":"0xf1c5c1596190023b","size":"0x24a","custom":["0x0102","0x0203"],"posReference":null,"transactions":[{"type":"0x0","hash":"0x740b71de5591fe87bf661d5c4a39cf2a1fbf8cf21b68928033a7382154c78d19","nonce":"0xe033d","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x0","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aan4cta4wa1av51anm00844cg01hf19zw2vufsvk4n","value":"0x3bd913e6c1df4000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x57199fc1aced9c518fb8f2a31978c434fd280173602f38002b7252c02573cb00","s":"0x3d0ef3327d226d46ed0a53aa4f5486666aab2a9423a8261b9456975ba1fde346","yParity":"0x0"},{"type":"0x1","hash":"0x536cb069dc9024625c3ae27fef0a32df6733bec0a159f1b4871741b73b0419cb","nonce":"0xe033e","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x1","from":"cfx:aapkcjr28dg976fzr43c5hf1rwn5xv8t1uy4r2yyeu","to":"cfx:aam9ee2tdeajz4akcx3nyhgnmu7zw5hd2u0nnce7j5","value":"0x3ab4b07cc8db8000","gasPrice":"0xa","gas":"0x5208","contractCreated":null,"data":"0x","storageLimit":"0x0","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x7b5ff9bb9a93bf9d974102a22a6323c86558c1cc776ad93af5f2f1df0f1c9918","s":"0x6aaddd6e3c988bd6b02b37cd8f211a26f6ecd759fb8744f5233a3dfcd2d10183","yParity":"0x0"},{"type":"0x2","hash":"0x18e0f546df2f56e8149bb9424d70201feb41f8e2ea7c1a850a03b8a2f508a8f7","nonce":"0x1063","blockHash":"0x26f15dc6f353485cdfb1b370becc4abfdacbd36e39c3f9f42be724fe4073cfeb","transactionIndex":"0x2","from":"cfx:aakycdtv194ws11y73tsam7va08ex0ztmjrjaxuds3","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","value":"0x3635c9adc5dea00000","gasPrice":"0x1","gas":"0x28e04","contractCreated":null,"data":"0x5c350838000000000000000000000000000000000000000000000017931cda8bd511fb00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000013410df1bff5275ef4ee5ee02bb105bc49daaf520000000000000000000000000000000000000000000000000000000060b9a56e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000008d7df9316faa0586e175b5e6d03c6bda76e3d9500000000000000000000000008b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27","storageLimit":"0x1cc","epochHeight":"0xf7cf19","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x2e2237b2baf72e80725d0cbd5aee2dd755a606c905e77e45883b2ed8998523ab","s":"0x3f3be41bbfab7d4aca6d8c45887882f61b2ed0cc8f00a4ab2ab197eaad2a8c70","yParity":"0x0"}]}` - for _, blockJson := range []string{testJsonStr3, testJsonStr2, testJsonStr1} { + for i, blockJson := range []string{testJsonStr1, testJsonStr2, testJsonStr3} { var block Block err := json.Unmarshal([]byte(blockJson), &block) fatalIfErr(t, err) @@ -70,7 +70,7 @@ func TestRLPMarshalBlock(t *testing.T) { blockJsonStr2 := string(jBytes2) if blockJsonStr != blockJsonStr2 { - t.Fatalf("expect %v, actual %v", blockJsonStr, blockJsonStr2) + t.Fatalf("item %d expect %v, actual %v", i, blockJsonStr, blockJsonStr2) } } } @@ -108,10 +108,10 @@ func TestRLPMarshalBlockSummary(t *testing.T) { func TestJsonMarhsalBlock(t *testing.T) { jsons := []string{ - `{"hash":"0x6720dc2e79931b4727289612cb3a8ead65f65a3cd1d079348601c52116713b73","parentHash":"0x9154c74219f6e556372e252cf2dd9e675ebcf1a7c257e31cf5a8c3cd79c336f5","height":"0x22","miner":"net8888:aajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaph895n0mm","deferredStateRoot":"0x223ca6a2e599d487f739a0586bf26c88b8032f10f7607cb4e623d100675ef3b0","deferredReceiptsRoot":"0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","epochNumber":"0x22","blockNumber":"0x22","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x619daead","difficulty":"0x1f4","powQuality":"0x1f6","refereeHashes":[],"adaptive":false,"nonce":"0x865a421661e90c0e","size":"0x0","custom":[],"posReference":null,"transactions":[]}`, - `{"hash":"0x6720dc2e79931b4727289612cb3a8ead65f65a3cd1d079348601c52116713b73","parentHash":"0x9154c74219f6e556372e252cf2dd9e675ebcf1a7c257e31cf5a8c3cd79c336f5","height":"0x22","miner":"net8888:aajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaph895n0mm","deferredStateRoot":"0x223ca6a2e599d487f739a0586bf26c88b8032f10f7607cb4e623d100675ef3b0","deferredReceiptsRoot":"0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","epochNumber":"0x22","blockNumber":"0x22","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x619daead","difficulty":"0x1f4","powQuality":"0x1f6","refereeHashes":[],"adaptive":false,"nonce":"0x865a421661e90c0e","size":"0x0","custom":["0x0102"],"posReference":null,"transactions":[]}`, + `{"hash":"0x6720dc2e79931b4727289612cb3a8ead65f65a3cd1d079348601c52116713b73","parentHash":"0x9154c74219f6e556372e252cf2dd9e675ebcf1a7c257e31cf5a8c3cd79c336f5","height":"0x22","miner":"net8888:aajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaph895n0mm","deferredStateRoot":"0x223ca6a2e599d487f739a0586bf26c88b8032f10f7607cb4e623d100675ef3b0","deferredReceiptsRoot":"0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","epochNumber":"0x22","blockNumber":"0x22","gasLimit":"0x1c9c380","gasUsed":"0x0","baseFeePerGas":null,"timestamp":"0x619daead","difficulty":"0x1f4","powQuality":"0x1f6","refereeHashes":[],"adaptive":false,"nonce":"0x865a421661e90c0e","size":"0x0","custom":[],"posReference":null,"transactions":[]}`, + `{"hash":"0x6720dc2e79931b4727289612cb3a8ead65f65a3cd1d079348601c52116713b73","parentHash":"0x9154c74219f6e556372e252cf2dd9e675ebcf1a7c257e31cf5a8c3cd79c336f5","height":"0x22","miner":"net8888:aajaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaph895n0mm","deferredStateRoot":"0x223ca6a2e599d487f739a0586bf26c88b8032f10f7607cb4e623d100675ef3b0","deferredReceiptsRoot":"0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508","deferredLogsBloomHash":"0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5","blame":"0x0","transactionsRoot":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","epochNumber":"0x22","blockNumber":"0x22","gasLimit":"0x1c9c380","gasUsed":"0x0","baseFeePerGas":null,"timestamp":"0x619daead","difficulty":"0x1f4","powQuality":"0x1f6","refereeHashes":[],"adaptive":false,"nonce":"0x865a421661e90c0e","size":"0x0","custom":["0x0102"],"posReference":null,"transactions":[]}`, } - for _, j := range jsons { + for i, j := range jsons { var b Block e := json.Unmarshal([]byte(j), &b) if e != nil { @@ -123,7 +123,7 @@ func TestJsonMarhsalBlock(t *testing.T) { t.Fatal(e) } if string(d) != j { - t.Fatalf("expect %v, actual %v", j, string(d)) + t.Fatalf("item %d expect %v, actual %v", i, j, string(d)) } } } diff --git a/types/fee_history.go b/types/fee_history.go new file mode 100644 index 0000000..9fdecc4 --- /dev/null +++ b/types/fee_history.go @@ -0,0 +1,12 @@ +package types + +import "github.com/ethereum/go-ethereum/common/hexutil" + +type FeeHistory struct { + OldestEpoch *hexutil.Big `json:"oldestEpoch"` + Reward [][]*hexutil.Big `json:"reward,omitempty"` + BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` + GasUsedRatio []float64 `json:"gasUsedRatio"` + BlobBaseFee []*hexutil.Big `json:"baseFeePerBlobGas,omitempty"` + BlobGasUsedRatio []float64 `json:"blobGasUsedRatio,omitempty"` +} diff --git a/types/option.go b/types/option.go index d81f9ec..f50bb0b 100644 --- a/types/option.go +++ b/types/option.go @@ -42,6 +42,11 @@ type CallRequest struct { Data *string `json:"data,omitempty"` Nonce *hexutil.Big `json:"nonce,omitempty"` StorageLimit *hexutil.Uint64 `json:"storageLimit,omitempty"` + + MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + MaxFeePerGas *hexutil.Big `json:"maxFeePerGas,omitempty"` + AccessList AccessList `json:"accessList,omitempty"` + TransactionType *hexutil.Uint64 `json:"type,omitempty"` } // FillByUnsignedTx fills CallRequest fields by tx @@ -63,6 +68,8 @@ func (request *CallRequest) FillByUnsignedTx(tx *UnsignedTransaction) { if tx.Nonce != nil { request.Nonce = tx.Nonce } + + request.AccessList = tx.AccessList } } diff --git a/types/pos/pos.go b/types/pos/pos.go index 6d20d94..072a1d4 100644 --- a/types/pos/pos.go +++ b/types/pos/pos.go @@ -79,6 +79,7 @@ type VoteParamsInfo struct { PowBaseReward *hexutil.Big `json:"powBaseReward"` InterestRate *hexutil.Big `json:"interestRate"` StoragePointProp *hexutil.Big `json:"storagePointProp"` + BaseFeeShareProp *hexutil.Big `json:"baseFeeShareProp"` } type Block struct { diff --git a/types/transaction.go b/types/transaction.go index bf9d335..affc0a4 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -11,14 +11,17 @@ import ( "github.com/Conflux-Chain/go-conflux-sdk/types/enums" "github.com/ethereum/go-ethereum/common/hexutil" + etypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" + "github.com/pkg/errors" ) // Transaction represents a transaction with signature in Conflux. // it is the response from conflux node when sending rpc request, such as cfx_getTransactionByHash type Transaction struct { - // Space *string `json:"space,omitempty"` //currently it is always "nil", so comment it now and uncomment it if need later + // Space *string `json:"space,omitempty"` //currently it is always "nil", so comment it now and uncomment it if need later + TransactionType *hexutil.Uint64 `json:"type,omitempty"` Hash Hash `json:"hash"` Nonce *hexutil.Big `json:"nonce"` BlockHash *Hash `json:"blockHash"` @@ -35,14 +38,20 @@ type Transaction struct { ChainID *hexutil.Big `json:"chainId"` Status *hexutil.Uint64 `json:"status"` + AccessList *AccessList `json:"accessList,omitempty"` + MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + MaxFeePerGas *hexutil.Big `json:"maxFeePerGas,omitempty"` + //signature - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` + V *hexutil.Big `json:"v"` + R *hexutil.Big `json:"r"` + S *hexutil.Big `json:"s"` + YParity *hexutil.Uint64 `json:"yParity,omitempty"` } // rlpEncodableTransaction transaction struct used for rlp encoding type rlpEncodableTransaction struct { + TransactionType *hexutil.Uint64 Hash Hash Nonce *big.Int BlockHash *Hash @@ -59,38 +68,51 @@ type rlpEncodableTransaction struct { ChainID *big.Int Status *hexutil.Uint64 + AccessList *etypes.AccessList + MaxPriorityFeePerGas *big.Int + MaxFeePerGas *big.Int + //signature - V *big.Int - R *big.Int - S *big.Int + V *big.Int + R *big.Int + S *big.Int + YParity *hexutil.Uint64 } // EncodeRLP implements the rlp.Encoder interface. func (tx Transaction) EncodeRLP(w io.Writer) error { rtx := rlpEncodableTransaction{ + tx.TransactionIndex, tx.Hash, tx.Nonce.ToInt(), tx.BlockHash, tx.TransactionIndex, tx.From, tx.To, tx.Value.ToInt(), tx.GasPrice.ToInt(), tx.Gas.ToInt(), tx.ContractCreated, tx.Data, tx.StorageLimit.ToInt(), tx.EpochHeight.ToInt(), tx.ChainID.ToInt(), tx.Status, - tx.V.ToInt(), tx.R.ToInt(), tx.S.ToInt(), + tx.AccessList.ToEthType(), tx.MaxPriorityFeePerGas.ToInt(), tx.MaxFeePerGas.ToInt(), + tx.V.ToInt(), tx.R.ToInt(), tx.S.ToInt(), tx.YParity, } return rlp.Encode(w, rtx) } // DecodeRLP implements the rlp.Decoder interface. -func (tx *Transaction) DecodeRLP(r *rlp.Stream) error { +func (tx *Transaction) DecodeRLP(r *rlp.Stream, networkID uint32) error { var rtx rlpEncodableTransaction if err := r.Decode(&rtx); err != nil { return err } + var accessList AccessList + accessList.FromEthType(rtx.AccessList, networkID) + + tx.TransactionType = rtx.TransactionType tx.Hash, tx.Nonce, tx.BlockHash = rtx.Hash, (*hexutil.Big)(rtx.Nonce), rtx.BlockHash tx.TransactionIndex, tx.From, tx.To = rtx.TransactionIndex, rtx.From, rtx.To tx.Value, tx.GasPrice = (*hexutil.Big)(rtx.Value), (*hexutil.Big)(rtx.GasPrice) tx.Gas, tx.ContractCreated, tx.Data = (*hexutil.Big)(rtx.Gas), rtx.ContractCreated, rtx.Data tx.StorageLimit, tx.EpochHeight = (*hexutil.Big)(rtx.StorageLimit), (*hexutil.Big)(rtx.EpochHeight) - tx.ChainID, tx.Status, tx.V = (*hexutil.Big)(rtx.ChainID), rtx.Status, (*hexutil.Big)(rtx.V) - tx.R, tx.S = (*hexutil.Big)(rtx.R), (*hexutil.Big)(rtx.S) + tx.ChainID, tx.Status = (*hexutil.Big)(rtx.ChainID), rtx.Status + tx.AccessList, tx.MaxPriorityFeePerGas, tx.MaxFeePerGas = &accessList, (*hexutil.Big)(rtx.MaxPriorityFeePerGas), (*hexutil.Big)(rtx.MaxFeePerGas) + tx.V, tx.R, tx.S = (*hexutil.Big)(rtx.V), (*hexutil.Big)(rtx.R), (*hexutil.Big)(rtx.S) + tx.YParity = rtx.YParity return nil } @@ -98,6 +120,7 @@ func (tx *Transaction) DecodeRLP(r *rlp.Stream) error { // TransactionReceipt represents the transaction execution result in Conflux. // it is the response from conflux node when sending rpc request, such as cfx_getTransactionReceipt type TransactionReceipt struct { + Type *hexutil.Uint64 `json:"type,omitempty"` TransactionHash Hash `json:"transactionHash"` Index hexutil.Uint64 `json:"index"` BlockHash Hash `json:"blockHash"` @@ -107,6 +130,7 @@ type TransactionReceipt struct { GasUsed *hexutil.Big `json:"gasUsed"` AccumulatedGasUsed *hexutil.Big `json:"accumulatedGasUsed,omitempty"` GasFee *hexutil.Big `json:"gasFee"` + EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"` ContractCreated *Address `json:"contractCreated"` Logs []Log `json:"logs"` LogsBloom Bloom `json:"logsBloom"` @@ -122,6 +146,7 @@ type TransactionReceipt struct { // Storage collaterals released during the execution of the transaction. StorageReleased []StorageChange `json:"storageReleased"` Space *SpaceType `json:"space,omitempty"` + BurntGasFee *hexutil.Big `json:"burntGasFee,omitempty"` } func (r *TransactionReceipt) GetOutcomeType() (enums.TransactionOutcome, error) { @@ -169,20 +194,22 @@ type StorageChange struct { // rlpEncodableTransactionReceipt transaction receipt struct used for rlp encoding type rlpEncodableTransactionReceipt struct { - TransactionHash Hash - Index hexutil.Uint64 - BlockHash Hash - EpochNumber *hexutil.Uint64 - From Address - To *Address `rlp:"nil"` - GasUsed *big.Int - GasFee *big.Int - ContractCreated *Address `rlp:"nil"` // nil means contract creation - Logs []Log - LogsBloom Bloom - StateRoot Hash - OutcomeStatus hexutil.Uint64 - TxExecErrorMsg *string `rlp:"nil"` + Type *hexutil.Uint64 + TransactionHash Hash + Index hexutil.Uint64 + BlockHash Hash + EpochNumber *hexutil.Uint64 + From Address + To *Address `rlp:"nil"` + GasUsed *big.Int + GasFee *big.Int + EffectiveGasPrice *big.Int + ContractCreated *Address `rlp:"nil"` // nil means contract creation + Logs []Log + LogsBloom Bloom + StateRoot Hash + OutcomeStatus hexutil.Uint64 + TxExecErrorMsg *string `rlp:"nil"` // Whether gas costs were covered by the sponsor. GasCoveredBySponsor bool // Whether storage costs were covered by the sponsor. @@ -191,15 +218,18 @@ type rlpEncodableTransactionReceipt struct { StorageCollateralized hexutil.Uint64 // Storage collaterals released during the execution of the transaction. StorageReleased []StorageChange + BurntGasFee *big.Int } // EncodeRLP implements the rlp.Encoder interface. func (tr TransactionReceipt) EncodeRLP(w io.Writer) error { rtx := rlpEncodableTransactionReceipt{ + tr.Type, tr.TransactionHash, tr.Index, tr.BlockHash, tr.EpochNumber, tr.From, tr.To, - tr.GasUsed.ToInt(), tr.GasFee.ToInt(), tr.ContractCreated, tr.Logs, tr.LogsBloom, + tr.GasUsed.ToInt(), tr.GasFee.ToInt(), tr.EffectiveGasPrice.ToInt(), tr.ContractCreated, tr.Logs, tr.LogsBloom, tr.StateRoot, tr.OutcomeStatus, tr.TxExecErrorMsg, tr.GasCoveredBySponsor, tr.StorageCoveredBySponsor, tr.StorageCollateralized, tr.StorageReleased, + tr.BurntGasFee.ToInt(), } return rlp.Encode(w, rtx) @@ -212,14 +242,15 @@ func (tr *TransactionReceipt) DecodeRLP(r *rlp.Stream) error { return err } + tr.Type = rtr.Type tr.TransactionHash, tr.Index, tr.BlockHash = rtr.TransactionHash, rtr.Index, rtr.BlockHash tr.EpochNumber, tr.From, tr.To = rtr.EpochNumber, rtr.From, rtr.To - tr.GasUsed, tr.GasFee = (*hexutil.Big)(rtr.GasUsed), (*hexutil.Big)(rtr.GasFee) + tr.GasUsed, tr.GasFee, tr.EffectiveGasPrice = (*hexutil.Big)(rtr.GasUsed), (*hexutil.Big)(rtr.GasFee), (*hexutil.Big)(rtr.EffectiveGasPrice) tr.ContractCreated, tr.Logs, tr.LogsBloom = rtr.ContractCreated, rtr.Logs, rtr.LogsBloom tr.StateRoot, tr.OutcomeStatus, tr.TxExecErrorMsg = rtr.StateRoot, rtr.OutcomeStatus, rtr.TxExecErrorMsg tr.GasCoveredBySponsor, tr.StorageCoveredBySponsor = rtr.GasCoveredBySponsor, rtr.StorageCoveredBySponsor tr.StorageCollateralized, tr.StorageReleased = rtr.StorageCollateralized, rtr.StorageReleased - + tr.BurntGasFee = (*hexutil.Big)(rtr.BurntGasFee) return nil } diff --git a/types/transaction_signed.go b/types/transaction_signed.go index 60c05ab..7c3f861 100644 --- a/types/transaction_signed.go +++ b/types/transaction_signed.go @@ -6,6 +6,7 @@ package types import ( "math/big" + "slices" "github.com/Conflux-Chain/go-conflux-sdk/utils/addressutil" "github.com/ethereum/go-ethereum/common/hexutil" @@ -14,14 +15,6 @@ import ( "github.com/pkg/errors" ) -// signedTransactionForRlp is a intermediate struct for encoding rlp data -type signedTransactionForRlp struct { - UnsignedData *unsignedTransactionForRlp - V byte - R *big.Int - S *big.Int -} - // SignedTransaction represents a transaction with signature, // it is the transaction information for sending transaction. type SignedTransaction struct { @@ -31,27 +24,110 @@ type SignedTransaction struct { S hexutil.Bytes } +// signedTransactionForRlp is a intermediate struct for encoding rlp data +type signedTransactionForRlp struct { + UnsignedData interface{} + V byte + R *big.Int + S *big.Int +} + +// geneic format of type signedTransactionForRlp +type gSignedTransactionForRlp[T any] struct { + UnsignedData T + V byte + R *big.Int + S *big.Int +} + +// convert from gSignedTransactionForRlp to signedTransactionForRlp +func (g gSignedTransactionForRlp[T]) toRaw() *signedTransactionForRlp { + return &signedTransactionForRlp{ + UnsignedData: g.UnsignedData, + V: g.V, + R: g.R, + S: g.S, + } +} + // Decode decodes RLP encoded data to tx func (tx *SignedTransaction) Decode(data []byte, networkID uint32) error { - txForRlp := new(signedTransactionForRlp) - err := rlp.DecodeBytes(data, txForRlp) - if err != nil { - return err + + if !slices.Equal(data[:3], TRANSACTION_TYPE_PREFIX) { + txForRlp := new(gSignedTransactionForRlp[unsignedLegacyTransactionForRlp]) + err := rlp.DecodeBytes(data, txForRlp) + if err != nil { + return err + } + + _tx, err := txForRlp.toRaw().toSignedTransaction(networkID) + if err != nil { + return err + } + *tx = *_tx + return nil } - *tx = *txForRlp.toSignedTransaction(networkID) - return nil + txType := TransactionType(data[3]) + switch txType { + case TRANSACTION_TYPE_2930: + txForRlp := new(gSignedTransactionForRlp[unsigned2930TransactionForRlp]) + err := rlp.DecodeBytes(data[4:], txForRlp) + if err != nil { + return err + } + + _tx, err := txForRlp.toRaw().toSignedTransaction(networkID) + if err != nil { + return err + } + *tx = *_tx + return nil + + case TRANSACTION_TYPE_1559: + txForRlp := new(gSignedTransactionForRlp[unsigned1559TransactionForRlp]) + err := rlp.DecodeBytes(data[4:], txForRlp) + if err != nil { + return err + } + + _tx, err := txForRlp.toRaw().toSignedTransaction(networkID) + if err != nil { + return err + } + *tx = *_tx + return nil + + default: + return errors.Errorf("unknown transaction type %d", txType) + } } -//Encode encodes tx and returns its RLP encoded data +// Encode encodes tx and returns its RLP encoded data; Encode format is "cfx||tx_type||body_rlp" func (tx *SignedTransaction) Encode() ([]byte, error) { - txForRlp := *tx.toStructForRlp() - encoded, err := rlp.EncodeToBytes(txForRlp) + _tx := *tx + if tx.UnsignedTransaction.Type == nil { + _tx.UnsignedTransaction.Type = TRANSACTION_TYPE_LEGACY.Ptr() + } + + txForRlp, err := _tx.toStructForRlp() + if err != nil { + return nil, err + } + + bodyRlp, err := rlp.EncodeToBytes(txForRlp) if err != nil { return nil, err } - return encoded, nil + if *_tx.UnsignedTransaction.Type == TRANSACTION_TYPE_LEGACY { + return bodyRlp, nil + } else { + data := append([]byte{}, TRANSACTION_TYPE_PREFIX...) + data = append(data, byte(*_tx.UnsignedTransaction.Type)) + data = append(data, bodyRlp...) + return data, nil + } } // Hash calculates the hash of the transaction rlp encode result @@ -88,22 +164,30 @@ func (tx *SignedTransaction) Signature() []byte { return sig } -func (tx *SignedTransaction) toStructForRlp() *signedTransactionForRlp { +func (tx *SignedTransaction) toStructForRlp() (*signedTransactionForRlp, error) { + untxForRlp, err := tx.UnsignedTransaction.toStructForRlp() + if err != nil { + return nil, err + } + txForRlp := signedTransactionForRlp{ - UnsignedData: tx.UnsignedTransaction.toStructForRlp(), + UnsignedData: untxForRlp, V: tx.V, R: big.NewInt(0).SetBytes(tx.R), S: big.NewInt(0).SetBytes(tx.S), } - return &txForRlp + return &txForRlp, nil } -func (tx *signedTransactionForRlp) toSignedTransaction(networkID uint32) *SignedTransaction { - unsigned := tx.UnsignedData.toUnsignedTransaction(networkID) +func (tx *signedTransactionForRlp) toSignedTransaction(networkID uint32) (*SignedTransaction, error) { + unsigned, err := toUnsignedTransaction(tx.UnsignedData, networkID) + if err != nil { + return nil, err + } return &SignedTransaction{ UnsignedTransaction: *unsigned, V: tx.V, R: tx.R.Bytes(), S: tx.S.Bytes(), - } + }, nil } diff --git a/types/transaction_signed_test.go b/types/transaction_signed_test.go index 71f8676..d8fae6d 100644 --- a/types/transaction_signed_test.go +++ b/types/transaction_signed_test.go @@ -7,82 +7,94 @@ import ( "testing" "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/status-im/keycard-go/hexutils" "github.com/stretchr/testify/assert" ) -func TestDecodeTransaction(t *testing.T) { - rawData := `0xf84dc901010180010101010101a0ca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31a036953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea` - tx := SignedTransaction{} - b := mustDecodeStringToBytes(t, rawData) - err := tx.Decode(b, 1037) - if err != nil { - t.Fatal(err) - } +func TestEncodeSignedTransaction(t *testing.T) { - b, err = json.Marshal(tx) - if err != nil { - t.Fatal(err) + table := []struct { + raw string + expect string + }{ + { + raw: `{"UnsignedTransaction":{"From":null,"Nonce":"0x1","GasPrice":"0x1","Gas":"0x1","Value":"0x1","StorageLimit":"0x1","EpochHeight":"0x1","ChainID":"0x1","AccessList":null,"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":null,"To":null,"Data":"0x01"},"V":1,"R":"0xca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31","S":"0x36953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea"}`, + expect: `f84dc901010180010101010101a0ca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31a036953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea`, + }, + { + raw: `{"UnsignedTransaction":{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":1,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"},"V":0,"R":"0x01","S":"0x01"}`, + expect: `63667801f868f8636464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef800101`, + }, + { + raw: `{"UnsignedTransaction":{"From":null,"Nonce":"0x64","GasPrice":null,"Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":"0x64","MaxFeePerGas":"0x64","Type":2,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"},"V":0,"R":"0x01","S":"0x01"}`, + expect: `63667802f869f864646464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef800101`, + }, } - expect := `{"UnsignedTransaction":{"From":null,"Nonce":"0x1","GasPrice":"0x1","Gas":"0x1","Value":"0x1","StorageLimit":"0x1","EpochHeight":"0x1","ChainID":"0x1","To":null,"Data":"0x01"},"V":1,"R":"0xca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31","S":"0x36953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea"}` + for _, item := range table { + tx := SignedTransaction{} + err := json.Unmarshal([]byte(item.raw), &tx) + if err != nil { + t.Fatal(err) + } + + b, err := tx.Encode() + if err != nil { + t.Fatal(err) + } - if string(b) != expect { - t.Fatalf("expect: %s, got: %s", expect, string(b)) + if hex.EncodeToString(b) != item.expect { + t.Fatalf("expect %s, but got %s", item.expect, hex.EncodeToString(b)) + } } + } +func TestDecodeSignedTransaction(t *testing.T) { -func TestEncodeTransaction(t *testing.T) { - jsonStr := `{"UnsignedTransaction":{"From":"CFXTEST:TYPE.USER:AAR7X4R8MKRNW39GGS8RZ40J1ZNWH5MRRPUFPR2U76","Nonce":"0x1","GasPrice":"0x1","Gas":"0x1","Value":"0x1","StorageLimit":"0x1","EpochHeight":"0x1","ChainID":"0x1","To":null,"Data":"0x01"},"V":1,"R":"0xca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31","S":"0x36953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea"}` - tx := SignedTransaction{} - err := json.Unmarshal([]byte(jsonStr), &tx) - if err != nil { - t.Fatal(err) + table := []struct { + raw string + expect string + }{ + { + raw: `0xf84dc901010180010101010101a0ca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31a036953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea`, + expect: `{"UnsignedTransaction":{"From":null,"Nonce":"0x1","GasPrice":"0x1","Gas":"0x1","Value":"0x1","StorageLimit":"0x1","EpochHeight":"0x1","ChainID":"0x1","AccessList":null,"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":null,"To":null,"Data":"0x01"},"V":1,"R":"0xca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31","S":"0x36953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea"}`, + }, + { + raw: `0x63667801f868f8636464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef800101`, + expect: `{"UnsignedTransaction":{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":1,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"},"V":0,"R":"0x01","S":"0x01"}`, + }, + { + raw: `0x63667802f869f864646464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef800101`, + expect: `{"UnsignedTransaction":{"From":null,"Nonce":"0x64","GasPrice":null,"Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":"0x64","MaxFeePerGas":"0x64","Type":2,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"},"V":0,"R":"0x01","S":"0x01"}`, + }, } - b, err := tx.Encode() - if err != nil { - t.Fatal(err) - } + for i, item := range table { + // rawData := `0xf84dc901010180010101010101a0ca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31a036953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea` + tx := SignedTransaction{} + b := mustDecodeStringToBytes(t, item.raw) + err := tx.Decode(b, 0) + if err != nil { + t.Fatal(err) + } - expect := `f84dc901010180010101010101a0ca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31a036953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea` - if hex.EncodeToString(b) != expect { - t.Fatalf("expect %s, but got %s", expect, hex.EncodeToString(b)) - } -} + b, err = json.Marshal(tx) + if err != nil { + t.Fatal(err) + } -func mustDecodeStringToBytes(t *testing.T, s string) []byte { - b, e := hex.DecodeString(s[2:]) - if e != nil { - t.Fatal(e) + // expect := `{"UnsignedTransaction":{"From":null,"Nonce":"0x1","GasPrice":"0x1","Gas":"0x1","Value":"0x1","StorageLimit":"0x1","EpochHeight":"0x1","ChainID":"0x1","AccessList":null,"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":null,"To":null,"Data":"0x01"},"V":1,"R":"0xca43b3f84e4afefcc6946d2953a0391774bd3c692015f64e51895b4a93fcba31","S":"0x36953d461a84e15367a463d4f7624970ad4c3833013f23103f2ea90a202e4aea"}` + + if string(b) != item.expect { + t.Fatalf("item %d expect: %s, got: %s", i, item.expect, string(b)) + } } - return b + } -/* - "result": { - "hash": "0xbe47fb886dd24dba30cb25527b866b3139fb020ac344d5dc910b0140cce05478", - "nonce": "0x4d073", - "blockHash": "0xd530f560436892a034ccd3516de50a8745d7607b834d483d75097ad13e1bfb0a", - "transactionIndex": "0x0", - "from": "cfxtest:aaph8hphbv84fkn3bunm051aek68aua6wy0tg08xnd", - "to": "cfxtest:achs3nehae0j6ksvy1bhrffsh1rtfrw1f6w1kzv46t", - "value": "0x1", - "gasPrice": "0x3b9aca00", - "gas": "0xb316", - "contractCreated": null, - "data": "0xd0e30db0", - "storageLimit": "0x0", - "epochHeight": "0x6f26e7b", - "chainId": "0x1", - "status": "0x0", - "v": "0x1", - "r": "0x8a0a8568bab8a8cd0105e9caeb0fc0d5aa4a568cea123ce41a0299e9f18ebccf", - "s": "0x7831351ea915b82625f728239eef279aaecb74a90abd066cf85e2f5d3e3a5f40" - } -*/ -func TestTransactionHashShouldBeSignedTxHash(t *testing.T) { +func TestHashSignedTransaction(t *testing.T) { to := cfxaddress.MustNew("cfxtest:achs3nehae0j6ksvy1bhrffsh1rtfrw1f6w1kzv46t") utx := UnsignedTransaction{ UnsignedTransactionBase: UnsignedTransactionBase{ @@ -115,3 +127,216 @@ func TestTransactionHashShouldBeSignedTxHash(t *testing.T) { assert.NotEqual(t, "0xbe47fb886dd24dba30cb25527b866b3139fb020ac344d5dc910b0140cce05478", hexutil.Encode(utxHash)) assert.Equal(t, "0xbe47fb886dd24dba30cb25527b866b3139fb020ac344d5dc910b0140cce05478", hexutil.Encode(signedTxhash)) } + +func TestHashUnsignedTransaction(t *testing.T) { + + table := []struct { + tx string + rlpExpect string + hashExpect string + }{ + { + tx: `{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + rlpExpect: `e96464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64`, + hashExpect: `5487fa843420144fd78f19bb86e9da81040e50423ab3ec2818ad4b6c86fcecc2`, + }, + { + tx: `{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":1,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + rlpExpect: `63667801f8636464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef`, + hashExpect: `690d58e271b90254e7954147846d5de0f76f3649510bb58a5f26e4fef8d601ba`, + }, + { + tx: `{"From":null,"Nonce":"0x64","GasPrice":null,"Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":"0x64","MaxFeePerGas":"0x64","Type":2,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + rlpExpect: `63667802f864646464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef`, + hashExpect: `3da56dbe2b76c41135c2429f3035cd79b1abb68902cf588075c30d4912e71cf3`, + }, + } + + for _, item := range table { + tx := UnsignedTransaction{} + err := json.Unmarshal([]byte(item.tx), &tx) + if err != nil { + t.Fatal(err) + } + + rlp, err := tx.Encode() + if err != nil { + t.Fatal(err) + } + + hash, err := tx.Hash() + if err != nil { + t.Fatal(err) + } + + if hex.EncodeToString(rlp) != item.rlpExpect { + t.Fatalf("expect %s, but got %s", item.rlpExpect, hex.EncodeToString(rlp)) + } + + if hex.EncodeToString(hash) != item.hashExpect { + t.Fatalf("expect %s, but got %s", item.hashExpect, hex.EncodeToString(hash)) + } + } +} + +func TestDecodeUnsignedTransaction(t *testing.T) { + table := []struct { + raw string + expect string + }{ + { + raw: `0xe96464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64`, + expect: `{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":null,"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":null,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + }, + { + raw: `0x63667801f8636464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef`, + expect: `{"From":null,"Nonce":"0x64","GasPrice":"0x64","Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":null,"MaxFeePerGas":null,"Type":1,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + }, + { + raw: `0x63667802f864646464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef`, + expect: `{"From":null,"Nonce":"0x64","GasPrice":null,"Gas":"0x64","Value":"0x64","StorageLimit":"0x64","EpochHeight":"0x64","ChainID":"0x64","AccessList":[{"address":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","storageKeys":["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]}],"MaxPriorityFeePerGas":"0x64","MaxFeePerGas":"0x64","Type":2,"To":"net0:aapztdhx26tm0wgtueghvrj1nzsk651yjejbamakm5","Data":"0x48656c6c6f2c20576f726c64"}`, + }, + } + + for i, item := range table { + tx := UnsignedTransaction{} + b := mustDecodeStringToBytes(t, item.raw) + err := tx.Decode(b, 0) + if err != nil { + t.Fatal(err) + } + + b, err = json.Marshal(tx) + if err != nil { + t.Fatal(err) + } + + if string(b) != item.expect { + t.Fatalf("item %d expect: %s, got: %s", i, item.expect, string(b)) + } + } +} + +func mustDecodeStringToBytes(t *testing.T, s string) []byte { + b, e := hex.DecodeString(s[2:]) + if e != nil { + t.Fatal(e) + } + return b +} + +func TestTemp(t *testing.T) { + accessList := AccessList([]AccessTuple{ + { + Address: cfxaddress.MustNew("0x19578CF3c71eaB48cF810c78B5175d5c9E6Ef441"), + StorageKeys: []common.Hash{ + common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"), + }, + }, + }) + to := cfxaddress.MustNew("0x19578CF3c71eaB48cF810c78B5175d5c9E6Ef441") + tx := SignedTransaction{ + UnsignedTransaction: UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + Type: TRANSACTION_TYPE_2930.Ptr(), + Nonce: NewBigInt(100), + GasPrice: NewBigInt(100), + Gas: NewBigInt(100), + Value: NewBigInt(100), + StorageLimit: NewUint64(100), + EpochHeight: NewUint64(100), + ChainID: NewUint(100), + AccessList: accessList, + }, + To: &to, + Data: []byte("Hello, World"), + }, + R: NewBytes([]byte{1}), + S: NewBytes([]byte{1}), + V: byte(0), + } + j, _ := json.Marshal(tx) + fmt.Println(string(j)) + + tx = SignedTransaction{ + UnsignedTransaction: UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + Type: TRANSACTION_TYPE_1559.Ptr(), + Nonce: NewBigInt(100), + MaxPriorityFeePerGas: NewBigInt(100), + MaxFeePerGas: NewBigInt(100), + Gas: NewBigInt(100), + Value: NewBigInt(100), + StorageLimit: NewUint64(100), + EpochHeight: NewUint64(100), + ChainID: NewUint(100), + AccessList: accessList, + }, + To: &to, + Data: []byte("Hello, World"), + }, + R: NewBytes([]byte{1}), + S: NewBytes([]byte{1}), + V: byte(0), + } + j, _ = json.Marshal(tx) + fmt.Println(string(j)) +} + +func TestTemp2(t *testing.T) { + accessList := AccessList([]AccessTuple{ + { + Address: cfxaddress.MustNew("0x19578CF3c71eaB48cF810c78B5175d5c9E6Ef441"), + StorageKeys: []common.Hash{ + common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"), + }, + }, + }) + to := cfxaddress.MustNew("0x19578CF3c71eaB48cF810c78B5175d5c9E6Ef441") + tx := SignedTransaction{ + UnsignedTransaction: UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + Type: TRANSACTION_TYPE_2930.Ptr(), + Nonce: NewBigInt(100), + GasPrice: NewBigInt(100), + Gas: NewBigInt(100), + Value: NewBigInt(100), + StorageLimit: NewUint64(100), + EpochHeight: NewUint64(100), + ChainID: NewUint(100), + AccessList: accessList, + }, + To: &to, + Data: []byte("Hello, World"), + }, + R: NewBytes([]byte{1}), + S: NewBytes([]byte{1}), + V: byte(0), + } + j, _ := json.Marshal(tx.UnsignedTransaction) + fmt.Println(string(j)) + + tx = SignedTransaction{ + UnsignedTransaction: UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + Type: TRANSACTION_TYPE_1559.Ptr(), + Nonce: NewBigInt(100), + MaxPriorityFeePerGas: NewBigInt(100), + MaxFeePerGas: NewBigInt(100), + Gas: NewBigInt(100), + Value: NewBigInt(100), + StorageLimit: NewUint64(100), + EpochHeight: NewUint64(100), + ChainID: NewUint(100), + AccessList: accessList, + }, + To: &to, + Data: []byte("Hello, World"), + }, + R: NewBytes([]byte{1}), + S: NewBytes([]byte{1}), + V: byte(0), + } + j, _ = json.Marshal(tx.UnsignedTransaction) + fmt.Println(string(j)) +} diff --git a/types/transaction_test.go b/types/transaction_test.go index 6808ac1..7b700c5 100644 --- a/types/transaction_test.go +++ b/types/transaction_test.go @@ -9,8 +9,8 @@ import ( ) func TestRLPMarshalTransaction(t *testing.T) { - txJson1 := `{"hash":"0x4016c5b1675182700ef67b9df90c13ddf2e774b12385af63ba43576039b13f8a","nonce":"0x0","blockHash":"0xce70d3387731e0d09605c37c322070ba30223b327b8790b15086847241cb857d","transactionIndex":"0x0","from":"cfx:aam9edem02j9tmzavu81y4g0ygy06cyeg2vx3zwe8y","to":"cfx:acb59fk6vryh8dj5vyvehj9apzhpd72rdpwsc651kz","value":"0x0","gasPrice":"0x1","gas":"0x4c4b40","contractCreated":null,"data":"0xfebe49090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162788589c8e386863f217faef78840919fb2854","storageLimit":"0x40","epochHeight":"0x5","chainId":"0x405","status":"0x0","v":"0x0","r":"0x7c15d3f0e517a66ad96a79cfd24b00439de725d9cbbcb8a1d0107cd5c16c8751","s":"0x27a0faab73d4ab512fa97d9e52ef3b3d2bea2a39d58c8d3d65dac59abbe6fee5"}` - txJson2 := `{"hash":"0xdeffba5291f0d669ca63514f2f9c95fd313fcf6c2855ec929076225890113b59","nonce":"0x0","blockHash":"0xa751293043bba5353b0fca393820927ec9bc30a27916a085c92ba4e79f8152f7","transactionIndex":"0x0","from":"cfxtest:aaph8hphbv84fkn3bunm051aek68aua6wy0tg08xnd","to":null,"value":"0x0","gasPrice":"0x3b9aca00","gas":"0x6ed68","contractCreated":"cfxtest:aca514ancmbdu9u349u4m7d0u4jjdv83py3muarnv1","data":"0x608060405234801561001057600080fd5b50610544806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328f7fd781461003b578063cf7bb3091461006b575b600080fd5b61005560048036038101906100509190610308565b61009b565b6040516100629190610432565b60405180910390f35b610085600480360381019061008091906102c3565b610115565b6040516100929190610432565b60405180910390f35b600084846040516100ad9291906103de565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f14cb751d0950ff2788201931c45f715f7472443bc197311d9e3a7a0ba566b7e68787878760405161010194939291906103f7565b60405180910390a360019050949350505050565b600080600090505b838390508110156102225783838281811061013457fe5b905060200281019061014691906104a4565b8060000190610155919061044d565b6040516101639291906103de565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f14cb751d0950ff2788201931c45f715f7472443bc197311d9e3a7a0ba566b7e68686858181106101af57fe5b90506020028101906101c191906104a4565b80600001906101d0919061044d565b8888878181106101dc57fe5b90506020028101906101ee91906104a4565b80602001906101fd919061044d565b60405161020d94939291906103f7565b60405180910390a3808060010191505061011d565b5082829050905092915050565b60008083601f84011261024157600080fd5b8235905067ffffffffffffffff81111561025a57600080fd5b60208301915083602082028301111561027257600080fd5b9250929050565b60008083601f84011261028b57600080fd5b8235905067ffffffffffffffff8111156102a457600080fd5b6020830191508360018202830111156102bc57600080fd5b9250929050565b600080602083850312156102d657600080fd5b600083013567ffffffffffffffff8111156102f057600080fd5b6102fc8582860161022f565b92509250509250929050565b6000806000806040858703121561031e57600080fd5b600085013567ffffffffffffffff81111561033857600080fd5b61034487828801610279565b9450945050602085013567ffffffffffffffff81111561036357600080fd5b61036f87828801610279565b925092505092959194509250565b600061038983856104c8565b93506103968385846104ee565b61039f836104fd565b840190509392505050565b60006103b683856104d9565b93506103c38385846104ee565b82840190509392505050565b6103d8816104e4565b82525050565b60006103eb8284866103aa565b91508190509392505050565b6000604082019050818103600083015261041281868861037d565b9050818103602083015261042781848661037d565b905095945050505050565b600060208201905061044760008301846103cf565b92915050565b6000808335600160200384360303811261046657600080fd5b80840192508235915067ffffffffffffffff82111561048457600080fd5b60208301925060018202360383131561049c57600080fd5b509250929050565b6000823560016040038336030381126104bc57600080fd5b80830191505092915050565b600082825260208201905092915050565b600081905092915050565b6000819050919050565b82818337600083830152505050565b6000601f19601f830116905091905056fea26469706673582212200aab70e63ece6dc222afcf381fec642c6d414adf33cf0ed6da53680bd904f5ac64736f6c63430007040033","storageLimit":"0x466","epochHeight":"0x43e","chainId":"0x1","status":"0x0","v":"0x0","r":"0x4b0551c1db7ec8ea089f15e679cf0ec3ba15c638b8b3f71ce8df5e35f29f6c9f","s":"0x7c7f2130c26c31f744092a58ea3daac826695a9aef45ec6fad38b9a0c2882a23"}` + txJson1 := `{"type":"0x0","hash":"0x4016c5b1675182700ef67b9df90c13ddf2e774b12385af63ba43576039b13f8a","nonce":"0x0","blockHash":"0xce70d3387731e0d09605c37c322070ba30223b327b8790b15086847241cb857d","transactionIndex":"0x0","from":"cfx:aam9edem02j9tmzavu81y4g0ygy06cyeg2vx3zwe8y","to":"cfx:acb59fk6vryh8dj5vyvehj9apzhpd72rdpwsc651kz","value":"0x0","gasPrice":"0x1","gas":"0x4c4b40","contractCreated":null,"data":"0xfebe49090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162788589c8e386863f217faef78840919fb2854","storageLimit":"0x40","epochHeight":"0x5","chainId":"0x405","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x7c15d3f0e517a66ad96a79cfd24b00439de725d9cbbcb8a1d0107cd5c16c8751","s":"0x27a0faab73d4ab512fa97d9e52ef3b3d2bea2a39d58c8d3d65dac59abbe6fee5","yParity":"0x0"}` + txJson2 := `{"type":"0x0","hash":"0xdeffba5291f0d669ca63514f2f9c95fd313fcf6c2855ec929076225890113b59","nonce":"0x0","blockHash":"0xa751293043bba5353b0fca393820927ec9bc30a27916a085c92ba4e79f8152f7","transactionIndex":"0x0","from":"cfxtest:aaph8hphbv84fkn3bunm051aek68aua6wy0tg08xnd","to":null,"value":"0x0","gasPrice":"0x3b9aca00","gas":"0x6ed68","contractCreated":"cfxtest:aca514ancmbdu9u349u4m7d0u4jjdv83py3muarnv1","data":"0x608060405234801561001057600080fd5b50610544806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328f7fd781461003b578063cf7bb3091461006b575b600080fd5b61005560048036038101906100509190610308565b61009b565b6040516100629190610432565b60405180910390f35b610085600480360381019061008091906102c3565b610115565b6040516100929190610432565b60405180910390f35b600084846040516100ad9291906103de565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f14cb751d0950ff2788201931c45f715f7472443bc197311d9e3a7a0ba566b7e68787878760405161010194939291906103f7565b60405180910390a360019050949350505050565b600080600090505b838390508110156102225783838281811061013457fe5b905060200281019061014691906104a4565b8060000190610155919061044d565b6040516101639291906103de565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f14cb751d0950ff2788201931c45f715f7472443bc197311d9e3a7a0ba566b7e68686858181106101af57fe5b90506020028101906101c191906104a4565b80600001906101d0919061044d565b8888878181106101dc57fe5b90506020028101906101ee91906104a4565b80602001906101fd919061044d565b60405161020d94939291906103f7565b60405180910390a3808060010191505061011d565b5082829050905092915050565b60008083601f84011261024157600080fd5b8235905067ffffffffffffffff81111561025a57600080fd5b60208301915083602082028301111561027257600080fd5b9250929050565b60008083601f84011261028b57600080fd5b8235905067ffffffffffffffff8111156102a457600080fd5b6020830191508360018202830111156102bc57600080fd5b9250929050565b600080602083850312156102d657600080fd5b600083013567ffffffffffffffff8111156102f057600080fd5b6102fc8582860161022f565b92509250509250929050565b6000806000806040858703121561031e57600080fd5b600085013567ffffffffffffffff81111561033857600080fd5b61034487828801610279565b9450945050602085013567ffffffffffffffff81111561036357600080fd5b61036f87828801610279565b925092505092959194509250565b600061038983856104c8565b93506103968385846104ee565b61039f836104fd565b840190509392505050565b60006103b683856104d9565b93506103c38385846104ee565b82840190509392505050565b6103d8816104e4565b82525050565b60006103eb8284866103aa565b91508190509392505050565b6000604082019050818103600083015261041281868861037d565b9050818103602083015261042781848661037d565b905095945050505050565b600060208201905061044760008301846103cf565b92915050565b6000808335600160200384360303811261046657600080fd5b80840192508235915067ffffffffffffffff82111561048457600080fd5b60208301925060018202360383131561049c57600080fd5b509250929050565b6000823560016040038336030381126104bc57600080fd5b80830191505092915050565b600082825260208201905092915050565b600081905092915050565b6000819050919050565b82818337600083830152505050565b6000601f19601f830116905091905056fea26469706673582212200aab70e63ece6dc222afcf381fec642c6d414adf33cf0ed6da53680bd904f5ac64736f6c63430007040033","storageLimit":"0x466","epochHeight":"0x43e","chainId":"0x1","status":"0x0","accessList":[],"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","v":"0x0","r":"0x4b0551c1db7ec8ea089f15e679cf0ec3ba15c638b8b3f71ce8df5e35f29f6c9f","s":"0x7c7f2130c26c31f744092a58ea3daac826695a9aef45ec6fad38b9a0c2882a23","yParity":"0x0"}` for _, txJson := range []string{txJson2, txJson1} { var tx Transaction @@ -39,9 +39,9 @@ func TestRLPMarshalTransaction(t *testing.T) { } func TestRLPMarshalTransactionReceipt(t *testing.T) { - trJson1 := `{"transactionHash":"0xa2c678cc97e07ce060b71f87ac65e68d482abf8e1a93b7d1bc425504c4584ca7","index":"0x1","blockHash":"0x935bc7ebab4e6256ade6327682de8bee6b15dcee5c83f7772ae6a945510fe940","epochNumber":"0xf7cf0d","from":"cfx:aaspca00u76ew2eharzsy355svm3t6yw4pxsyu7vka","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","gasUsed":"0x22144","gasFee":"0xd4fe90","contractCreated":null,"logs":[{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0x2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d","0x00000000000000000000000080ae6a88ce3351e9f729e8199f2871ba786ad7c5","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c800000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c80000","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0x68051bc50b1ef1654bf1e6204b5f8fa9badcd038e00fa5b43f21f898fc2728ca","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c80000","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acf2rcsh8payyxpg6xj7b0ztswwh81ute60tsw35j7","topics":["0x06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc82614677987","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000019ceb8990635656bbf0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acf2rcsh8payyxpg6xj7b0ztswwh81ute60tsw35j7","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000019ceb8990635656bbf","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acgzjyj25esae9eanvmw827f2afcbnxm3jr3784tyu","topics":["0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1"],"data":"0x000000000000000000000000000000000000000000003a4a9c46eba30a4fb89e00000000000000000000000000000000000000000000854b7ce25c8407e77655","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null},{"address":"cfx:acgzjyj25esae9eanvmw827f2afcbnxm3jr3784tyu","topics":["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822","0x00000000000000000000000080ae6a88ce3351e9f729e8199f2871ba786ad7c5","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b16c9e8eeb7c80000000000000000000000000000000000000000000000000019ceb8990635656bbf0000000000000000000000000000000000000000000000000000000000000000","blockHash":null,"epochNumber":null,"transactionHash":null,"transactionIndex":null,"logIndex":null,"transactionLogIndex":null}],"logsBloom":"0x0020000000000000000000008000000000000808000000000000000000000000804000000000200040080000009000000000000000000000000000000008000000000000000010000000000a00000020000000000000000000000000000000000000000002004000000000000000080004000040000000000000001000000000000008000020000000001100000002000000000000000018000000400000000000000000012000000000000000000000000000000000000000000000000000000000000200000010000004000000000000000000000000100000a000000020000000000000000400000000000000000000000000100000000000000000040000","stateRoot":"0x2b35e444ba6118f85447efc1c504b3526229c99451fd172ae35a49fe5d7127bd","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":true,"storageCoveredBySponsor":true,"storageCollateralized":"0x0","storageReleased":[]}` - trJson2 := `{"transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","index":"0x1","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","from":"cfx:aarh9m8vs8ecrhmw76efb61a5w9yjwyyapz8yj2evb","to":"cfx:acbcnsptvcgggjwb7u8gbprffacx7657k67j8taaxg","gasUsed":"0x13b3a","gasFee":"0x13b3a","contractCreated":null,"logs":[{"address":"cfx:acc8ya1f2a2bfphxg5ax7a8h29k47d5xsebxfj24nd","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000008225b98f888c632241ec3c60b1a528053ef37d4f","0x0000000000000000000000001a7fabd17788269d52ef0850f2e0dcbf444a9403"],"data":"0x00000000000000000000000000000000000000000000000016b276f7e4180350","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","transactionIndex":"0x1","logIndex":"0x0","transactionLogIndex":"0x0"},{"address":"cfx:acbcnsptvcgggjwb7u8gbprffacx7657k67j8taaxg","topics":["0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15","0x0000000000000000000000001a7fabd17788269d52ef0850f2e0dcbf444a9403","0x0000000000000000000000000000000000000000000000000000000000000001"],"data":"0x0000000000000000000000000000000000000000000000000000000000000000","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","transactionIndex":"0x1","logIndex":"0x1","transactionLogIndex":"0x1"}],"logsBloom":"0x00000000000000400000000000000000000000000400000000000000000010000000000000800000000000000000000008000000000000000000000000040000000000000000000000000008000000000000000000040000000000000000000000000000000000200000000000000000000000000000000000000010000100000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000010001000000000000000000000000000000000002000000000000000000040000000000000000000000000000000040000000000000000400010000000000000000000000400000200000000000000000","stateRoot":"0x46347c46f62b53144431cfd6d1e5af9bdf2d2f0ed13b4e68f96cba6cf3839ec0","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":true,"storageCoveredBySponsor":true,"storageCollateralized":"0x0","storageReleased":[]}` - trJson3 := `{"transactionHash":"0xdeffba5291f0d669ca63514f2f9c95fd313fcf6c2855ec929076225890113b59","index":"0x0","blockHash":"0xa751293043bba5353b0fca393820927ec9bc30a27916a085c92ba4e79f8152f7","epochNumber":"0x441","from":"cfxtest:aaph8hphbv84fkn3bunm051aek68aua6wy0tg08xnd","to":null,"gasUsed":"0x64c30","gasFee":"0x1775ddcfde000","contractCreated":"cfxtest:aca514ancmbdu9u349u4m7d0u4jjdv83py3muarnv1","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","stateRoot":"0x3f57ef68b851da591aac50f1cbdf369d87a2e3b66d7679a00678fb5fcd02653a","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":false,"storageCoveredBySponsor":false,"storageCollateralized":"0x400","storageReleased":[]}` + trJson1 := `{"type":"0x0","transactionHash":"0xa2c678cc97e07ce060b71f87ac65e68d482abf8e1a93b7d1bc425504c4584ca7","index":"0x1","blockHash":"0x935bc7ebab4e6256ade6327682de8bee6b15dcee5c83f7772ae6a945510fe940","epochNumber":"0xf7cf0d","from":"cfx:aaspca00u76ew2eharzsy355svm3t6yw4pxsyu7vka","to":"cfx:acam64yj323zd4t1fhybxh3jsg7hu4012yz9kakxs9","gasUsed":"0x22144","gasFee":"0xd4fe90","effectiveGasPrice":"0x0","contractCreated":null,"logs":[{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0x2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d","0x00000000000000000000000080ae6a88ce3351e9f729e8199f2871ba786ad7c5","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c800000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c80000"},{"address":"cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx","topics":["0x68051bc50b1ef1654bf1e6204b5f8fa9badcd038e00fa5b43f21f898fc2728ca","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"data":"0x00000000000000000000000000000000000000000000003b16c9e8eeb7c80000"},{"address":"cfx:acf2rcsh8payyxpg6xj7b0ztswwh81ute60tsw35j7","topics":["0x06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc82614677987","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000019ceb8990635656bbf0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},{"address":"cfx:acf2rcsh8payyxpg6xj7b0ztswwh81ute60tsw35j7","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000008d545118d91c027c805c552f63a5c00a20ae6aca","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000019ceb8990635656bbf"},{"address":"cfx:acgzjyj25esae9eanvmw827f2afcbnxm3jr3784tyu","topics":["0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1"],"data":"0x000000000000000000000000000000000000000000003a4a9c46eba30a4fb89e00000000000000000000000000000000000000000000854b7ce25c8407e77655"},{"address":"cfx:acgzjyj25esae9eanvmw827f2afcbnxm3jr3784tyu","topics":["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822","0x00000000000000000000000080ae6a88ce3351e9f729e8199f2871ba786ad7c5","0x0000000000000000000000001cc102d68778496087036aea677b745597f292d3"],"data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b16c9e8eeb7c80000000000000000000000000000000000000000000000000019ceb8990635656bbf0000000000000000000000000000000000000000000000000000000000000000"}],"logsBloom":"0x0020000000000000000000008000000000000808000000000000000000000000804000000000200040080000009000000000000000000000000000000008000000000000000010000000000a00000020000000000000000000000000000000000000000002004000000000000000080004000040000000000000001000000000000008000020000000001100000002000000000000000018000000400000000000000000012000000000000000000000000000000000000000000000000000000000000200000010000004000000000000000000000000100000a000000020000000000000000400000000000000000000000000100000000000000000040000","stateRoot":"0x2b35e444ba6118f85447efc1c504b3526229c99451fd172ae35a49fe5d7127bd","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":true,"storageCoveredBySponsor":true,"storageCollateralized":"0x0","storageReleased":[],"burntGasFee":"0x0"}` + trJson2 := `{"type":"0x0","transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","index":"0x1","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","from":"cfx:aarh9m8vs8ecrhmw76efb61a5w9yjwyyapz8yj2evb","to":"cfx:acbcnsptvcgggjwb7u8gbprffacx7657k67j8taaxg","gasUsed":"0x13b3a","gasFee":"0x13b3a","effectiveGasPrice":"0x0","contractCreated":null,"logs":[{"address":"cfx:acc8ya1f2a2bfphxg5ax7a8h29k47d5xsebxfj24nd","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000008225b98f888c632241ec3c60b1a528053ef37d4f","0x0000000000000000000000001a7fabd17788269d52ef0850f2e0dcbf444a9403"],"data":"0x00000000000000000000000000000000000000000000000016b276f7e4180350","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","transactionIndex":"0x1","logIndex":"0x0","transactionLogIndex":"0x0"},{"address":"cfx:acbcnsptvcgggjwb7u8gbprffacx7657k67j8taaxg","topics":["0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15","0x0000000000000000000000001a7fabd17788269d52ef0850f2e0dcbf444a9403","0x0000000000000000000000000000000000000000000000000000000000000001"],"data":"0x0000000000000000000000000000000000000000000000000000000000000000","blockHash":"0x25fd857127dbef9e9a4f851ade9b11ac1cb22967266d915fe00f61ec1e356f54","epochNumber":"0xfce4df","transactionHash":"0xa45f5101687f1cc11ea8ea56eab670cff670c55c84c7feb06ed33b7840346c60","transactionIndex":"0x1","logIndex":"0x1","transactionLogIndex":"0x1"}],"logsBloom":"0x00000000000000400000000000000000000000000400000000000000000010000000000000800000000000000000000008000000000000000000000000040000000000000000000000000008000000000000000000040000000000000000000000000000000000200000000000000000000000000000000000000010000100000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000010001000000000000000000000000000000000002000000000000000000040000000000000000000000000000000040000000000000000400010000000000000000000000400000200000000000000000","stateRoot":"0x46347c46f62b53144431cfd6d1e5af9bdf2d2f0ed13b4e68f96cba6cf3839ec0","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":true,"storageCoveredBySponsor":true,"storageCollateralized":"0x0","storageReleased":[],"burntGasFee":"0x0"}` + trJson3 := `{"type":"0x0","transactionHash":"0xdeffba5291f0d669ca63514f2f9c95fd313fcf6c2855ec929076225890113b59","index":"0x0","blockHash":"0xa751293043bba5353b0fca393820927ec9bc30a27916a085c92ba4e79f8152f7","epochNumber":"0x441","from":"cfxtest:aaph8hphbv84fkn3bunm051aek68aua6wy0tg08xnd","to":null,"gasUsed":"0x64c30","gasFee":"0x1775ddcfde000","effectiveGasPrice":"0x0","contractCreated":"cfxtest:aca514ancmbdu9u349u4m7d0u4jjdv83py3muarnv1","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","stateRoot":"0x3f57ef68b851da591aac50f1cbdf369d87a2e3b66d7679a00678fb5fcd02653a","outcomeStatus":"0x0","txExecErrorMsg":null,"gasCoveredBySponsor":false,"storageCoveredBySponsor":false,"storageCollateralized":"0x400","storageReleased":[],"burntGasFee":"0x0"}` for _, trJson := range []string{trJson3, trJson2, trJson1} { var tr TransactionReceipt diff --git a/types/transaction_unsigned.go b/types/transaction_unsigned.go index a5daec4..7270a24 100644 --- a/types/transaction_unsigned.go +++ b/types/transaction_unsigned.go @@ -6,12 +6,31 @@ package types import ( "math/big" + "slices" "github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + etypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" + "github.com/pkg/errors" +) + +type TransactionType uint + +func (t TransactionType) Ptr() *TransactionType { + return &t +} + +const ( + TRANSACTION_TYPE_LEGACY TransactionType = iota + TRANSACTION_TYPE_2930 + TRANSACTION_TYPE_1559 +) + +var ( + TRANSACTION_TYPE_PREFIX = []byte("cfx") ) // UnsignedTransactionBase represents a transaction without To, Data and signature @@ -24,8 +43,34 @@ type UnsignedTransactionBase struct { StorageLimit *hexutil.Uint64 EpochHeight *hexutil.Uint64 ChainID *hexutil.Uint + + AccessList AccessList + MaxPriorityFeePerGas *hexutil.Big + MaxFeePerGas *hexutil.Big + + Type *TransactionType } +// // get the txtype according to feeData +// // - if if has maxFeePerGas or maxPriorityFeePerGas, then set txtype to 2 +// // - else if contains accesslist, set txtype to 1 +// // - else set txtype to 0 +// func (utx UnsignedTransactionBase) GetType() TransactionType { +// if utx.Type != nil { +// return *utx.Type +// } + +// if utx.MaxPriorityFeePerGas != nil || utx.MaxFeePerGas != nil { +// return TRANSACTION_TYPE_LEGACY +// } + +// if utx.AccessList != nil { +// return TRANSACTION_TYPE_2930 +// } + +// return TRANSACTION_TYPE_LEGACY +// } + // UnsignedTransaction represents a transaction without signature, // it is the transaction information for sending transaction. type UnsignedTransaction struct { @@ -34,8 +79,20 @@ type UnsignedTransaction struct { Data hexutil.Bytes } -// unsignedTransactionForRlp is a intermediate struct for encoding rlp data -type unsignedTransactionForRlp struct { +// unsignedLegacyTransactionForRlp is a intermediate struct for encoding rlp data +type unsignedLegacyTransactionForRlp struct { + Nonce *big.Int `rlp:"nil"` + GasPrice *big.Int `rlp:"nil"` + Gas *big.Int `rlp:"nil"` + To *common.Address `rlp:"nil"` + Value *big.Int `rlp:"nil"` + StorageLimit *hexutil.Uint64 `rlp:"nil"` + EpochHeight *hexutil.Uint64 `rlp:"nil"` + ChainID *hexutil.Uint `rlp:"nil"` + Data []byte +} + +type unsigned2930TransactionForRlp struct { Nonce *big.Int `rlp:"nil"` GasPrice *big.Int `rlp:"nil"` Gas *big.Int `rlp:"nil"` @@ -45,6 +102,21 @@ type unsignedTransactionForRlp struct { EpochHeight *hexutil.Uint64 `rlp:"nil"` ChainID *hexutil.Uint `rlp:"nil"` Data []byte + AccessList etypes.AccessList +} + +type unsigned1559TransactionForRlp struct { + Nonce *big.Int `rlp:"nil"` + MaxPriorityFeePerGas *big.Int `rlp:"nil"` + MaxFeePerGas *big.Int `rlp:"nil"` + Gas *big.Int `rlp:"nil"` + To *common.Address `rlp:"nil"` + Value *big.Int `rlp:"nil"` + StorageLimit *hexutil.Uint64 `rlp:"nil"` + EpochHeight *hexutil.Uint64 `rlp:"nil"` + ChainID *hexutil.Uint `rlp:"nil"` + Data []byte + AccessList etypes.AccessList } // DefaultGas is the default gas in a transaction to transfer amount without any data. @@ -52,13 +124,13 @@ type unsignedTransactionForRlp struct { var defaultGas *hexutil.Big = NewBigInt(21000) // DefaultGasPrice is the default gas price. -var defaultGasPrice *hexutil.Big = NewBigInt(10000000000) // 10G drip +// var defaultGasPrice *hexutil.Big = NewBigInt(10000000000) // 10G drip // ApplyDefault applys default value for these fields if they are empty func (tx *UnsignedTransaction) ApplyDefault() { - if tx.GasPrice == nil { - tx.GasPrice = defaultGasPrice - } + // if tx.GasPrice == nil { + // tx.GasPrice = defaultGasPrice + // } if tx.Gas == nil { tx.Gas = defaultGas @@ -79,14 +151,30 @@ func (tx *UnsignedTransaction) Hash() ([]byte, error) { return crypto.Keccak256(encoded), nil } -//Encode encodes tx and returns its RLP encoded data +// Encode encodes tx and returns its RLP encoded data func (tx *UnsignedTransaction) Encode() ([]byte, error) { - data := *tx.toStructForRlp() - encoded, err := rlp.EncodeToBytes(data) + _tx := *tx + if tx.Type == nil { + _tx.Type = TRANSACTION_TYPE_LEGACY.Ptr() + } + + data, err := tx.toStructForRlp() if err != nil { return nil, err } - return encoded, nil + bodyRlp, err := rlp.EncodeToBytes(data) + if err != nil { + return nil, err + } + + if *_tx.Type == TRANSACTION_TYPE_LEGACY { + return bodyRlp, nil + } else { + data := append([]byte{}, TRANSACTION_TYPE_PREFIX...) + data = append(data, byte(*_tx.Type)) + data = append(data, bodyRlp...) + return data, nil + } } // EncodeWithSignature encodes tx with signature and return its RLP encoded data @@ -101,63 +189,202 @@ func (tx *UnsignedTransaction) EncodeWithSignature(v byte, r, s []byte) ([]byte, // Decode decodes RLP encoded data to tx func (tx *UnsignedTransaction) Decode(data []byte, networkID uint32) error { - utxForRlp := new(unsignedTransactionForRlp) - err := rlp.DecodeBytes(data, utxForRlp) - if err != nil { - return err + if !slices.Equal(data[:3], TRANSACTION_TYPE_PREFIX) { + utxForRlp := new(unsignedLegacyTransactionForRlp) + err := rlp.DecodeBytes(data, utxForRlp) + if err != nil { + return err + } + + *tx = *utxForRlp.toUnsignedTransaction(networkID) + return nil } + txType := TransactionType(data[3]) + switch txType { + case TRANSACTION_TYPE_2930: + txForRlp := new(unsigned2930TransactionForRlp) + err := rlp.DecodeBytes(data[4:], txForRlp) + if err != nil { + return err + } + + _tx := txForRlp.toUnsignedTransaction(networkID) + if err != nil { + return err + } + *tx = *_tx + return nil + + case TRANSACTION_TYPE_1559: + txForRlp := new(unsigned1559TransactionForRlp) + err := rlp.DecodeBytes(data[4:], txForRlp) + if err != nil { + return err + } - *tx = *utxForRlp.toUnsignedTransaction(networkID) - return nil + _tx := txForRlp.toUnsignedTransaction(networkID) + if err != nil { + return err + } + *tx = *_tx + return nil + + default: + return errors.Errorf("unknown transaction type %d", txType) + } } -func (tx *UnsignedTransaction) toStructForRlp() *unsignedTransactionForRlp { +func (tx *UnsignedTransaction) toStructForRlp() (interface{}, error) { + txType := tx.Type + if txType == nil { + txType = TRANSACTION_TYPE_LEGACY.Ptr() + } + var to *common.Address if tx.To != nil { addr := tx.To.MustGetCommonAddress() to = &addr } - return &unsignedTransactionForRlp{ - Nonce: tx.Nonce.ToInt(), - GasPrice: tx.GasPrice.ToInt(), - Gas: tx.Gas.ToInt(), - To: to, - Value: tx.Value.ToInt(), - StorageLimit: tx.StorageLimit, - EpochHeight: tx.EpochHeight, - ChainID: tx.ChainID, - Data: tx.Data, + switch *txType { + case TRANSACTION_TYPE_LEGACY: + return unsignedLegacyTransactionForRlp{ + Nonce: tx.Nonce.ToInt(), + GasPrice: tx.GasPrice.ToInt(), + Gas: tx.Gas.ToInt(), + To: to, + Value: tx.Value.ToInt(), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + Data: tx.Data, + }, nil + case TRANSACTION_TYPE_2930: + return unsigned2930TransactionForRlp{ + Nonce: tx.Nonce.ToInt(), + GasPrice: tx.GasPrice.ToInt(), + Gas: tx.Gas.ToInt(), + To: to, + Value: tx.Value.ToInt(), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + Data: tx.Data, + AccessList: *tx.AccessList.ToEthType(), + }, nil + case TRANSACTION_TYPE_1559: + return unsigned1559TransactionForRlp{ + Nonce: tx.Nonce.ToInt(), + MaxPriorityFeePerGas: tx.MaxFeePerGas.ToInt(), + MaxFeePerGas: tx.MaxFeePerGas.ToInt(), + Gas: tx.Gas.ToInt(), + To: to, + Value: tx.Value.ToInt(), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + Data: tx.Data, + AccessList: *tx.AccessList.ToEthType(), + }, nil + default: + return nil, errors.New("unkown transaction type") + } +} + +func (tx *unsignedLegacyTransactionForRlp) toUnsignedTransaction(networkID uint32) *UnsignedTransaction { + var to *cfxaddress.Address + if tx.To != nil { + _to := cfxaddress.MustNewFromCommon(*tx.To, networkID) + to = &_to + } + + return &UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + From: nil, + Nonce: (*hexutil.Big)(tx.Nonce), + GasPrice: (*hexutil.Big)(tx.GasPrice), + Gas: (*hexutil.Big)(tx.Gas), + Value: (*hexutil.Big)(tx.Value), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + }, + To: to, + Data: tx.Data, } } -func (tx *unsignedTransactionForRlp) toUnsignedTransaction(networkID uint32) *UnsignedTransaction { +func (tx *unsigned2930TransactionForRlp) toUnsignedTransaction(networkID uint32) *UnsignedTransaction { var to *cfxaddress.Address if tx.To != nil { _to := cfxaddress.MustNewFromCommon(*tx.To, networkID) to = &_to } - gasPrice := hexutil.Big(*tx.GasPrice) - value := hexutil.Big(*tx.Value) - storageLimit := tx.StorageLimit - epochHeight := tx.EpochHeight + var accessList AccessList + accessList.FromEthType(&tx.AccessList, networkID) - nonce := hexutil.Big(*tx.Nonce) - gas := hexutil.Big(*tx.Gas) - chainid := tx.ChainID return &UnsignedTransaction{ UnsignedTransactionBase: UnsignedTransactionBase{ From: nil, - Nonce: &nonce, - GasPrice: &gasPrice, - Gas: &gas, - Value: &value, - StorageLimit: storageLimit, - EpochHeight: epochHeight, - ChainID: chainid, + Nonce: (*hexutil.Big)(tx.Nonce), + GasPrice: (*hexutil.Big)(tx.GasPrice), + Gas: (*hexutil.Big)(tx.Gas), + Value: (*hexutil.Big)(tx.Value), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + AccessList: accessList, + Type: TRANSACTION_TYPE_2930.Ptr(), }, To: to, Data: tx.Data, } } + +func (tx *unsigned1559TransactionForRlp) toUnsignedTransaction(networkID uint32) *UnsignedTransaction { + var to *cfxaddress.Address + if tx.To != nil { + _to := cfxaddress.MustNewFromCommon(*tx.To, networkID) + to = &_to + } + + var accessList AccessList + accessList.FromEthType(&tx.AccessList, networkID) + + return &UnsignedTransaction{ + UnsignedTransactionBase: UnsignedTransactionBase{ + From: nil, + Nonce: (*hexutil.Big)(tx.Nonce), + MaxPriorityFeePerGas: (*hexutil.Big)(tx.MaxPriorityFeePerGas), + MaxFeePerGas: (*hexutil.Big)(tx.MaxFeePerGas), + Gas: (*hexutil.Big)(tx.Gas), + Value: (*hexutil.Big)(tx.Value), + StorageLimit: tx.StorageLimit, + EpochHeight: tx.EpochHeight, + ChainID: tx.ChainID, + AccessList: accessList, + Type: TRANSACTION_TYPE_1559.Ptr(), + }, + To: to, + Data: tx.Data, + } +} + +func toUnsignedTransaction(unsignedTxForRlp interface{}, networkID uint32) (*UnsignedTransaction, error) { + switch val := unsignedTxForRlp.(type) { + case unsignedLegacyTransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + case *unsignedLegacyTransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + case unsigned2930TransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + case *unsigned2930TransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + case unsigned1559TransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + case *unsigned1559TransactionForRlp: + return val.toUnsignedTransaction(networkID), nil + } + return nil, errors.New("unkown transaction type") +}