github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/rpc/web3/eth_service.go (about)

     1  package web3
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"math/big"
     8  	"strconv"
     9  
    10  	"github.com/hyperledger/burrow/encoding"
    11  	"github.com/hyperledger/burrow/encoding/rlp"
    12  	"github.com/hyperledger/burrow/encoding/web3hex"
    13  
    14  	"github.com/hyperledger/burrow/acm/acmstate"
    15  	"github.com/hyperledger/burrow/acm/balance"
    16  	"github.com/hyperledger/burrow/acm/validator"
    17  	bcm "github.com/hyperledger/burrow/bcm"
    18  	"github.com/hyperledger/burrow/consensus/tendermint"
    19  	"github.com/hyperledger/burrow/crypto"
    20  	"github.com/hyperledger/burrow/execution"
    21  	"github.com/hyperledger/burrow/execution/exec"
    22  	"github.com/hyperledger/burrow/execution/state"
    23  	"github.com/hyperledger/burrow/keys"
    24  	"github.com/hyperledger/burrow/logging"
    25  	"github.com/hyperledger/burrow/project"
    26  	"github.com/hyperledger/burrow/txs"
    27  	"github.com/hyperledger/burrow/txs/payload"
    28  	tmConfig "github.com/tendermint/tendermint/config"
    29  	"github.com/tendermint/tendermint/types"
    30  )
    31  
    32  const (
    33  	maxGasLimit  = 2<<52 - 1
    34  	hexZero      = "0x0"
    35  	hexZeroNonce = "0x0000000000000000"
    36  	pending      = "null"
    37  )
    38  
    39  // EthService is a web3 provider
    40  type EthService struct {
    41  	accounts   acmstate.IterableStatsReader
    42  	events     EventsReader
    43  	blockchain bcm.BlockchainInfo
    44  	validators validator.History
    45  	nodeView   *tendermint.NodeView
    46  	trans      *execution.Transactor
    47  	keyClient  keys.KeyClient
    48  	keyStore   *keys.FilesystemKeyStore
    49  	config     *tmConfig.Config
    50  	chainID    *big.Int
    51  	logger     *logging.Logger
    52  }
    53  
    54  // NewEthService returns our web3 provider
    55  func NewEthService(
    56  	accounts acmstate.IterableStatsReader,
    57  	events EventsReader,
    58  	blockchain bcm.BlockchainInfo,
    59  	validators validator.History,
    60  	nodeView *tendermint.NodeView,
    61  	trans *execution.Transactor,
    62  	keyStore *keys.FilesystemKeyStore,
    63  	logger *logging.Logger,
    64  ) *EthService {
    65  
    66  	keyClient := keys.NewLocalKeyClient(keyStore, logger)
    67  
    68  	return &EthService{
    69  		accounts:   accounts,
    70  		events:     events,
    71  		blockchain: blockchain,
    72  		validators: validators,
    73  		nodeView:   nodeView,
    74  		trans:      trans,
    75  		keyClient:  keyClient,
    76  		keyStore:   keyStore,
    77  		config:     tmConfig.DefaultConfig(),
    78  		// Ethereum expects ChainID to be an integer value
    79  		chainID: encoding.GetEthChainID(blockchain.ChainID()),
    80  		logger:  logger,
    81  	}
    82  }
    83  
    84  var _ Service = &EthService{}
    85  
    86  type EventsReader interface {
    87  	TxsAtHeight(height uint64) ([]*exec.TxExecution, error)
    88  	TxByHash(txHash []byte) (*exec.TxExecution, error)
    89  }
    90  
    91  var _ EventsReader = &state.State{}
    92  
    93  // Web3ClientVersion returns the version of burrow
    94  func (srv *EthService) Web3ClientVersion() (*Web3ClientVersionResult, error) {
    95  	return &Web3ClientVersionResult{
    96  		ClientVersion: project.FullVersion(),
    97  	}, nil
    98  }
    99  
   100  // Web3Sha3 returns Keccak-256 (not the standardized SHA3-256) of the given data
   101  func (srv *EthService) Web3Sha3(req *Web3Sha3Params) (*Web3Sha3Result, error) {
   102  	d := new(web3hex.Decoder)
   103  	return &Web3Sha3Result{
   104  		HashedData: web3hex.Encoder.Bytes(crypto.Keccak256(d.Bytes(req.Data))),
   105  	}, d.Err()
   106  }
   107  
   108  // NetListening returns true if the peer is running
   109  func (srv *EthService) NetListening() (*NetListeningResult, error) {
   110  	return &NetListeningResult{
   111  		IsNetListening: srv.nodeView.NodeInfo().GetListenAddress() != "",
   112  	}, nil
   113  }
   114  
   115  // NetPeerCount returns the number of connected peers
   116  func (srv *EthService) NetPeerCount() (*NetPeerCountResult, error) {
   117  	s := web3hex.Encoder.Uint64(uint64(srv.nodeView.Peers().Size()))
   118  	return &NetPeerCountResult{
   119  		s,
   120  	}, nil
   121  }
   122  
   123  // NetVersion returns the hex encoding of the network id,
   124  // this is typically a small int (where 1 == Ethereum mainnet)
   125  func (srv *EthService) NetVersion() (*NetVersionResult, error) {
   126  	return &NetVersionResult{
   127  		ChainID: web3hex.Encoder.BigInt(srv.chainID),
   128  	}, nil
   129  }
   130  
   131  // EthProtocolVersion returns the version of tendermint
   132  func (srv *EthService) EthProtocolVersion() (*EthProtocolVersionResult, error) {
   133  	return &EthProtocolVersionResult{
   134  		ProtocolVersion: srv.nodeView.NodeInfo().Version,
   135  	}, nil
   136  }
   137  
   138  // EthChainId returns the chainID
   139  func (srv *EthService) EthChainId() (*EthChainIdResult, error) {
   140  	return &EthChainIdResult{
   141  		ChainId: web3hex.Encoder.BigInt(srv.chainID),
   142  	}, nil
   143  }
   144  
   145  // EthBlockNumber returns the latest height
   146  func (srv *EthService) EthBlockNumber() (*EthBlockNumberResult, error) {
   147  	return &EthBlockNumberResult{
   148  		BlockNumber: web3hex.Encoder.Uint64(srv.blockchain.LastBlockHeight()),
   149  	}, nil
   150  }
   151  
   152  // EthCall executes a new message call immediately without creating a transaction
   153  func (srv *EthService) EthCall(req *EthCallParams) (*EthCallResult, error) {
   154  	d := new(web3hex.Decoder)
   155  
   156  	from := d.Address(req.Transaction.From)
   157  	to := d.Address(req.Transaction.To)
   158  	data := d.Bytes(req.Transaction.Data)
   159  
   160  	if d.Err() != nil {
   161  		return nil, d.Err()
   162  	}
   163  	txe, err := execution.CallSim(srv.accounts, srv.blockchain, from, to, data, srv.logger)
   164  	if err != nil {
   165  		return nil, err
   166  	} else if txe.Exception != nil {
   167  		return nil, txe.Exception.AsError()
   168  	}
   169  
   170  	var result string
   171  	if r := txe.GetResult(); r != nil {
   172  		result = web3hex.Encoder.Bytes(r.GetReturn())
   173  	}
   174  
   175  	return &EthCallResult{
   176  		ReturnValue: result,
   177  	}, nil
   178  }
   179  
   180  // EthGetBalance returns an accounts balance, or an error if it does not exist
   181  func (srv *EthService) EthGetBalance(req *EthGetBalanceParams) (*EthGetBalanceResult, error) {
   182  	d := new(web3hex.Decoder)
   183  	addr := d.Address(req.Address)
   184  	if d.Err() != nil {
   185  		return nil, d.Err()
   186  	}
   187  
   188  	// TODO: read account state at height
   189  	acc, err := srv.accounts.GetAccount(addr)
   190  	if err != nil {
   191  		return nil, err
   192  	} else if acc == nil {
   193  		return nil, fmt.Errorf("account not found at address %s", req.Address)
   194  	}
   195  
   196  	return &EthGetBalanceResult{
   197  		GetBalanceResult: web3hex.Encoder.Bytes(balance.NativeToWei(acc.Balance).Bytes()),
   198  	}, nil
   199  }
   200  
   201  // EthGetBlockByHash iterates through all headers to find a matching block height for a given hash
   202  func (srv *EthService) EthGetBlockByHash(req *EthGetBlockByHashParams) (*EthGetBlockByHashResult, error) {
   203  	height, err := srv.getBlockHeightByHash(req.BlockHash)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	block, err := srv.getBlockInfoAtHeight(height, req.IsTransactionsIncluded)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  
   213  	return &EthGetBlockByHashResult{
   214  		GetBlockByHashResult: block,
   215  	}, nil
   216  }
   217  
   218  // EthGetBlockByNumber returns block info at the given height
   219  func (srv *EthService) EthGetBlockByNumber(req *EthGetBlockByNumberParams) (*EthGetBlockByNumberResult, error) {
   220  	height, err := srv.getHeightByWordOrNumber(req.BlockNumber)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  
   225  	block, err := srv.getBlockInfoAtHeight(height, req.IsTransactionsIncluded)
   226  	if err != nil {
   227  		return nil, err
   228  	}
   229  
   230  	return &EthGetBlockByNumberResult{
   231  		GetBlockByNumberResult: block,
   232  	}, nil
   233  }
   234  
   235  // EthGetBlockTransactionCountByHash returns the number of transactions in a block matching a given hash
   236  func (srv *EthService) EthGetBlockTransactionCountByHash(req *EthGetBlockTransactionCountByHashParams) (*EthGetBlockTransactionCountByHashResult, error) {
   237  	height, err := srv.getBlockHeightByHash(req.BlockHash)
   238  	if err != nil {
   239  		return nil, err
   240  	}
   241  
   242  	numTxs, err := srv.blockchain.GetNumTxs(height)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	return &EthGetBlockTransactionCountByHashResult{
   248  		BlockTransactionCountByHash: web3hex.Encoder.Uint64(uint64(numTxs)),
   249  	}, nil
   250  }
   251  
   252  // EthGetBlockTransactionCountByNumber returns the number of transactions in a block matching a given height
   253  func (srv *EthService) EthGetBlockTransactionCountByNumber(req *EthGetBlockTransactionCountByNumberParams) (*EthGetBlockTransactionCountByNumberResult, error) {
   254  	height, err := srv.getHeightByWordOrNumber(req.BlockNumber)
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  
   259  	numTxs, err := srv.blockchain.GetNumTxs(height)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  
   264  	return &EthGetBlockTransactionCountByNumberResult{
   265  		BlockTransactionCountByHash: web3hex.Encoder.Uint64(uint64(numTxs)),
   266  	}, nil
   267  }
   268  
   269  // EthGetCode returns the EVM bytecode at an address
   270  func (srv *EthService) EthGetCode(req *EthGetCodeParams) (*EthGetCodeResult, error) {
   271  	d := new(web3hex.Decoder)
   272  	addr := d.Address(req.Address)
   273  	if d.Err() != nil {
   274  		return nil, d.Err()
   275  	}
   276  
   277  	acc, err := srv.accounts.GetAccount(addr)
   278  	if err != nil {
   279  		return nil, err
   280  	} else if acc == nil {
   281  		return nil, fmt.Errorf("account not found at address %s", req.Address)
   282  	}
   283  
   284  	return &EthGetCodeResult{
   285  		Bytes: web3hex.Encoder.Bytes(acc.EVMCode),
   286  	}, nil
   287  }
   288  
   289  func (srv *EthService) EthGetStorageAt(req *EthGetStorageAtParams) (*EthGetStorageAtResult, error) {
   290  	// TODO
   291  	return nil, ErrNotFound
   292  }
   293  
   294  func (srv *EthService) EthGetTransactionByBlockHashAndIndex(req *EthGetTransactionByBlockHashAndIndexParams) (*EthGetTransactionByBlockHashAndIndexResult, error) {
   295  	height, err := srv.getBlockHeightByHash(req.BlockHash)
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  
   300  	head, err := srv.blockchain.GetBlockHeader(height)
   301  	if err != nil {
   302  		return nil, err
   303  	}
   304  
   305  	txes, err := srv.events.TxsAtHeight(height)
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  
   310  	d := new(web3hex.Decoder)
   311  
   312  	index := d.Uint64(req.Index)
   313  
   314  	if d.Err() != nil {
   315  		return nil, d.Err()
   316  	}
   317  
   318  	for _, txe := range txes {
   319  		if txe.GetIndex() == index {
   320  			hash, tx, err := getHashAndCallTxFromExecution(txe)
   321  			if err != nil {
   322  				return nil, err
   323  			}
   324  			return &EthGetTransactionByBlockHashAndIndexResult{
   325  				TransactionResult: getTransaction(head, hash, tx),
   326  			}, nil
   327  		}
   328  	}
   329  
   330  	return nil, fmt.Errorf("tx not found at hash %s, index %d", req.BlockHash, index)
   331  }
   332  
   333  func (srv *EthService) EthGetTransactionByBlockNumberAndIndex(req *EthGetTransactionByBlockNumberAndIndexParams) (*EthGetTransactionByBlockNumberAndIndexResult, error) {
   334  	height, err := srv.getHeightByWordOrNumber(req.BlockNumber)
   335  	if err != nil {
   336  		return nil, err
   337  	}
   338  
   339  	head, err := srv.blockchain.GetBlockHeader(height)
   340  	if err != nil {
   341  		return nil, err
   342  	}
   343  
   344  	txes, err := srv.events.TxsAtHeight(height)
   345  	if err != nil {
   346  		return nil, err
   347  	}
   348  	d := new(web3hex.Decoder)
   349  	index := d.Uint64(req.Index)
   350  	if d.Err() != nil {
   351  		return nil, d.Err()
   352  	}
   353  
   354  	for _, txe := range txes {
   355  		if txe.GetIndex() == index {
   356  			hash, tx, err := getHashAndCallTxFromExecution(txe)
   357  			if err != nil {
   358  				return nil, err
   359  			}
   360  			return &EthGetTransactionByBlockNumberAndIndexResult{
   361  				TransactionResult: getTransaction(head, hash, tx),
   362  			}, nil
   363  		}
   364  	}
   365  
   366  	return nil, fmt.Errorf("tx not found at height %d, index %d", height, index)
   367  }
   368  
   369  // EthGetTransactionByHash finds a tx by the given hash
   370  func (srv *EthService) EthGetTransactionByHash(req *EthGetTransactionByHashParams) (*EthGetTransactionByHashResult, error) {
   371  	d := new(web3hex.Decoder)
   372  
   373  	hash := d.Bytes(req.TransactionHash)
   374  	if d.Err() != nil {
   375  		return nil, d.Err()
   376  	}
   377  	txe, err := srv.events.TxByHash(hash)
   378  	if err != nil {
   379  		return nil, err
   380  	}
   381  
   382  	head, err := srv.blockchain.GetBlockHeader(txe.Height)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  
   387  	hash, tx, err := getHashAndCallTxFromExecution(txe)
   388  	if err != nil {
   389  		return nil, err
   390  	}
   391  
   392  	return &EthGetTransactionByHashResult{
   393  		Transaction: getTransaction(head, hash, tx),
   394  	}, nil
   395  }
   396  
   397  // EthGetTransactionCount returns the number of transactions sent from an address
   398  func (srv *EthService) EthGetTransactionCount(req *EthGetTransactionCountParams) (*EthGetTransactionCountResult, error) {
   399  	d := new(web3hex.Decoder)
   400  	addr := d.Address(req.Address)
   401  	if d.Err() != nil {
   402  		return nil, d.Err()
   403  	}
   404  
   405  	// TODO: get tx count at height
   406  	acc, err := srv.accounts.GetAccount(addr)
   407  	if err != nil {
   408  		return nil, err
   409  	}
   410  
   411  	// TODO: sequence may not always be accurate, is there a better way?
   412  	return &EthGetTransactionCountResult{
   413  		NonceOrNull: web3hex.Encoder.Uint64(acc.GetSequence()),
   414  	}, nil
   415  }
   416  
   417  func getHashAndCallTxFromEnvelope(env *txs.Envelope) ([]byte, *payload.CallTx, error) {
   418  	if env.Tx == nil {
   419  		return nil, nil, fmt.Errorf("tx not found for %s", env.String())
   420  	} else if tx, ok := env.Tx.Payload.(*payload.CallTx); ok {
   421  		return env.Tx.Hash().Bytes(), tx, nil
   422  	}
   423  	return nil, nil, fmt.Errorf("tx not valid")
   424  }
   425  
   426  func getHashAndCallTxFromExecution(txe *exec.TxExecution) ([]byte, *payload.CallTx, error) {
   427  	if txe.Envelope == nil {
   428  		return nil, nil, fmt.Errorf("envelope not found for %s", txe.GetTxHash().String())
   429  	}
   430  	return getHashAndCallTxFromEnvelope(txe.Envelope)
   431  }
   432  
   433  // EthGetTransactionReceipt returns the receipt of a previously committed tx
   434  func (srv *EthService) EthGetTransactionReceipt(req *EthGetTransactionReceiptParams) (*EthGetTransactionReceiptResult, error) {
   435  	d := new(web3hex.Decoder)
   436  
   437  	data := d.Bytes(req.TransactionHash)
   438  	if d.Err() != nil {
   439  		return nil, d.Err()
   440  	}
   441  
   442  	txe, err := srv.events.TxByHash(data)
   443  	if err != nil {
   444  		return nil, err
   445  	} else if txe == nil {
   446  		return nil, fmt.Errorf("tx with hash %s does not exist", req.TransactionHash)
   447  	}
   448  
   449  	hash, tx, err := getHashAndCallTxFromExecution(txe)
   450  	if err != nil {
   451  		return nil, err
   452  	}
   453  
   454  	block, err := srv.blockchain.GetBlockHeader(txe.Height)
   455  	if err != nil {
   456  		return nil, err
   457  	}
   458  
   459  	status := web3hex.Encoder.Uint64(1)
   460  	if err := txe.Exception.AsError(); err != nil {
   461  		status = web3hex.Encoder.Uint64(0)
   462  	}
   463  
   464  	result := &EthGetTransactionReceiptResult{
   465  		Receipt: Receipt{
   466  			Status:            status,
   467  			TransactionIndex:  web3hex.Encoder.Uint64(txe.GetIndex()),
   468  			BlockNumber:       web3hex.Encoder.Uint64(uint64(block.Height)),
   469  			BlockHash:         web3hex.Encoder.Bytes(block.Hash()),
   470  			From:              web3hex.Encoder.Bytes(tx.GetInput().Address.Bytes()),
   471  			GasUsed:           web3hex.Encoder.Uint64(txe.Result.GetGasUsed()),
   472  			TransactionHash:   web3hex.Encoder.Bytes(hash),
   473  			CumulativeGasUsed: hexZero,
   474  			LogsBloom:         hexZero,
   475  			Logs:              []Logs{},
   476  		},
   477  	}
   478  
   479  	if txe.Receipt != nil {
   480  		result.Receipt.ContractAddress = web3hex.Encoder.Bytes(txe.Receipt.ContractAddress.Bytes())
   481  		result.Receipt.To = pending
   482  	} else if tx.Address != nil {
   483  		result.Receipt.To = web3hex.Encoder.Bytes(tx.Address.Bytes())
   484  	}
   485  
   486  	return result, nil
   487  }
   488  
   489  // EthHashrate returns the configured tendermint commit timeout
   490  func (srv *EthService) EthHashrate() (*EthHashrateResult, error) {
   491  	return &EthHashrateResult{
   492  		HashesPerSecond: srv.config.Consensus.TimeoutCommit.String(),
   493  	}, nil
   494  }
   495  
   496  // EthMining returns true if client is a validator
   497  func (srv *EthService) EthMining() (*EthMiningResult, error) {
   498  	var isVal bool
   499  	addr := srv.nodeView.ValidatorAddress()
   500  	val := srv.validators.Validators(1)
   501  	err := val.IterateValidators(func(id crypto.Addressable, _ *big.Int) error {
   502  		if addr == id.GetAddress() {
   503  			isVal = true
   504  		}
   505  		return nil
   506  	})
   507  	if err != nil {
   508  		return nil, err
   509  	}
   510  	return &EthMiningResult{
   511  		Mining: isVal,
   512  	}, nil
   513  }
   514  
   515  // EthPendingTransactions returns all txs in the mempool
   516  func (srv *EthService) EthPendingTransactions() (*EthPendingTransactionsResult, error) {
   517  	pending := make([]PendingTransactions, 0)
   518  	envelopes, err := srv.nodeView.MempoolTransactions(-1)
   519  	if err != nil {
   520  		return nil, err
   521  	}
   522  
   523  	for _, env := range envelopes {
   524  		hash, tx, err := getHashAndCallTxFromEnvelope(env)
   525  		if err != nil {
   526  			continue
   527  		}
   528  		pending = append(pending, PendingTransactions{
   529  			Transaction: getTransaction(nil, hash, tx),
   530  		})
   531  	}
   532  
   533  	return &EthPendingTransactionsResult{
   534  		PendingTransactions: pending,
   535  	}, nil
   536  }
   537  
   538  func (srv *EthService) EthEstimateGas(req *EthEstimateGasParams) (*EthEstimateGasResult, error) {
   539  	// TODO
   540  	return &EthEstimateGasResult{
   541  		GasUsed: hexZero,
   542  	}, nil
   543  }
   544  
   545  func (srv *EthService) EthGasPrice() (*EthGasPriceResult, error) {
   546  	// TODO
   547  	return &EthGasPriceResult{
   548  		GasPrice: hexZero,
   549  	}, nil
   550  }
   551  
   552  func (srv *EthService) EthGetRawTransactionByHash(req *EthGetRawTransactionByHashParams) (*EthGetRawTransactionByHashResult, error) {
   553  	// TODO
   554  	return nil, ErrNotFound
   555  }
   556  
   557  func (srv *EthService) EthGetRawTransactionByBlockHashAndIndex(req *EthGetRawTransactionByBlockHashAndIndexParams) (*EthGetRawTransactionByBlockHashAndIndexResult, error) {
   558  	// TODO
   559  	return nil, ErrNotFound
   560  }
   561  
   562  func (srv *EthService) EthGetRawTransactionByBlockNumberAndIndex(req *EthGetRawTransactionByBlockNumberAndIndexParams) (*EthGetRawTransactionByBlockNumberAndIndexResult, error) {
   563  	// TODO
   564  	return nil, ErrNotFound
   565  }
   566  
   567  func (srv *EthService) EthSendRawTransaction(req *EthSendRawTransactionParams) (*EthSendRawTransactionResult, error) {
   568  	d := new(web3hex.Decoder)
   569  
   570  	data := d.Bytes(req.SignedTransactionData)
   571  
   572  	if d.Err() != nil {
   573  		return nil, d.Err()
   574  	}
   575  
   576  	rawTx := txs.NewEthRawTx(srv.chainID)
   577  	err := rlp.Decode(data, rawTx)
   578  	if err != nil {
   579  		return nil, err
   580  	}
   581  
   582  	publicKey, signature, err := rawTx.RecoverPublicKey()
   583  	if err != nil {
   584  		return nil, err
   585  	}
   586  
   587  	from := publicKey.GetAddress()
   588  
   589  	to, err := crypto.AddressFromBytes(rawTx.To)
   590  	if err != nil {
   591  		return nil, err
   592  	}
   593  
   594  	amount := balance.WeiToNative(rawTx.Amount).Uint64()
   595  
   596  	txEnv := &txs.Envelope{
   597  		Signatories: []txs.Signatory{
   598  			{
   599  				Address:   &from,
   600  				PublicKey: publicKey,
   601  				Signature: signature,
   602  			},
   603  		},
   604  		Encoding: txs.Envelope_RLP,
   605  		Tx: &txs.Tx{
   606  			ChainID: srv.blockchain.ChainID(),
   607  			Payload: &payload.CallTx{
   608  				Input: &payload.TxInput{
   609  					Address: from,
   610  					Amount:  amount,
   611  					// first tx sequence should be 1,
   612  					// but metamask starts at 0
   613  					Sequence: rawTx.Sequence + 1,
   614  				},
   615  				Address:  &to,
   616  				GasLimit: rawTx.GasLimit,
   617  				GasPrice: rawTx.GasPrice,
   618  				Data:     rawTx.Data,
   619  			},
   620  		},
   621  	}
   622  
   623  	ctx := context.Background()
   624  	txe, err := srv.trans.BroadcastTxSync(ctx, txEnv)
   625  	if err != nil {
   626  		return nil, err
   627  	} else if txe.Exception != nil {
   628  		return nil, txe.Exception.AsError()
   629  	}
   630  
   631  	return &EthSendRawTransactionResult{
   632  		TransactionHash: web3hex.Encoder.Bytes(txe.GetTxHash().Bytes()),
   633  	}, nil
   634  }
   635  
   636  // EthSyncing returns this nodes syncing status (i.e. whether it has caught up)
   637  func (srv *EthService) EthSyncing() (*EthSyncingResult, error) {
   638  	// TODO: remaining sync fields
   639  	return &EthSyncingResult{
   640  		Syncing: SyncStatus{
   641  			CurrentBlock: web3hex.Encoder.Uint64(srv.blockchain.LastBlockHeight()),
   642  		},
   643  	}, nil
   644  }
   645  
   646  func (srv *EthService) getBlockHeightByHash(hash string) (uint64, error) {
   647  	for i := uint64(1); i < srv.blockchain.LastBlockHeight(); i++ {
   648  		head, err := srv.blockchain.GetBlockHeader(i)
   649  		if err != nil {
   650  			return 0, err
   651  		} else if hexKeccak(head.Hash().Bytes()) == hash {
   652  			return i, nil
   653  		}
   654  	}
   655  	return 0, ErrNotFound
   656  }
   657  
   658  func (srv *EthService) getBlockHeaderAtHeight(height uint64) (*types.Header, error) {
   659  	return srv.blockchain.GetBlockHeader(height)
   660  }
   661  
   662  func hexKeccak(data []byte) string {
   663  	return web3hex.Encoder.Bytes(crypto.Keccak256(data))
   664  }
   665  
   666  func hexKeccakAddress(data []byte) string {
   667  	addr := crypto.Keccak256(data)
   668  	return web3hex.Encoder.Bytes(addr[len(addr)-20:])
   669  }
   670  
   671  func (srv *EthService) getBlockInfoAtHeight(height uint64, includeTxs bool) (Block, error) {
   672  	doc := srv.blockchain.GenesisDoc()
   673  	if height == 0 {
   674  		// genesis
   675  		return Block{
   676  			Transactions:    make([]Transactions, 0),
   677  			Uncles:          make([]string, 0),
   678  			Nonce:           hexZeroNonce,
   679  			Hash:            hexKeccak(doc.AppHash.Bytes()),
   680  			ParentHash:      hexKeccak(doc.AppHash.Bytes()),
   681  			ReceiptsRoot:    hexKeccak(doc.AppHash.Bytes()),
   682  			StateRoot:       hexKeccak(doc.AppHash.Bytes()),
   683  			Miner:           web3hex.Encoder.Bytes(doc.Validators[0].Address.Bytes()),
   684  			Timestamp:       web3hex.Encoder.Uint64(uint64(doc.GenesisTime.Unix())),
   685  			Number:          hexZero,
   686  			Size:            hexZero,
   687  			ExtraData:       hexZero,
   688  			Difficulty:      hexZero,
   689  			TotalDifficulty: hexZero,
   690  			GasLimit:        hexZero,
   691  			GasUsed:         hexZero,
   692  		}, nil
   693  	}
   694  	block, err := srv.getBlockHeaderAtHeight(height)
   695  	if err != nil {
   696  		return Block{}, err
   697  	} else if block == nil {
   698  		return Block{}, fmt.Errorf("block at height %d does not exist", height)
   699  	}
   700  
   701  	numTxs, err := srv.blockchain.GetNumTxs(height)
   702  	if err != nil {
   703  		return Block{}, err
   704  	}
   705  
   706  	transactions := make([]Transactions, 0)
   707  	if includeTxs {
   708  		txes, err := srv.events.TxsAtHeight(height)
   709  		if err != nil {
   710  			return Block{}, err
   711  		}
   712  		for _, txe := range txes {
   713  			hash, tx, err := getHashAndCallTxFromExecution(txe)
   714  			if err != nil {
   715  				continue
   716  			}
   717  			transactions = append(transactions, Transactions{
   718  				getTransaction(block, hash, tx),
   719  			})
   720  		}
   721  	}
   722  
   723  	return Block{
   724  		Hash:             hexKeccak(block.Hash().Bytes()),
   725  		ParentHash:       hexKeccak(block.Hash().Bytes()),
   726  		TransactionsRoot: hexKeccak(block.Hash().Bytes()),
   727  		StateRoot:        hexKeccak(block.Hash().Bytes()),
   728  		ReceiptsRoot:     hexKeccak(block.Hash().Bytes()),
   729  		Nonce:            hexZeroNonce,
   730  		Size:             web3hex.Encoder.Uint64(uint64(numTxs)),
   731  		Number:           web3hex.Encoder.Uint64(uint64(block.Height)),
   732  		Miner:            web3hex.Encoder.Bytes(block.ProposerAddress.Bytes()),
   733  		Sha3Uncles:       hexZero,
   734  		LogsBloom:        hexZero,
   735  		ExtraData:        hexZero,
   736  		Difficulty:       hexZero,
   737  		TotalDifficulty:  hexZero,
   738  		GasUsed:          hexZero,
   739  		GasLimit:         web3hex.Encoder.Uint64(maxGasLimit),
   740  		Timestamp:        web3hex.Encoder.Uint64(uint64(block.Time.Unix())),
   741  		Transactions:     transactions,
   742  		Uncles:           []string{},
   743  	}, nil
   744  }
   745  
   746  func getTransaction(block *types.Header, hash []byte, tx *payload.CallTx) Transaction {
   747  	// TODO: sensible defaults for non-call
   748  	transaction := Transaction{
   749  		V:        hexZero,
   750  		R:        hexZero,
   751  		S:        hexZero,
   752  		From:     web3hex.Encoder.Bytes(tx.Input.Address.Bytes()),
   753  		Value:    web3hex.Encoder.Uint64(tx.Input.Amount),
   754  		Nonce:    web3hex.Encoder.Uint64(tx.Input.Sequence),
   755  		Gas:      web3hex.Encoder.Uint64(tx.GasLimit),
   756  		GasPrice: web3hex.Encoder.Uint64(tx.GasPrice),
   757  		Data:     web3hex.Encoder.Bytes(tx.Data),
   758  	}
   759  
   760  	if block != nil {
   761  		// may be pending
   762  		transaction.BlockHash = hexKeccak(block.Hash().Bytes())
   763  		transaction.Hash = web3hex.Encoder.Bytes(hash)
   764  		transaction.BlockNumber = web3hex.Encoder.Uint64(uint64(block.Height))
   765  		transaction.TransactionIndex = hexZero
   766  	}
   767  
   768  	if tx.Address != nil {
   769  		transaction.To = web3hex.Encoder.Bytes(tx.Address.Bytes())
   770  	} else {
   771  		transaction.To = pending
   772  	}
   773  
   774  	return transaction
   775  }
   776  
   777  func (srv *EthService) getHeightByWord(height string) (uint64, bool) {
   778  	switch height {
   779  	case "earliest":
   780  		return 0, true
   781  	case "latest", "pending":
   782  		return srv.blockchain.LastBlockHeight(), true
   783  		// TODO: pending state/transactions
   784  	default:
   785  		return 0, false
   786  	}
   787  }
   788  
   789  func getHeightByNumber(height string) (uint64, error) {
   790  	d := new(web3hex.Decoder)
   791  	return d.Uint64(height), d.Err()
   792  }
   793  
   794  func (srv *EthService) getHeightByWordOrNumber(i string) (uint64, error) {
   795  	var err error
   796  	height, ok := srv.getHeightByWord(i)
   797  	if !ok {
   798  		height, err = getHeightByNumber(i)
   799  		if err != nil {
   800  			return 0, err
   801  		}
   802  	}
   803  	return height, nil
   804  }
   805  
   806  // EthSendTransaction constructs, signs and broadcasts a tx from the local node
   807  // Note: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1767.md#rationale
   808  func (srv *EthService) EthSendTransaction(req *EthSendTransactionParams) (*EthSendTransactionResult, error) {
   809  	tx := &payload.CallTx{
   810  		Input: new(payload.TxInput),
   811  	}
   812  
   813  	var err error
   814  	d := new(web3hex.Decoder)
   815  	if from := req.Transaction.From; from != "" {
   816  		tx.Input.Address = d.Address(from)
   817  		if d.Err() != nil {
   818  			return nil, fmt.Errorf("failed to parse from address: %v", d.Err())
   819  		}
   820  	} else {
   821  		return nil, fmt.Errorf("no from address specified")
   822  	}
   823  
   824  	if value := req.Transaction.Value; value != "" {
   825  		tx.Input.Amount, err = strconv.ParseUint(value, 0, 64)
   826  		if err != nil {
   827  			return nil, fmt.Errorf("failed to parse amount: %v", err)
   828  		}
   829  	}
   830  
   831  	if to := req.Transaction.To; to != "" {
   832  		addr := d.Address(to)
   833  		if d.Err() != nil {
   834  			return nil, fmt.Errorf("failed to parse to address: %v", d.Err())
   835  		}
   836  		tx.Address = &addr
   837  	}
   838  
   839  	// gas provided for the transaction execution
   840  	if gasLimit := req.Transaction.Gas; gasLimit != "" {
   841  		tx.GasLimit, err = strconv.ParseUint(gasLimit, 0, 64)
   842  		if err != nil {
   843  			return nil, fmt.Errorf("failed to parse gasLimit: %v", err)
   844  		}
   845  	}
   846  
   847  	if gasPrice := req.Transaction.GasPrice; gasPrice != "" {
   848  		tx.GasPrice, err = strconv.ParseUint(gasPrice, 0, 64)
   849  		if err != nil {
   850  			return nil, fmt.Errorf("failed to parse gasPrice: %v", err)
   851  		}
   852  	}
   853  
   854  	if data := req.Transaction.Data; data != "" {
   855  		bs := d.Bytes(data)
   856  		if d.Err() != nil {
   857  			return nil, fmt.Errorf("failed to parse data: %v", d.Err())
   858  		}
   859  		tx.Data = bs
   860  	}
   861  
   862  	txEnv := txs.Enclose(srv.blockchain.ChainID(), tx)
   863  
   864  	ctx := context.Background()
   865  	txe, err := srv.trans.BroadcastTxSync(ctx, txEnv)
   866  	if err != nil {
   867  		return nil, err
   868  	} else if txe.Exception != nil {
   869  		return nil, txe.Exception.AsError()
   870  	}
   871  
   872  	return &EthSendTransactionResult{
   873  		TransactionHash: web3hex.Encoder.Bytes(txe.GetTxHash().Bytes()),
   874  	}, nil
   875  }
   876  
   877  // EthAccounts returns all accounts signable from the local node
   878  func (srv *EthService) EthAccounts() (*EthAccountsResult, error) {
   879  	addresses, err := srv.keyStore.GetAllAddresses()
   880  	if err != nil {
   881  		return nil, err
   882  	}
   883  
   884  	addrs := make([]string, 0, len(addresses))
   885  	for _, addr := range addresses {
   886  		data, err := hex.DecodeString(addr)
   887  		if err != nil {
   888  			return nil, fmt.Errorf("could not decode address %s", addr)
   889  		}
   890  		key, err := srv.keyStore.GetKey("", data)
   891  		if err != nil {
   892  			return nil, fmt.Errorf("could not retrieve key for %s", addr)
   893  		} else if key.CurveType != crypto.CurveTypeSecp256k1 {
   894  			// we only want ethereum keys
   895  			continue
   896  		}
   897  		// TODO: only return accounts that exist in current chain
   898  		addrs = append(addrs, web3hex.Encoder.Bytes(key.Address.Bytes()))
   899  	}
   900  
   901  	return &EthAccountsResult{
   902  		Addresses: addrs,
   903  	}, nil
   904  }
   905  
   906  // EthSign: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
   907  func (srv *EthService) EthSign(req *EthSignParams) (*EthSignResult, error) {
   908  	d := new(web3hex.Decoder)
   909  	to := d.Address(req.Address)
   910  	signer, err := keys.AddressableSigner(srv.keyClient, to)
   911  	if err != nil {
   912  		return nil, err
   913  	}
   914  
   915  	data := d.Bytes(req.Bytes)
   916  	if d.Err() != nil {
   917  		return nil, d.Err()
   918  	}
   919  
   920  	msg := append([]byte{0x19}, []byte("Ethereum Signed Message:\n")...)
   921  	msg = append(msg, byte(len(data)))
   922  	msg = append(msg, data...)
   923  
   924  	sig, err := signer.Sign(crypto.Keccak256(msg))
   925  	if err != nil {
   926  		return nil, err
   927  	}
   928  
   929  	return &EthSignResult{
   930  		Signature: web3hex.Encoder.Bytes(sig.RawBytes()),
   931  	}, nil
   932  }
   933  
   934  // N / A
   935  
   936  func (srv *EthService) EthUninstallFilter(*EthUninstallFilterParams) (*EthUninstallFilterResult, error) {
   937  	return nil, ErrNotFound
   938  }
   939  
   940  func (srv *EthService) EthSubmitHashrate(req *EthSubmitHashrateParams) (*EthSubmitHashrateResult, error) {
   941  	return nil, ErrNotFound
   942  }
   943  
   944  func (srv *EthService) EthSubmitWork(*EthSubmitWorkParams) (*EthSubmitWorkResult, error) {
   945  	return nil, ErrNotFound
   946  }
   947  
   948  func (srv *EthService) EthNewBlockFilter() (*EthNewBlockFilterResult, error) {
   949  	return nil, ErrNotFound
   950  }
   951  
   952  func (srv *EthService) EthNewFilter(req *EthNewFilterParams) (*EthNewFilterResult, error) {
   953  	return nil, ErrNotFound
   954  }
   955  
   956  func (srv *EthService) EthNewPendingTransactionFilter() (*EthNewPendingTransactionFilterResult, error) {
   957  	return nil, ErrNotFound
   958  }
   959  
   960  func (srv *EthService) EthGetUncleByBlockHashAndIndex(req *EthGetUncleByBlockHashAndIndexParams) (*EthGetUncleByBlockHashAndIndexResult, error) {
   961  	return nil, ErrNotFound
   962  }
   963  
   964  func (srv *EthService) EthGetUncleByBlockNumberAndIndex(req *EthGetUncleByBlockNumberAndIndexParams) (*EthGetUncleByBlockNumberAndIndexResult, error) {
   965  	return nil, ErrNotFound
   966  }
   967  
   968  func (srv *EthService) EthGetUncleCountByBlockHash(req *EthGetUncleCountByBlockHashParams) (*EthGetUncleCountByBlockHashResult, error) {
   969  	return nil, ErrNotFound
   970  }
   971  
   972  func (srv *EthService) EthGetUncleCountByBlockNumber(req *EthGetUncleCountByBlockNumberParams) (*EthGetUncleCountByBlockNumberResult, error) {
   973  	return nil, ErrNotFound
   974  }
   975  
   976  func (srv *EthService) EthGetProof(req *EthGetProofParams) (*EthGetProofResult, error) {
   977  	return nil, ErrNotFound
   978  }
   979  
   980  func (srv *EthService) EthGetWork() (*EthGetWorkResult, error) {
   981  	return nil, ErrNotFound
   982  }
   983  
   984  func (srv *EthService) EthGetFilterChanges(req *EthGetFilterChangesParams) (*EthGetFilterChangesResult, error) {
   985  	return nil, ErrNotFound
   986  }
   987  
   988  func (srv *EthService) EthGetFilterLogs(req *EthGetFilterLogsParams) (*EthGetFilterLogsResult, error) {
   989  	return nil, ErrNotFound
   990  }
   991  
   992  func (srv *EthService) EthCoinbase() (*EthCoinbaseResult, error) {
   993  	return nil, ErrNotFound
   994  }
   995  
   996  func (srv *EthService) EthGetLogs(req *EthGetLogsParams) (*EthGetLogsResult, error) {
   997  	return nil, ErrNotFound
   998  }