Remove status backend from les internal api (#670)
This commit is contained in:
parent
b83666a90e
commit
4a49e840e3
|
@ -1,381 +0,0 @@
|
||||||
diff --git a/eth/api_backend.go b/eth/api_backend.go
|
|
||||||
index 91f392f94..471275de5 100644
|
|
||||||
--- a/eth/api_backend.go
|
|
||||||
+++ b/eth/api_backend.go
|
|
||||||
@@ -32,14 +32,20 @@ import (
|
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
+ "github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EthApiBackend implements ethapi.Backend for full nodes
|
|
||||||
type EthApiBackend struct {
|
|
||||||
- eth *Ethereum
|
|
||||||
- gpo *gasprice.Oracle
|
|
||||||
+ eth *Ethereum
|
|
||||||
+ gpo *gasprice.Oracle
|
|
||||||
+ statusBackend *ethapi.StatusBackend
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (b *EthApiBackend) GetStatusBackend() *ethapi.StatusBackend {
|
|
||||||
+ return b.statusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *EthApiBackend) ChainConfig() *params.ChainConfig {
|
|
||||||
diff --git a/eth/backend.go b/eth/backend.go
|
|
||||||
index 1cd9e8fff..2fbdec4e2 100644
|
|
||||||
--- a/eth/backend.go
|
|
||||||
+++ b/eth/backend.go
|
|
||||||
@@ -169,7 +169,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|
||||||
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
|
|
||||||
eth.miner.SetExtra(makeExtraData(config.ExtraData))
|
|
||||||
|
|
||||||
- eth.ApiBackend = &EthApiBackend{eth, nil}
|
|
||||||
+ eth.ApiBackend = &EthApiBackend{eth, nil, nil}
|
|
||||||
gpoParams := config.GPO
|
|
||||||
if gpoParams.Default == nil {
|
|
||||||
gpoParams.Default = config.GasPrice
|
|
||||||
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
|
|
||||||
index 025f42617..d8f48a890 100644
|
|
||||||
--- a/internal/ethapi/api.go
|
|
||||||
+++ b/internal/ethapi/api.go
|
|
||||||
@@ -178,15 +178,24 @@ func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string]string {
|
|
||||||
// It offers only methods that can retrieve accounts.
|
|
||||||
type PublicAccountAPI struct {
|
|
||||||
am *accounts.Manager
|
|
||||||
+ b Backend
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPublicAccountAPI creates a new PublicAccountAPI.
|
|
||||||
-func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
|
|
||||||
- return &PublicAccountAPI{am: am}
|
|
||||||
+func NewPublicAccountAPI(b Backend) *PublicAccountAPI {
|
|
||||||
+ return &PublicAccountAPI{
|
|
||||||
+ am: b.AccountManager(),
|
|
||||||
+ b: b,
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accounts returns the collection of accounts this node manages
|
|
||||||
func (s *PublicAccountAPI) Accounts() []common.Address {
|
|
||||||
+ backend := s.b.GetStatusBackend()
|
|
||||||
+ if backend != nil {
|
|
||||||
+ return backend.am.Accounts()
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
|
||||||
for _, wallet := range s.am.Wallets() {
|
|
||||||
for _, account := range wallet.Accounts() {
|
|
||||||
@@ -216,6 +225,11 @@ func NewPrivateAccountAPI(b Backend, nonceLock *AddrLocker) *PrivateAccountAPI {
|
|
||||||
|
|
||||||
// ListAccounts will return a list of addresses for accounts this node manages.
|
|
||||||
func (s *PrivateAccountAPI) ListAccounts() []common.Address {
|
|
||||||
+ backend := s.b.GetStatusBackend()
|
|
||||||
+ if backend != nil {
|
|
||||||
+ return backend.am.Accounts()
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
|
||||||
for _, wallet := range s.am.Wallets() {
|
|
||||||
for _, account := range wallet.Accounts() {
|
|
||||||
@@ -1122,10 +1136,46 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
|
|
||||||
return tx.Hash(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
-// SendTransaction creates a transaction for the given argument, sign it and submit it to the
|
|
||||||
+// SendTransactionWithPassphrase creates a transaction by unpacking queued transaction, signs it and submits to the
|
|
||||||
// transaction pool.
|
|
||||||
-func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
|
|
||||||
+// @Status
|
|
||||||
+func (s *PublicTransactionPoolAPI) SendTransactionWithPassphrase(ctx context.Context, args SendTxArgs, passphrase string) (common.Hash, error) {
|
|
||||||
+ // Look up the wallet containing the requested signer
|
|
||||||
+ account := accounts.Account{Address: args.From}
|
|
||||||
+
|
|
||||||
+ wallet, err := s.b.AccountManager().Find(account)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return common.Hash{}, err
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if args.Nonce == nil {
|
|
||||||
+ // Hold the addresse's mutex around signing to prevent concurrent assignment of
|
|
||||||
+ // the same nonce to multiple accounts.
|
|
||||||
+ s.nonceLock.LockAddr(args.From)
|
|
||||||
+ defer s.nonceLock.UnlockAddr(args.From)
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ // Set some sanity defaults and terminate on failure
|
|
||||||
+ if err := args.setDefaults(ctx, s.b); err != nil {
|
|
||||||
+ return common.Hash{}, err
|
|
||||||
+ }
|
|
||||||
+ // Assemble the transaction and sign with the wallet
|
|
||||||
+ tx := args.toTransaction()
|
|
||||||
+
|
|
||||||
+ var chainID *big.Int
|
|
||||||
+ if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
|
|
||||||
+ chainID = config.ChainId
|
|
||||||
+ }
|
|
||||||
+ signed, err := wallet.SignTxWithPassphrase(account, passphrase, tx, chainID)
|
|
||||||
+ if err != nil {
|
|
||||||
+ return common.Hash{}, err
|
|
||||||
+ }
|
|
||||||
+ return submitTransaction(ctx, s.b, signed)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SendTransaction creates a transaction by unpacking queued transaction, signs it and submits to the
|
|
||||||
+// transaction pool.
|
|
||||||
+func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
|
|
||||||
// Look up the wallet containing the requested signer
|
|
||||||
account := accounts.Account{Address: args.From}
|
|
||||||
|
|
||||||
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
|
|
||||||
index 368fa4872..cac58dfc0 100644
|
|
||||||
--- a/internal/ethapi/backend.go
|
|
||||||
+++ b/internal/ethapi/backend.go
|
|
||||||
@@ -68,6 +68,8 @@ type Backend interface {
|
|
||||||
|
|
||||||
ChainConfig() *params.ChainConfig
|
|
||||||
CurrentBlock() *types.Block
|
|
||||||
+
|
|
||||||
+ GetStatusBackend() *StatusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAPIs(apiBackend Backend) []rpc.API {
|
|
||||||
@@ -105,7 +107,7 @@ func GetAPIs(apiBackend Backend) []rpc.API {
|
|
||||||
}, {
|
|
||||||
Namespace: "eth",
|
|
||||||
Version: "1.0",
|
|
||||||
- Service: NewPublicAccountAPI(apiBackend.AccountManager()),
|
|
||||||
+ Service: NewPublicAccountAPI(apiBackend),
|
|
||||||
Public: true,
|
|
||||||
}, {
|
|
||||||
Namespace: "personal",
|
|
||||||
diff --git a/internal/ethapi/status_backend.go b/internal/ethapi/status_backend.go
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..c4e553cae
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/internal/ethapi/status_backend.go
|
|
||||||
@@ -0,0 +1,88 @@
|
|
||||||
+package ethapi
|
|
||||||
+
|
|
||||||
+import (
|
|
||||||
+ "context"
|
|
||||||
+ "errors"
|
|
||||||
+ "math/big"
|
|
||||||
+
|
|
||||||
+ "github.com/ethereum/go-ethereum/common"
|
|
||||||
+ "github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
+ "github.com/ethereum/go-ethereum/les/status"
|
|
||||||
+ "github.com/ethereum/go-ethereum/log"
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+// StatusBackend exposes Ethereum internals to support custom semantics in status-go bindings
|
|
||||||
+type StatusBackend struct {
|
|
||||||
+ eapi *PublicEthereumAPI // Wrapper around the Ethereum object to access metadata
|
|
||||||
+ bcapi *PublicBlockChainAPI // Wrapper around the blockchain to access chain data
|
|
||||||
+ txapi *PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data
|
|
||||||
+
|
|
||||||
+ am *status.AccountManager
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+var (
|
|
||||||
+ ErrStatusBackendNotInited = errors.New("StatusIM backend is not properly inited")
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+// NewStatusBackend creates a new backend using an existing Ethereum object.
|
|
||||||
+func NewStatusBackend(apiBackend Backend) *StatusBackend {
|
|
||||||
+ log.Info("StatusIM: backend service inited")
|
|
||||||
+ return &StatusBackend{
|
|
||||||
+ eapi: NewPublicEthereumAPI(apiBackend),
|
|
||||||
+ bcapi: NewPublicBlockChainAPI(apiBackend),
|
|
||||||
+ txapi: NewPublicTransactionPoolAPI(apiBackend, new(AddrLocker)),
|
|
||||||
+ am: status.NewAccountManager(apiBackend.AccountManager()),
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SetAccountsFilterHandler sets a callback that is triggered when account list is requested
|
|
||||||
+func (b *StatusBackend) SetAccountsFilterHandler(fn status.AccountsFilterHandler) {
|
|
||||||
+ b.am.SetAccountsFilterHandler(fn)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// AccountManager returns reference to account manager
|
|
||||||
+func (b *StatusBackend) AccountManager() *status.AccountManager {
|
|
||||||
+ return b.am
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SendTransaction wraps call to PublicTransactionPoolAPI.SendTransactionWithPassphrase
|
|
||||||
+func (b *StatusBackend) SendTransaction(ctx context.Context, args status.SendTxArgs, passphrase string) (common.Hash, error) {
|
|
||||||
+ if ctx == nil {
|
|
||||||
+ ctx = context.Background()
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if estimatedGas, err := b.EstimateGas(ctx, args); err == nil {
|
|
||||||
+ if estimatedGas.ToInt().Cmp(big.NewInt(defaultGas)) == 1 { // gas > defaultGas
|
|
||||||
+ args.Gas = estimatedGas
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return b.txapi.SendTransactionWithPassphrase(ctx, SendTxArgs(args), passphrase)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// EstimateGas uses underlying blockchain API to obtain gas for a given tx arguments
|
|
||||||
+func (b *StatusBackend) EstimateGas(ctx context.Context, args status.SendTxArgs) (*hexutil.Big, error) {
|
|
||||||
+ if args.Gas != nil {
|
|
||||||
+ return args.Gas, nil
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ var gasPrice hexutil.Big
|
|
||||||
+ if args.GasPrice != nil {
|
|
||||||
+ gasPrice = *args.GasPrice
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ var value hexutil.Big
|
|
||||||
+ if args.Value != nil {
|
|
||||||
+ value = *args.Value
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ callArgs := CallArgs{
|
|
||||||
+ From: args.From,
|
|
||||||
+ To: args.To,
|
|
||||||
+ GasPrice: gasPrice,
|
|
||||||
+ Value: value,
|
|
||||||
+ Data: args.Data,
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return b.bcapi.EstimateGas(ctx, callArgs)
|
|
||||||
+}
|
|
||||||
diff --git a/les/api_backend.go b/les/api_backend.go
|
|
||||||
index 56f617a7d..f839f24e6 100644
|
|
||||||
--- a/les/api_backend.go
|
|
||||||
+++ b/les/api_backend.go
|
|
||||||
@@ -32,14 +32,20 @@ import (
|
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
+ "github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
"github.com/ethereum/go-ethereum/light"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LesApiBackend struct {
|
|
||||||
- eth *LightEthereum
|
|
||||||
- gpo *gasprice.Oracle
|
|
||||||
+ eth *LightEthereum
|
|
||||||
+ gpo *gasprice.Oracle
|
|
||||||
+ statusBackend *ethapi.StatusBackend
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+func (b *LesApiBackend) GetStatusBackend() *ethapi.StatusBackend {
|
|
||||||
+ return b.statusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LesApiBackend) ChainConfig() *params.ChainConfig {
|
|
||||||
diff --git a/les/backend.go b/les/backend.go
|
|
||||||
index 333df920e..71fbc181b 100644
|
|
||||||
--- a/les/backend.go
|
|
||||||
+++ b/les/backend.go
|
|
||||||
@@ -75,6 +75,8 @@ type LightEthereum struct {
|
|
||||||
netRPCService *ethapi.PublicNetAPI
|
|
||||||
|
|
||||||
wg sync.WaitGroup
|
|
||||||
+
|
|
||||||
+ StatusBackend *ethapi.StatusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
|
||||||
@@ -126,12 +128,17 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
|
||||||
if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, true, ClientProtocolVersions, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, quitSync, &leth.wg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
- leth.ApiBackend = &LesApiBackend{leth, nil}
|
|
||||||
+ leth.ApiBackend = &LesApiBackend{leth, nil, nil}
|
|
||||||
gpoParams := config.GPO
|
|
||||||
if gpoParams.Default == nil {
|
|
||||||
gpoParams.Default = config.GasPrice
|
|
||||||
}
|
|
||||||
leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
|
|
||||||
+
|
|
||||||
+ // inject status-im backend
|
|
||||||
+ leth.ApiBackend.statusBackend = ethapi.NewStatusBackend(leth.ApiBackend)
|
|
||||||
+ leth.StatusBackend = leth.ApiBackend.statusBackend // alias
|
|
||||||
+
|
|
||||||
return leth, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/les/status/accounts.go b/les/status/accounts.go
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..78bd2ad92
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/les/status/accounts.go
|
|
||||||
@@ -0,0 +1,45 @@
|
|
||||||
+package status
|
|
||||||
+
|
|
||||||
+import (
|
|
||||||
+ "github.com/ethereum/go-ethereum/accounts"
|
|
||||||
+ "github.com/ethereum/go-ethereum/common"
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+// AccountManager abstracts both internal account manager and extra filter status backend requires
|
|
||||||
+type AccountManager struct {
|
|
||||||
+ am *accounts.Manager
|
|
||||||
+ accountsFilterHandler AccountsFilterHandler
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// NewAccountManager creates a new AccountManager
|
|
||||||
+func NewAccountManager(am *accounts.Manager) *AccountManager {
|
|
||||||
+ return &AccountManager{
|
|
||||||
+ am: am,
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// AccountsFilterHandler function to filter out accounts list
|
|
||||||
+type AccountsFilterHandler func([]common.Address) []common.Address
|
|
||||||
+
|
|
||||||
+// Accounts returns accounts' addresses of currently logged in user.
|
|
||||||
+// Since status supports HD keys, the following list is returned:
|
|
||||||
+// [addressCDK#1, addressCKD#2->Child1, addressCKD#2->Child2, .. addressCKD#2->ChildN]
|
|
||||||
+func (d *AccountManager) Accounts() []common.Address {
|
|
||||||
+ var addresses []common.Address
|
|
||||||
+ for _, wallet := range d.am.Wallets() {
|
|
||||||
+ for _, account := range wallet.Accounts() {
|
|
||||||
+ addresses = append(addresses, account.Address)
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if d.accountsFilterHandler != nil {
|
|
||||||
+ return d.accountsFilterHandler(addresses)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return addresses
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// SetAccountsFilterHandler sets filtering function for accounts list
|
|
||||||
+func (d *AccountManager) SetAccountsFilterHandler(fn AccountsFilterHandler) {
|
|
||||||
+ d.accountsFilterHandler = fn
|
|
||||||
+}
|
|
||||||
diff --git a/les/status/types.go b/les/status/types.go
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..04437bdb6
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/les/status/types.go
|
|
||||||
@@ -0,0 +1,17 @@
|
|
||||||
+package status
|
|
||||||
+
|
|
||||||
+import (
|
|
||||||
+ "github.com/ethereum/go-ethereum/common"
|
|
||||||
+ "github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+// SendTxArgs represents the arguments to submit a new transaction into the transaction pool.
|
|
||||||
+type SendTxArgs struct {
|
|
||||||
+ From common.Address `json:"from"`
|
|
||||||
+ To *common.Address `json:"to"`
|
|
||||||
+ Gas *hexutil.Big `json:"gas"`
|
|
||||||
+ GasPrice *hexutil.Big `json:"gasPrice"`
|
|
||||||
+ Value *hexutil.Big `json:"value"`
|
|
||||||
+ Data hexutil.Bytes `json:"data"`
|
|
||||||
+ Nonce *hexutil.Uint64 `json:"nonce"`
|
|
||||||
+}
|
|
|
@ -30,7 +30,6 @@ Instructions for creating a patch from the command line:
|
||||||
# Patches
|
# Patches
|
||||||
|
|
||||||
- [`0000-accounts-hd-keys.patch`](./0000-accounts-hd-keys.patch) — adds support for HD extended keys (links/docs?)
|
- [`0000-accounts-hd-keys.patch`](./0000-accounts-hd-keys.patch) — adds support for HD extended keys (links/docs?)
|
||||||
- [`0002-les-api-status.patch`](./0002-les-api-status.patch) — adds StatusBackend into LES code (need to be inspected, some things can and should be done outside of les code
|
|
||||||
- [`0004-whisper-notifications.patch`](./0004-whisper-notifications.patch) — adds Whisper notifications (need to be reviewed and documented)
|
- [`0004-whisper-notifications.patch`](./0004-whisper-notifications.patch) — adds Whisper notifications (need to be reviewed and documented)
|
||||||
- [`0006-latest-cht.patch`](./0006-latest-cht.patch) – updates CHT root hashes, should be updated regularly to keep sync fast, until proper Trusted Checkpoint sync is not implemented as part of LES/2 protocol.
|
- [`0006-latest-cht.patch`](./0006-latest-cht.patch) – updates CHT root hashes, should be updated regularly to keep sync fast, until proper Trusted Checkpoint sync is not implemented as part of LES/2 protocol.
|
||||||
- [`0009-whisper-envelopes-tracing.patch`](./0009-whisper-envelopes-tracing.patch) — adds Whisper envelope tracing (need to be reviewed and documented)
|
- [`0009-whisper-envelopes-tracing.patch`](./0009-whisper-envelopes-tracing.patch) — adds Whisper envelope tracing (need to be reviewed and documented)
|
||||||
|
|
|
@ -233,9 +233,6 @@ func (s *TransactionsTestSuite) TestSendEther() {
|
||||||
|
|
||||||
EnsureNodeSync(s.Backend.NodeManager())
|
EnsureNodeSync(s.Backend.NodeManager())
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
|
|
||||||
// create an account
|
// create an account
|
||||||
sampleAddress, _, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
sampleAddress, _, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
|
@ -373,9 +370,6 @@ func (s *TransactionsTestSuite) TestDoubleCompleteQueuedTransactions() {
|
||||||
|
|
||||||
EnsureNodeSync(s.Backend.NodeManager())
|
EnsureNodeSync(s.Backend.NodeManager())
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
|
|
||||||
// log into account from which transactions will be sent
|
// log into account from which transactions will be sent
|
||||||
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
|
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
|
||||||
|
|
||||||
|
@ -450,9 +444,6 @@ func (s *TransactionsTestSuite) TestDiscardQueuedTransaction() {
|
||||||
|
|
||||||
EnsureNodeSync(s.Backend.NodeManager())
|
EnsureNodeSync(s.Backend.NodeManager())
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
|
|
||||||
// reset queue
|
// reset queue
|
||||||
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
||||||
|
|
||||||
|
@ -543,9 +534,6 @@ func (s *TransactionsTestSuite) TestDiscardMultipleQueuedTransactions() {
|
||||||
|
|
||||||
EnsureNodeSync(s.Backend.NodeManager())
|
EnsureNodeSync(s.Backend.NodeManager())
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
|
|
||||||
// reset queue
|
// reset queue
|
||||||
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
s.Backend.TxQueueManager().TransactionQueue().Reset()
|
||||||
|
|
||||||
|
@ -660,9 +648,6 @@ func (s *TransactionsTestSuite) TestNonExistentQueuedTransactions() {
|
||||||
s.StartTestBackend()
|
s.StartTestBackend()
|
||||||
defer s.StopTestBackend()
|
defer s.StopTestBackend()
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
|
|
||||||
// log into account from which transactions will be sent
|
// log into account from which transactions will be sent
|
||||||
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
|
s.NoError(s.Backend.AccountManager().SelectAccount(TestConfig.Account1.Address, TestConfig.Account1.Password))
|
||||||
|
|
||||||
|
@ -679,8 +664,6 @@ func (s *TransactionsTestSuite) TestEvictionOfQueuedTransactions() {
|
||||||
s.StartTestBackend()
|
s.StartTestBackend()
|
||||||
defer s.StopTestBackend()
|
defer s.StopTestBackend()
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
var m sync.Mutex
|
var m sync.Mutex
|
||||||
txCount := 0
|
txCount := 0
|
||||||
txIDs := [queue.DefaultTxQueueCap + 5 + 10]common.QueuedTxID{}
|
txIDs := [queue.DefaultTxQueueCap + 5 + 10]common.QueuedTxID{}
|
||||||
|
@ -747,9 +730,6 @@ func (s *TransactionsTestSuite) setupLocalNode() {
|
||||||
s.StartTestBackend()
|
s.StartTestBackend()
|
||||||
|
|
||||||
EnsureNodeSync(s.Backend.NodeManager())
|
EnsureNodeSync(s.Backend.NodeManager())
|
||||||
|
|
||||||
backend := s.LightEthereumService().StatusBackend
|
|
||||||
s.NotNil(backend)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TransactionsTestSuite) setupUpstreamNode() {
|
func (s *TransactionsTestSuite) setupUpstreamNode() {
|
||||||
|
|
|
@ -32,20 +32,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EthApiBackend implements ethapi.Backend for full nodes
|
// EthApiBackend implements ethapi.Backend for full nodes
|
||||||
type EthApiBackend struct {
|
type EthApiBackend struct {
|
||||||
eth *Ethereum
|
eth *Ethereum
|
||||||
gpo *gasprice.Oracle
|
gpo *gasprice.Oracle
|
||||||
statusBackend *ethapi.StatusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *EthApiBackend) GetStatusBackend() *ethapi.StatusBackend {
|
|
||||||
return b.statusBackend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthApiBackend) ChainConfig() *params.ChainConfig {
|
func (b *EthApiBackend) ChainConfig() *params.ChainConfig {
|
||||||
|
|
|
@ -169,7 +169,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
|
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
|
||||||
eth.miner.SetExtra(makeExtraData(config.ExtraData))
|
eth.miner.SetExtra(makeExtraData(config.ExtraData))
|
||||||
|
|
||||||
eth.ApiBackend = &EthApiBackend{eth, nil, nil}
|
eth.ApiBackend = &EthApiBackend{eth, nil}
|
||||||
gpoParams := config.GPO
|
gpoParams := config.GPO
|
||||||
if gpoParams.Default == nil {
|
if gpoParams.Default == nil {
|
||||||
gpoParams.Default = config.GasPrice
|
gpoParams.Default = config.GasPrice
|
||||||
|
|
|
@ -178,24 +178,15 @@ func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string]string {
|
||||||
// It offers only methods that can retrieve accounts.
|
// It offers only methods that can retrieve accounts.
|
||||||
type PublicAccountAPI struct {
|
type PublicAccountAPI struct {
|
||||||
am *accounts.Manager
|
am *accounts.Manager
|
||||||
b Backend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPublicAccountAPI creates a new PublicAccountAPI.
|
// NewPublicAccountAPI creates a new PublicAccountAPI.
|
||||||
func NewPublicAccountAPI(b Backend) *PublicAccountAPI {
|
func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
|
||||||
return &PublicAccountAPI{
|
return &PublicAccountAPI{am: am}
|
||||||
am: b.AccountManager(),
|
|
||||||
b: b,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accounts returns the collection of accounts this node manages
|
// Accounts returns the collection of accounts this node manages
|
||||||
func (s *PublicAccountAPI) Accounts() []common.Address {
|
func (s *PublicAccountAPI) Accounts() []common.Address {
|
||||||
backend := s.b.GetStatusBackend()
|
|
||||||
if backend != nil {
|
|
||||||
return backend.am.Accounts()
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
||||||
for _, wallet := range s.am.Wallets() {
|
for _, wallet := range s.am.Wallets() {
|
||||||
for _, account := range wallet.Accounts() {
|
for _, account := range wallet.Accounts() {
|
||||||
|
@ -225,11 +216,6 @@ func NewPrivateAccountAPI(b Backend, nonceLock *AddrLocker) *PrivateAccountAPI {
|
||||||
|
|
||||||
// ListAccounts will return a list of addresses for accounts this node manages.
|
// ListAccounts will return a list of addresses for accounts this node manages.
|
||||||
func (s *PrivateAccountAPI) ListAccounts() []common.Address {
|
func (s *PrivateAccountAPI) ListAccounts() []common.Address {
|
||||||
backend := s.b.GetStatusBackend()
|
|
||||||
if backend != nil {
|
|
||||||
return backend.am.Accounts()
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
addresses := make([]common.Address, 0) // return [] instead of nil if empty
|
||||||
for _, wallet := range s.am.Wallets() {
|
for _, wallet := range s.am.Wallets() {
|
||||||
for _, account := range wallet.Accounts() {
|
for _, account := range wallet.Accounts() {
|
||||||
|
@ -1136,46 +1122,10 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
|
||||||
return tx.Hash(), nil
|
return tx.Hash(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTransactionWithPassphrase creates a transaction by unpacking queued transaction, signs it and submits to the
|
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
|
||||||
// transaction pool.
|
|
||||||
// @Status
|
|
||||||
func (s *PublicTransactionPoolAPI) SendTransactionWithPassphrase(ctx context.Context, args SendTxArgs, passphrase string) (common.Hash, error) {
|
|
||||||
// Look up the wallet containing the requested signer
|
|
||||||
account := accounts.Account{Address: args.From}
|
|
||||||
|
|
||||||
wallet, err := s.b.AccountManager().Find(account)
|
|
||||||
if err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.Nonce == nil {
|
|
||||||
// Hold the addresse's mutex around signing to prevent concurrent assignment of
|
|
||||||
// the same nonce to multiple accounts.
|
|
||||||
s.nonceLock.LockAddr(args.From)
|
|
||||||
defer s.nonceLock.UnlockAddr(args.From)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set some sanity defaults and terminate on failure
|
|
||||||
if err := args.setDefaults(ctx, s.b); err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
// Assemble the transaction and sign with the wallet
|
|
||||||
tx := args.toTransaction()
|
|
||||||
|
|
||||||
var chainID *big.Int
|
|
||||||
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
|
|
||||||
chainID = config.ChainId
|
|
||||||
}
|
|
||||||
signed, err := wallet.SignTxWithPassphrase(account, passphrase, tx, chainID)
|
|
||||||
if err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
return submitTransaction(ctx, s.b, signed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendTransaction creates a transaction by unpacking queued transaction, signs it and submits to the
|
|
||||||
// transaction pool.
|
// transaction pool.
|
||||||
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
|
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
|
||||||
|
|
||||||
// Look up the wallet containing the requested signer
|
// Look up the wallet containing the requested signer
|
||||||
account := accounts.Account{Address: args.From}
|
account := accounts.Account{Address: args.From}
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,6 @@ type Backend interface {
|
||||||
|
|
||||||
ChainConfig() *params.ChainConfig
|
ChainConfig() *params.ChainConfig
|
||||||
CurrentBlock() *types.Block
|
CurrentBlock() *types.Block
|
||||||
|
|
||||||
GetStatusBackend() *StatusBackend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAPIs(apiBackend Backend) []rpc.API {
|
func GetAPIs(apiBackend Backend) []rpc.API {
|
||||||
|
@ -107,7 +105,7 @@ func GetAPIs(apiBackend Backend) []rpc.API {
|
||||||
}, {
|
}, {
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Version: "1.0",
|
Version: "1.0",
|
||||||
Service: NewPublicAccountAPI(apiBackend),
|
Service: NewPublicAccountAPI(apiBackend.AccountManager()),
|
||||||
Public: true,
|
Public: true,
|
||||||
}, {
|
}, {
|
||||||
Namespace: "personal",
|
Namespace: "personal",
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
package ethapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/les/status"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StatusBackend exposes Ethereum internals to support custom semantics in status-go bindings
|
|
||||||
type StatusBackend struct {
|
|
||||||
eapi *PublicEthereumAPI // Wrapper around the Ethereum object to access metadata
|
|
||||||
bcapi *PublicBlockChainAPI // Wrapper around the blockchain to access chain data
|
|
||||||
txapi *PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data
|
|
||||||
|
|
||||||
am *status.AccountManager
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrStatusBackendNotInited = errors.New("StatusIM backend is not properly inited")
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewStatusBackend creates a new backend using an existing Ethereum object.
|
|
||||||
func NewStatusBackend(apiBackend Backend) *StatusBackend {
|
|
||||||
log.Info("StatusIM: backend service inited")
|
|
||||||
return &StatusBackend{
|
|
||||||
eapi: NewPublicEthereumAPI(apiBackend),
|
|
||||||
bcapi: NewPublicBlockChainAPI(apiBackend),
|
|
||||||
txapi: NewPublicTransactionPoolAPI(apiBackend, new(AddrLocker)),
|
|
||||||
am: status.NewAccountManager(apiBackend.AccountManager()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAccountsFilterHandler sets a callback that is triggered when account list is requested
|
|
||||||
func (b *StatusBackend) SetAccountsFilterHandler(fn status.AccountsFilterHandler) {
|
|
||||||
b.am.SetAccountsFilterHandler(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccountManager returns reference to account manager
|
|
||||||
func (b *StatusBackend) AccountManager() *status.AccountManager {
|
|
||||||
return b.am
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendTransaction wraps call to PublicTransactionPoolAPI.SendTransactionWithPassphrase
|
|
||||||
func (b *StatusBackend) SendTransaction(ctx context.Context, args status.SendTxArgs, passphrase string) (common.Hash, error) {
|
|
||||||
if ctx == nil {
|
|
||||||
ctx = context.Background()
|
|
||||||
}
|
|
||||||
|
|
||||||
if estimatedGas, err := b.EstimateGas(ctx, args); err == nil {
|
|
||||||
if estimatedGas.ToInt().Cmp(big.NewInt(defaultGas)) == 1 { // gas > defaultGas
|
|
||||||
args.Gas = estimatedGas
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.txapi.SendTransactionWithPassphrase(ctx, SendTxArgs(args), passphrase)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EstimateGas uses underlying blockchain API to obtain gas for a given tx arguments
|
|
||||||
func (b *StatusBackend) EstimateGas(ctx context.Context, args status.SendTxArgs) (*hexutil.Big, error) {
|
|
||||||
if args.Gas != nil {
|
|
||||||
return args.Gas, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var gasPrice hexutil.Big
|
|
||||||
if args.GasPrice != nil {
|
|
||||||
gasPrice = *args.GasPrice
|
|
||||||
}
|
|
||||||
|
|
||||||
var value hexutil.Big
|
|
||||||
if args.Value != nil {
|
|
||||||
value = *args.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
callArgs := CallArgs{
|
|
||||||
From: args.From,
|
|
||||||
To: args.To,
|
|
||||||
GasPrice: gasPrice,
|
|
||||||
Value: value,
|
|
||||||
Data: args.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.bcapi.EstimateGas(ctx, callArgs)
|
|
||||||
}
|
|
|
@ -32,20 +32,14 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
"github.com/ethereum/go-ethereum/light"
|
"github.com/ethereum/go-ethereum/light"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LesApiBackend struct {
|
type LesApiBackend struct {
|
||||||
eth *LightEthereum
|
eth *LightEthereum
|
||||||
gpo *gasprice.Oracle
|
gpo *gasprice.Oracle
|
||||||
statusBackend *ethapi.StatusBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LesApiBackend) GetStatusBackend() *ethapi.StatusBackend {
|
|
||||||
return b.statusBackend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) ChainConfig() *params.ChainConfig {
|
func (b *LesApiBackend) ChainConfig() *params.ChainConfig {
|
||||||
|
|
|
@ -75,8 +75,6 @@ type LightEthereum struct {
|
||||||
netRPCService *ethapi.PublicNetAPI
|
netRPCService *ethapi.PublicNetAPI
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
StatusBackend *ethapi.StatusBackend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
|
@ -128,17 +126,12 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, true, ClientProtocolVersions, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, quitSync, &leth.wg); err != nil {
|
if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, true, ClientProtocolVersions, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, quitSync, &leth.wg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
leth.ApiBackend = &LesApiBackend{leth, nil, nil}
|
leth.ApiBackend = &LesApiBackend{leth, nil}
|
||||||
gpoParams := config.GPO
|
gpoParams := config.GPO
|
||||||
if gpoParams.Default == nil {
|
if gpoParams.Default == nil {
|
||||||
gpoParams.Default = config.GasPrice
|
gpoParams.Default = config.GasPrice
|
||||||
}
|
}
|
||||||
leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
|
leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
|
||||||
|
|
||||||
// inject status-im backend
|
|
||||||
leth.ApiBackend.statusBackend = ethapi.NewStatusBackend(leth.ApiBackend)
|
|
||||||
leth.StatusBackend = leth.ApiBackend.statusBackend // alias
|
|
||||||
|
|
||||||
return leth, nil
|
return leth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package status
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AccountManager abstracts both internal account manager and extra filter status backend requires
|
|
||||||
type AccountManager struct {
|
|
||||||
am *accounts.Manager
|
|
||||||
accountsFilterHandler AccountsFilterHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAccountManager creates a new AccountManager
|
|
||||||
func NewAccountManager(am *accounts.Manager) *AccountManager {
|
|
||||||
return &AccountManager{
|
|
||||||
am: am,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccountsFilterHandler function to filter out accounts list
|
|
||||||
type AccountsFilterHandler func([]common.Address) []common.Address
|
|
||||||
|
|
||||||
// Accounts returns accounts' addresses of currently logged in user.
|
|
||||||
// Since status supports HD keys, the following list is returned:
|
|
||||||
// [addressCDK#1, addressCKD#2->Child1, addressCKD#2->Child2, .. addressCKD#2->ChildN]
|
|
||||||
func (d *AccountManager) Accounts() []common.Address {
|
|
||||||
var addresses []common.Address
|
|
||||||
for _, wallet := range d.am.Wallets() {
|
|
||||||
for _, account := range wallet.Accounts() {
|
|
||||||
addresses = append(addresses, account.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.accountsFilterHandler != nil {
|
|
||||||
return d.accountsFilterHandler(addresses)
|
|
||||||
}
|
|
||||||
|
|
||||||
return addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAccountsFilterHandler sets filtering function for accounts list
|
|
||||||
func (d *AccountManager) SetAccountsFilterHandler(fn AccountsFilterHandler) {
|
|
||||||
d.accountsFilterHandler = fn
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package status
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SendTxArgs represents the arguments to submit a new transaction into the transaction pool.
|
|
||||||
type SendTxArgs struct {
|
|
||||||
From common.Address `json:"from"`
|
|
||||||
To *common.Address `json:"to"`
|
|
||||||
Gas *hexutil.Big `json:"gas"`
|
|
||||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
|
||||||
Value *hexutil.Big `json:"value"`
|
|
||||||
Data hexutil.Bytes `json:"data"`
|
|
||||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
|
||||||
}
|
|
Loading…
Reference in New Issue