diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 5a7be49c..2f1a4fd9 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -273,10 +273,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call sero.CallMsg, if call.Value == nil { call.Value = new(big.Int) } - var fromAddr common.Address - copy(fromAddr[:], call.From[:]) // Set infinite balance to the fake caller account. - from := statedb.GetOrNewStateObject(fromAddr) + from := statedb.GetOrNewStateObject(call.From) from.SetBalance("sero", math.MaxBig256) // Execute the call. msg := callmsg{call} @@ -381,11 +379,7 @@ type callmsg struct { sero.CallMsg } -func (m callmsg) From() common.Address { - var from common.Address - copy(from[:], m.CallMsg.From[:]) - return from -} +func (m callmsg) From() common.Address { return m.CallMsg.From } func (m callmsg) FromNonceAddr() *common.Address { return nil } func (m callmsg) Nonce() uint64 { return 0 } func (m callmsg) CheckNonce() bool { return false } diff --git a/accounts/external/backend.go b/accounts/external/backend.go new file mode 100644 index 00000000..1e2ecc73 --- /dev/null +++ b/accounts/external/backend.go @@ -0,0 +1,230 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package external + +import ( + "fmt" + "math/big" + "sync" + + "github.com/sero-cash/go-sero/accounts" + "github.com/sero-cash/go-sero/common" + "github.com/sero-cash/go-sero/common/hexutil" + "github.com/sero-cash/go-sero/core/types" + "github.com/sero-cash/go-sero/event" + "github.com/sero-cash/go-sero/internal/ethapi" + "github.com/sero-cash/go-sero/log" + "github.com/sero-cash/go-sero/rpc" + "github.com/sero-cash/go-sero/signer/core" +) + +type ExternalBackend struct { + signers []accounts.Wallet +} + +func (eb *ExternalBackend) Wallets() []accounts.Wallet { + return eb.signers +} + +func NewExternalBackend(endpoint string) (*ExternalBackend, error) { + signer, err := NewExternalSigner(endpoint) + if err != nil { + return nil, err + } + return &ExternalBackend{ + signers: []accounts.Wallet{signer}, + }, nil +} + +func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + <-quit + return nil + }) +} + +// ExternalSigner provides an API to interact with an external signer (clef) +// It proxies request to the external signer while forwarding relevant +// request headers +type ExternalSigner struct { + client *rpc.Client + endpoint string + status string + cacheMu sync.RWMutex + cache []accounts.Account +} + +func NewExternalSigner(endpoint string) (*ExternalSigner, error) { + client, err := rpc.Dial(endpoint) + if err != nil { + return nil, err + } + extsigner := &ExternalSigner{ + client: client, + endpoint: endpoint, + } + // Check if reachable + version, err := extsigner.pingVersion() + if err != nil { + return nil, err + } + extsigner.status = fmt.Sprintf("ok [version=%v]", version) + return extsigner, nil +} + +func (api *ExternalSigner) URL() accounts.URL { + return accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + } +} + +func (api *ExternalSigner) Status() (string, error) { + return api.status, nil +} + +func (api *ExternalSigner) Open(passphrase string) error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Close() error { + return fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) Accounts() []accounts.Account { + var accnts []accounts.Account + res, err := api.listAccounts() + if err != nil { + log.Error("account listing failed", "error", err) + return accnts + } + for _, addr := range res { + accnts = append(accnts, accounts.Account{ + URL: accounts.URL{ + Scheme: "extapi", + Path: api.endpoint, + }, + Address: addr, + }) + } + api.cacheMu.Lock() + api.cache = accnts + api.cacheMu.Unlock() + return accnts +} + +func (api *ExternalSigner) Contains(account accounts.Account) bool { + api.cacheMu.RLock() + defer api.cacheMu.RUnlock() + for _, a := range api.cache { + if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) { + return true + } + } + return false +} + +func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + return accounts.Account{}, fmt.Errorf("operation not supported on external signers") +} + +func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { + log.Error("operation SelfDerive not supported on external signers") +} + +func (api *ExternalSigner) signHash(account accounts.Account, hash []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("operation not supported on external signers") +} + +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + mimeType, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(data)); err != nil { + return nil, err + } + // If V is on 27/28-form, convert to to 0/1 for Clique + if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) { + res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use + } + return res, nil +} + +func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) { + var res hexutil.Bytes + var signAddress = common.NewMixedcaseAddress(account.Address) + if err := api.client.Call(&res, "account_signData", + accounts.MimetypeTextPlain, + &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined + hexutil.Encode(text)); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + res := ethapi.SignTransactionResult{} + data := hexutil.Bytes(tx.Data()) + var to *common.MixedcaseAddress + if tx.To() != nil { + t := common.NewMixedcaseAddress(*tx.To()) + to = &t + } + args := &core.SendTxArgs{ + Data: &data, + Nonce: hexutil.Uint64(tx.Nonce()), + Value: hexutil.Big(*tx.Value()), + Gas: hexutil.Uint64(tx.Gas()), + GasPrice: hexutil.Big(*tx.GasPrice()), + To: to, + From: common.NewMixedcaseAddress(account.Address), + } + if err := api.client.Call(&res, "account_signTransaction", args); err != nil { + return nil, err + } + return res.Tx, nil +} + +func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + return []byte{}, fmt.Errorf("passphrase-operations not supported on external signers") +} + +func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + return nil, fmt.Errorf("passphrase-operations not supported on external signers") +} +func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + return nil, fmt.Errorf("passphrase-operations not supported on external signers") +} + +func (api *ExternalSigner) listAccounts() ([]common.Address, error) { + var res []common.Address + if err := api.client.Call(&res, "account_list"); err != nil { + return nil, err + } + return res, nil +} + +func (api *ExternalSigner) pingVersion() (string, error) { + var v string + if err := api.client.Call(&v, "account_version"); err != nil { + return "", err + } + return v, nil +} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8168fa73..206904f9 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1974,14 +1974,6 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen } -func (s *PublicTransactionPoolAPI) GenTx(ctx context.Context, param GenTxArgs) (*txtool.GTxParam, error) { - if err := param.check(); err != nil { - return nil, err - } - - return s.b.GenTx(param.toTxParam()) -} - func commitSendTxArgs(ctx context.Context, b Backend, args SendTxArgs) (common.Hash, error) { // Set some sanity defaults and terminate on failure diff --git a/internal/ethapi/api_abi.go b/internal/ethapi/api_abi.go index 66c36ecd..9b0e04f0 100644 --- a/internal/ethapi/api_abi.go +++ b/internal/ethapi/api_abi.go @@ -95,7 +95,7 @@ func encodeStringParams(abiArgs abi.Arguments, args []string) ([]interface{}, [] return nil, nil, err } //caddr := (c_superzk.HashPKr(addr.ToPKr().NewRef())) - packArgs[index] = addr + packArgs[index] = address address = append(address, addr.ToPKrAddress()) case "address[]": var addrs []AllMixedAddress diff --git a/seroclient/seroclient.go b/seroclient/seroclient.go index da9fd08c..7ecb1c99 100644 --- a/seroclient/seroclient.go +++ b/seroclient/seroclient.go @@ -451,7 +451,7 @@ func (ec *Client) EstimateGas(ctx context.Context, msg sero.CallMsg) (uint64, er func (ec *Client) GenContractTx(ctx context.Context, msg sero.CallMsg) (*txtool.GTxParam, error) { var param txtool.GTxParam - if err := ec.c.CallContext(ctx, ¶m, "sero_genTx", toContractTxArgs(msg)); err != nil { + if err := ec.c.CallContext(ctx, ¶m, "exchange_genTx", toContractTxArgs(msg)); err != nil { return nil, err } return ¶m, nil diff --git a/tests/abigen_test.go b/tests/abigen_test.go index 49967ac2..d4e85b46 100644 --- a/tests/abigen_test.go +++ b/tests/abigen_test.go @@ -91,7 +91,7 @@ func TestCall(t *testing.T) { if err != nil { log.Fatalf("Failed to connect to the Ethereum client: %v", err) } - contractAddress := common.Base58ToAddress("5KCRLWsEFGiXSWaSCwTeMV7MuN14vUhrsmeNAk8DgGT3Fxeo957HwRRzswbfpyjJwhktX3qdgAvpUQ91QLf16g44") + contractAddress := common.Base58ToAddress("25rwV92apLVTVcTyjhAKx2izEmEvpVv5kwoDBi1anWC2HtChJNVg3o4uHTaMxAPmYTUTRM1kLvNDdZLiFXgCJVsg") testAbi, err := abigen.NewTestabi(contractAddress, conn) if err != nil { log.Fatalf("Failed to NewTestabi : %v", err)