restructured eth rpc API
This commit is contained in:
		
				
					committed by
					
						
						Bas van Kervel
					
				
			
			
				
	
			
			
			
						parent
						
							6609d45ef4
						
					
				
				
					commit
					2f55a1d798
				
			
							
								
								
									
										12
									
								
								rpc/api/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								rpc/api/api.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import "github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
 | 
			
		||||
// Ethereum RPC API interface
 | 
			
		||||
type EthereumApi interface {
 | 
			
		||||
	// Execute the given request and returns the response or an error
 | 
			
		||||
	Execute(*shared.Request) (interface{}, error)
 | 
			
		||||
 | 
			
		||||
	// List of supported RCP methods this API provides
 | 
			
		||||
	Methods() []string
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								rpc/api/api_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								rpc/api/api_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/codec"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestParseApiString(t *testing.T) {
 | 
			
		||||
	apis, err := ParseApiString("", codec.JSON, nil, nil)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Errorf("Expected an err from parsing empty API string but got nil")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(apis) != 0 {
 | 
			
		||||
		t.Errorf("Expected 0 apis from empty API string")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apis, err = ParseApiString("eth", codec.JSON, nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Expected nil err from parsing empty API string but got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(apis) != 1 {
 | 
			
		||||
		t.Errorf("Expected 1 apis but got %d - %v", apis, apis)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apis, err = ParseApiString("eth,eth", codec.JSON, nil, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Expected nil err from parsing empty API string but got \"%v\"", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(apis) != 2 {
 | 
			
		||||
		t.Errorf("Expected 2 apis but got %d - %v", apis, apis)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apis, err = ParseApiString("eth,invalid", codec.JSON, nil, nil)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Errorf("Expected an err but got no err")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										523
									
								
								rpc/api/eth.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										523
									
								
								rpc/api/eth.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,523 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"math/big"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/common"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/codec"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/xeth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// eth api provider
 | 
			
		||||
// See https://github.com/ethereum/wiki/wiki/JSON-RPC
 | 
			
		||||
type EthApi struct {
 | 
			
		||||
	xeth    *xeth.XEth
 | 
			
		||||
	methods map[string]ethhandler
 | 
			
		||||
	codec   codec.ApiCoder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// eth callback handler
 | 
			
		||||
type ethhandler func(*EthApi, *shared.Request) (interface{}, error)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ethMapping = map[string]ethhandler{
 | 
			
		||||
		"eth_accounts":                          (*EthApi).Accounts,
 | 
			
		||||
		"eth_blockNumber":                       (*EthApi).BlockNumber,
 | 
			
		||||
		"eth_getBalance":                        (*EthApi).GetBalance,
 | 
			
		||||
		"eth_protocolVersion":                   (*EthApi).ProtocolVersion,
 | 
			
		||||
		"eth_coinbase":                          (*EthApi).Coinbase,
 | 
			
		||||
		"eth_mining":                            (*EthApi).IsMining,
 | 
			
		||||
		"eth_gasPrice":                          (*EthApi).GasPrice,
 | 
			
		||||
		"eth_getStorage":                        (*EthApi).GetStorage,
 | 
			
		||||
		"eth_storageAt":                         (*EthApi).GetStorage,
 | 
			
		||||
		"eth_getStorageAt":                      (*EthApi).GetStorageAt,
 | 
			
		||||
		"eth_getTransactionCount":               (*EthApi).GetTransactionCount,
 | 
			
		||||
		"eth_getBlockTransactionCountByHash":    (*EthApi).GetBlockTransactionCountByHash,
 | 
			
		||||
		"eth_getBlockTransactionCountByNumber":  (*EthApi).GetBlockTransactionCountByNumber,
 | 
			
		||||
		"eth_getUncleCountByBlockHash":          (*EthApi).GetUncleCountByBlockHash,
 | 
			
		||||
		"eth_getUncleCountByBlockNumber":        (*EthApi).GetUncleCountByBlockNumber,
 | 
			
		||||
		"eth_getData":                           (*EthApi).GetData,
 | 
			
		||||
		"eth_getCode":                           (*EthApi).GetData,
 | 
			
		||||
		"eth_sign":                              (*EthApi).Sign,
 | 
			
		||||
		"eth_sendTransaction":                   (*EthApi).SendTransaction,
 | 
			
		||||
		"eth_transact":                          (*EthApi).SendTransaction,
 | 
			
		||||
		"eth_estimateGas":                       (*EthApi).EstimateGas,
 | 
			
		||||
		"eth_call":                              (*EthApi).Call,
 | 
			
		||||
		"eth_flush":                             (*EthApi).Flush,
 | 
			
		||||
		"eth_getBlockByHash":                    (*EthApi).GetBlockByHash,
 | 
			
		||||
		"eth_getBlockByNumber":                  (*EthApi).GetBlockByNumber,
 | 
			
		||||
		"eth_getTransactionByHash":              (*EthApi).GetTransactionByHash,
 | 
			
		||||
		"eth_getTransactionByBlockHashAndIndex": (*EthApi).GetTransactionByBlockHashAndIndex,
 | 
			
		||||
		"eth_getUncleByBlockHashAndIndex":       (*EthApi).GetUncleByBlockHashAndIndex,
 | 
			
		||||
		"eth_getUncleByBlockNumberAndIndex":     (*EthApi).GetUncleByBlockNumberAndIndex,
 | 
			
		||||
		"eth_getCompilers":                      (*EthApi).GetCompilers,
 | 
			
		||||
		"eth_compileSolidity":                   (*EthApi).CompileSolidity,
 | 
			
		||||
		"eth_newFilter":                         (*EthApi).NewFilter,
 | 
			
		||||
		"eth_newBlockFilter":                    (*EthApi).NewBlockFilter,
 | 
			
		||||
		"eth_newPendingTransactionFilter":       (*EthApi).NewPendingTransactionFilter,
 | 
			
		||||
		"eth_uninstallFilter":                   (*EthApi).UninstallFilter,
 | 
			
		||||
		"eth_getFilterChanges":                  (*EthApi).GetFilterChanges,
 | 
			
		||||
		"eth_getFilterLogs":                     (*EthApi).GetFilterLogs,
 | 
			
		||||
		"eth_getLogs":                           (*EthApi).GetLogs,
 | 
			
		||||
		"eth_hashrate":                          (*EthApi).Hashrate,
 | 
			
		||||
		"eth_getWork":                           (*EthApi).GetWork,
 | 
			
		||||
		"eth_submitWork":                        (*EthApi).SubmitWork,
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// create new EthApi instance
 | 
			
		||||
func NewEthApi(xeth *xeth.XEth, codec codec.Codec) *EthApi {
 | 
			
		||||
	return &EthApi{xeth, ethMapping, codec.New(nil)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// collection with supported methods
 | 
			
		||||
func (self *EthApi) Methods() []string {
 | 
			
		||||
	methods := make([]string, len(self.methods))
 | 
			
		||||
	i := 0
 | 
			
		||||
	for k := range self.methods {
 | 
			
		||||
		methods[i] = k
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	return methods
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Execute given request
 | 
			
		||||
func (self *EthApi) Execute(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	if callback, ok := self.methods[req.Method]; ok {
 | 
			
		||||
		return callback(self, req)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, shared.NewNotImplementedError(req.Method)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Accounts(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.xeth.Accounts(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Hashrate(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return newHexNum(self.xeth.HashRate()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) BlockNumber(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.xeth.CurrentBlock().Number(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetBalance(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetBalanceArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.xeth.AtStateNum(args.BlockNumber).BalanceAt(args.Address), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) ProtocolVersion(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.xeth.EthVersion(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Coinbase(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return newHexData(self.xeth.Coinbase()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) IsMining(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.xeth.IsMining(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GasPrice(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return newHexNum(xeth.DefaultGasPrice().Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetStorage(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetStorageArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.xeth.AtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetStorageAt(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetStorageAtArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.xeth.AtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetTransactionCount(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetTxCountArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	count := self.xeth.AtStateNum(args.BlockNumber).TxCountAt(args.Address)
 | 
			
		||||
	return newHexNum(big.NewInt(int64(count)).Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetBlockTransactionCountByHash(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(HashArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := NewBlockRes(self.xeth.EthBlockByHash(args.Hash), false)
 | 
			
		||||
	if block == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return newHexNum(big.NewInt(int64(len(block.Transactions))).Bytes()), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetBlockTransactionCountByNumber(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockNumArg)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := NewBlockRes(self.xeth.EthBlockByNumber(args.BlockNumber), false)
 | 
			
		||||
	if block == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return newHexNum(big.NewInt(int64(len(block.Transactions))).Bytes()), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetUncleCountByBlockHash(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(HashArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByHash(args.Hash)
 | 
			
		||||
	br := NewBlockRes(block, false)
 | 
			
		||||
	if br == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return newHexNum(big.NewInt(int64(len(br.Uncles))).Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetUncleCountByBlockNumber(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockNumArg)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByNumber(args.BlockNumber)
 | 
			
		||||
	br := NewBlockRes(block, false)
 | 
			
		||||
	if br == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return newHexNum(big.NewInt(int64(len(br.Uncles))).Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetData(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetDataArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	v := self.xeth.AtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
 | 
			
		||||
	return newHexData(v), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Sign(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(NewSignArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	v, err := self.xeth.Sign(args.From, args.Data, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return v, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) SendTransaction(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(NewTxArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// nonce may be nil ("guess" mode)
 | 
			
		||||
	var nonce string
 | 
			
		||||
	if args.Nonce != nil {
 | 
			
		||||
		nonce = args.Nonce.String()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v, err := self.xeth.Transact(args.From, args.To, nonce, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return v, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) EstimateGas(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	_, gas, err := self.doCall(req.Params)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO unwrap the parent method's ToHex call
 | 
			
		||||
	if len(gas) == 0 {
 | 
			
		||||
		return newHexNum(0), nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return newHexNum(gas), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Call(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	v, _, err := self.doCall(req.Params)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO unwrap the parent method's ToHex call
 | 
			
		||||
	if v == "0x0" {
 | 
			
		||||
		return newHexData([]byte{}), nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return newHexData(common.FromHex(v)), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) Flush(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return nil, shared.NewNotImplementedError(req.Method)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) doCall(params json.RawMessage) (string, string, error) {
 | 
			
		||||
	args := new(CallArgs)
 | 
			
		||||
	if err := self.codec.Decode(params, &args); err != nil {
 | 
			
		||||
		return "", "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.xeth.AtStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetBlockByHash(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetBlockByHashArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByHash(args.BlockHash)
 | 
			
		||||
	return NewBlockRes(block, args.IncludeTxs), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetBlockByNumber(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(GetBlockByNumberArgs)
 | 
			
		||||
	if err := json.Unmarshal(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByNumber(args.BlockNumber)
 | 
			
		||||
	br := NewBlockRes(block, args.IncludeTxs)
 | 
			
		||||
	// If request was for "pending", nil nonsensical fields
 | 
			
		||||
	if args.BlockNumber == -2 {
 | 
			
		||||
		br.BlockHash = nil
 | 
			
		||||
		br.BlockNumber = nil
 | 
			
		||||
		br.Miner = nil
 | 
			
		||||
		br.Nonce = nil
 | 
			
		||||
		br.LogsBloom = nil
 | 
			
		||||
	}
 | 
			
		||||
	return br, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetTransactionByHash(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(HashArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash)
 | 
			
		||||
	if tx != nil {
 | 
			
		||||
		v := NewTransactionRes(tx)
 | 
			
		||||
		// if the blockhash is 0, assume this is a pending transaction
 | 
			
		||||
		if bytes.Compare(bhash.Bytes(), bytes.Repeat([]byte{0}, 32)) != 0 {
 | 
			
		||||
			v.BlockHash = newHexData(bhash)
 | 
			
		||||
			v.BlockNumber = newHexNum(bnum)
 | 
			
		||||
			v.TxIndex = newHexNum(txi)
 | 
			
		||||
		}
 | 
			
		||||
		return v, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetTransactionByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(HashIndexArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByHash(args.Hash)
 | 
			
		||||
	br := NewBlockRes(block, true)
 | 
			
		||||
	if br == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if args.Index >= int64(len(br.Transactions)) || args.Index < 0 {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return br.Transactions[args.Index], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetTransactionByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockNumIndexArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByNumber(args.BlockNumber)
 | 
			
		||||
	v := NewBlockRes(block, true)
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if args.Index >= int64(len(v.Transactions)) || args.Index < 0 {
 | 
			
		||||
		// return NewValidationError("Index", "does not exist")
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return v.Transactions[args.Index], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetUncleByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(HashIndexArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	br := NewBlockRes(self.xeth.EthBlockByHash(args.Hash), false)
 | 
			
		||||
	if br == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if args.Index >= int64(len(br.Uncles)) || args.Index < 0 {
 | 
			
		||||
		// return NewValidationError("Index", "does not exist")
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return br.Uncles[args.Index], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetUncleByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockNumIndexArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block := self.xeth.EthBlockByNumber(args.BlockNumber)
 | 
			
		||||
	v := NewBlockRes(block, true)
 | 
			
		||||
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if args.Index >= int64(len(v.Uncles)) || args.Index < 0 {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return v.Uncles[args.Index], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetCompilers(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	var lang string
 | 
			
		||||
	if solc, _ := self.xeth.Solc(); solc != nil {
 | 
			
		||||
		lang = "Solidity"
 | 
			
		||||
	}
 | 
			
		||||
	c := []string{lang}
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) CompileSolidity(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	solc, _ := self.xeth.Solc()
 | 
			
		||||
	if solc == nil {
 | 
			
		||||
		return nil, shared.NewNotAvailableError(req.Method, "solc (solidity compiler) not found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args := new(SourceArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	contracts, err := solc.Compile(args.Source)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return contracts, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) NewFilter(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockFilterArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	id := self.xeth.NewLogFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
 | 
			
		||||
	return newHexNum(big.NewInt(int64(id)).Bytes()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) NewBlockFilter(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return newHexNum(self.xeth.NewBlockFilter()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) NewPendingTransactionFilter(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return newHexNum(self.xeth.NewTransactionFilter()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) UninstallFilter(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(FilterIdArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return self.xeth.UninstallFilter(args.Id), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetFilterChanges(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(FilterIdArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch self.xeth.GetFilterType(args.Id) {
 | 
			
		||||
	case xeth.BlockFilterTy:
 | 
			
		||||
		return NewHashesRes(self.xeth.BlockFilterChanged(args.Id)), nil
 | 
			
		||||
	case xeth.TransactionFilterTy:
 | 
			
		||||
		return NewHashesRes(self.xeth.TransactionFilterChanged(args.Id)), nil
 | 
			
		||||
	case xeth.LogFilterTy:
 | 
			
		||||
		return NewLogsRes(self.xeth.LogFilterChanged(args.Id)), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return []string{}, nil // reply empty string slice
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetFilterLogs(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(FilterIdArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewLogsRes(self.xeth.Logs(args.Id)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetLogs(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(BlockFilterArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return NewLogsRes(self.xeth.AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) GetWork(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	self.xeth.SetMining(true, 0)
 | 
			
		||||
	return self.xeth.RemoteMining().GetWork(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *EthApi) SubmitWork(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	args := new(SubmitWorkArgs)
 | 
			
		||||
	if err := self.codec.Decode(req.Params, &args); err != nil {
 | 
			
		||||
		return nil, shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return self.xeth.RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header)), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										835
									
								
								rpc/api/eth_args.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										835
									
								
								rpc/api/eth_args.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,835 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/big"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/common"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/core/state"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	defaultLogLimit  = 100
 | 
			
		||||
	defaultLogOffset = 0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type GetBalanceArgs struct {
 | 
			
		||||
	Address     string
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("address", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Address = addstr
 | 
			
		||||
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetStorageArgs struct {
 | 
			
		||||
	Address     string
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("address", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Address = addstr
 | 
			
		||||
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetStorageAtArgs struct {
 | 
			
		||||
	Address     string
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
	Key         string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 2 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("address", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Address = addstr
 | 
			
		||||
 | 
			
		||||
	keystr, ok := obj[1].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("key", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Key = keystr
 | 
			
		||||
 | 
			
		||||
	if len(obj) > 2 {
 | 
			
		||||
		if err := blockHeight(obj[2], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetTxCountArgs struct {
 | 
			
		||||
	Address     string
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("address", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Address = addstr
 | 
			
		||||
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HashArgs struct {
 | 
			
		||||
	Hash string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *HashArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arg0, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("hash", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Hash = arg0
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BlockNumArg struct {
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *BlockNumArg) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetDataArgs struct {
 | 
			
		||||
	Address     string
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("address", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Address = addstr
 | 
			
		||||
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NewSignArgs struct {
 | 
			
		||||
	From string
 | 
			
		||||
	Data string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *NewSignArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []json.RawMessage
 | 
			
		||||
	var ext struct {
 | 
			
		||||
		From string
 | 
			
		||||
		Data string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode byte slice to array of RawMessages
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for sufficient params
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode 0th RawMessage to temporary struct
 | 
			
		||||
	if err := json.Unmarshal(obj[0], &ext); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ext.From) == 0 {
 | 
			
		||||
		return shared.NewValidationError("from", "is required")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ext.Data) == 0 {
 | 
			
		||||
		return shared.NewValidationError("data", "is required")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.From = ext.From
 | 
			
		||||
	args.Data = ext.Data
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NewTxArgs struct {
 | 
			
		||||
	From     string
 | 
			
		||||
	To       string
 | 
			
		||||
	Nonce    *big.Int
 | 
			
		||||
	Value    *big.Int
 | 
			
		||||
	Gas      *big.Int
 | 
			
		||||
	GasPrice *big.Int
 | 
			
		||||
	Data     string
 | 
			
		||||
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []json.RawMessage
 | 
			
		||||
	var ext struct {
 | 
			
		||||
		From     string
 | 
			
		||||
		To       string
 | 
			
		||||
		Nonce    interface{}
 | 
			
		||||
		Value    interface{}
 | 
			
		||||
		Gas      interface{}
 | 
			
		||||
		GasPrice interface{}
 | 
			
		||||
		Data     string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode byte slice to array of RawMessages
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for sufficient params
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode 0th RawMessage to temporary struct
 | 
			
		||||
	if err := json.Unmarshal(obj[0], &ext); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ext.From) == 0 {
 | 
			
		||||
		return shared.NewValidationError("from", "is required")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.From = ext.From
 | 
			
		||||
	args.To = ext.To
 | 
			
		||||
	args.Data = ext.Data
 | 
			
		||||
 | 
			
		||||
	var num *big.Int
 | 
			
		||||
	if ext.Nonce != nil {
 | 
			
		||||
		num, err = numString(ext.Nonce)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Nonce = num
 | 
			
		||||
 | 
			
		||||
	if ext.Value == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		num, err = numString(ext.Value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Value = num
 | 
			
		||||
 | 
			
		||||
	num = nil
 | 
			
		||||
	if ext.Gas == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		if num, err = numString(ext.Gas); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Gas = num
 | 
			
		||||
 | 
			
		||||
	num = nil
 | 
			
		||||
	if ext.GasPrice == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		if num, err = numString(ext.GasPrice); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.GasPrice = num
 | 
			
		||||
 | 
			
		||||
	// Check for optional BlockNumber param
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SourceArgs struct {
 | 
			
		||||
	Source string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *SourceArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arg0, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("source code", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Source = arg0
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CallArgs struct {
 | 
			
		||||
	From     string
 | 
			
		||||
	To       string
 | 
			
		||||
	Value    *big.Int
 | 
			
		||||
	Gas      *big.Int
 | 
			
		||||
	GasPrice *big.Int
 | 
			
		||||
	Data     string
 | 
			
		||||
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []json.RawMessage
 | 
			
		||||
	var ext struct {
 | 
			
		||||
		From     string
 | 
			
		||||
		To       string
 | 
			
		||||
		Value    interface{}
 | 
			
		||||
		Gas      interface{}
 | 
			
		||||
		GasPrice interface{}
 | 
			
		||||
		Data     string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode byte slice to array of RawMessages
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for sufficient params
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode 0th RawMessage to temporary struct
 | 
			
		||||
	if err := json.Unmarshal(obj[0], &ext); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.From = ext.From
 | 
			
		||||
 | 
			
		||||
	if len(ext.To) == 0 {
 | 
			
		||||
		return shared.NewValidationError("to", "is required")
 | 
			
		||||
	}
 | 
			
		||||
	args.To = ext.To
 | 
			
		||||
 | 
			
		||||
	var num *big.Int
 | 
			
		||||
	if ext.Value == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		if num, err = numString(ext.Value); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Value = num
 | 
			
		||||
 | 
			
		||||
	if ext.Gas == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		if num, err = numString(ext.Gas); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Gas = num
 | 
			
		||||
 | 
			
		||||
	if ext.GasPrice == nil {
 | 
			
		||||
		num = big.NewInt(0)
 | 
			
		||||
	} else {
 | 
			
		||||
		if num, err = numString(ext.GasPrice); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.GasPrice = num
 | 
			
		||||
 | 
			
		||||
	args.Data = ext.Data
 | 
			
		||||
 | 
			
		||||
	// Check for optional BlockNumber param
 | 
			
		||||
	if len(obj) > 1 {
 | 
			
		||||
		if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		args.BlockNumber = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HashIndexArgs struct {
 | 
			
		||||
	Hash  string
 | 
			
		||||
	Index int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 2 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arg0, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("hash", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Hash = arg0
 | 
			
		||||
 | 
			
		||||
	arg1, ok := obj[1].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("index", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.Index = common.Big(arg1).Int64()
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BlockNumIndexArgs struct {
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
	Index       int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 2 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var arg1 *big.Int
 | 
			
		||||
	if arg1, err = numString(obj[1]); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	args.Index = arg1.Int64()
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetBlockByHashArgs struct {
 | 
			
		||||
	BlockHash  string
 | 
			
		||||
	IncludeTxs bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 2 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	argstr, ok := obj[0].(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("blockHash", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
	args.BlockHash = argstr
 | 
			
		||||
 | 
			
		||||
	args.IncludeTxs = obj[1].(bool)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GetBlockByNumberArgs struct {
 | 
			
		||||
	BlockNumber int64
 | 
			
		||||
	IncludeTxs  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 2 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.IncludeTxs = obj[1].(bool)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BlockFilterArgs struct {
 | 
			
		||||
	Earliest int64
 | 
			
		||||
	Latest   int64
 | 
			
		||||
	Address  []string
 | 
			
		||||
	Topics   [][]string
 | 
			
		||||
	Skip     int
 | 
			
		||||
	Max      int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []struct {
 | 
			
		||||
		FromBlock interface{} `json:"fromBlock"`
 | 
			
		||||
		ToBlock   interface{} `json:"toBlock"`
 | 
			
		||||
		Limit     interface{} `json:"limit"`
 | 
			
		||||
		Offset    interface{} `json:"offset"`
 | 
			
		||||
		Address   interface{} `json:"address"`
 | 
			
		||||
		Topics    interface{} `json:"topics"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// args.Earliest, err = toNumber(obj[0].ToBlock)
 | 
			
		||||
	// if err != nil {
 | 
			
		||||
	// 	return shared.NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
 | 
			
		||||
	// }
 | 
			
		||||
	// args.Latest, err = toNumber(obj[0].FromBlock)
 | 
			
		||||
	// if err != nil {
 | 
			
		||||
	// 	return shared.NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
 | 
			
		||||
 | 
			
		||||
	var num int64
 | 
			
		||||
	var numBig *big.Int
 | 
			
		||||
 | 
			
		||||
	// if blank then latest
 | 
			
		||||
	if obj[0].FromBlock == nil {
 | 
			
		||||
		num = -1
 | 
			
		||||
	} else {
 | 
			
		||||
		if err := blockHeight(obj[0].FromBlock, &num); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// if -2 or other "silly" number, use latest
 | 
			
		||||
	if num < 0 {
 | 
			
		||||
		args.Earliest = -1 //latest block
 | 
			
		||||
	} else {
 | 
			
		||||
		args.Earliest = num
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if blank than latest
 | 
			
		||||
	if obj[0].ToBlock == nil {
 | 
			
		||||
		num = -1
 | 
			
		||||
	} else {
 | 
			
		||||
		if err := blockHeight(obj[0].ToBlock, &num); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Latest = num
 | 
			
		||||
 | 
			
		||||
	if obj[0].Limit == nil {
 | 
			
		||||
		numBig = big.NewInt(defaultLogLimit)
 | 
			
		||||
	} else {
 | 
			
		||||
		if numBig, err = numString(obj[0].Limit); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Max = int(numBig.Int64())
 | 
			
		||||
 | 
			
		||||
	if obj[0].Offset == nil {
 | 
			
		||||
		numBig = big.NewInt(defaultLogOffset)
 | 
			
		||||
	} else {
 | 
			
		||||
		if numBig, err = numString(obj[0].Offset); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.Skip = int(numBig.Int64())
 | 
			
		||||
 | 
			
		||||
	if obj[0].Address != nil {
 | 
			
		||||
		marg, ok := obj[0].Address.([]interface{})
 | 
			
		||||
		if ok {
 | 
			
		||||
			v := make([]string, len(marg))
 | 
			
		||||
			for i, arg := range marg {
 | 
			
		||||
				argstr, ok := arg.(string)
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return shared.NewInvalidTypeError(fmt.Sprintf("address[%d]", i), "is not a string")
 | 
			
		||||
				}
 | 
			
		||||
				v[i] = argstr
 | 
			
		||||
			}
 | 
			
		||||
			args.Address = v
 | 
			
		||||
		} else {
 | 
			
		||||
			argstr, ok := obj[0].Address.(string)
 | 
			
		||||
			if ok {
 | 
			
		||||
				v := make([]string, 1)
 | 
			
		||||
				v[0] = argstr
 | 
			
		||||
				args.Address = v
 | 
			
		||||
			} else {
 | 
			
		||||
				return shared.NewInvalidTypeError("address", "is not a string or array")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if obj[0].Topics != nil {
 | 
			
		||||
		other, ok := obj[0].Topics.([]interface{})
 | 
			
		||||
		if ok {
 | 
			
		||||
			topicdbl := make([][]string, len(other))
 | 
			
		||||
			for i, iv := range other {
 | 
			
		||||
				if argstr, ok := iv.(string); ok {
 | 
			
		||||
					// Found a string, push into first element of array
 | 
			
		||||
					topicsgl := make([]string, 1)
 | 
			
		||||
					topicsgl[0] = argstr
 | 
			
		||||
					topicdbl[i] = topicsgl
 | 
			
		||||
				} else if argarray, ok := iv.([]interface{}); ok {
 | 
			
		||||
					// Found an array of other
 | 
			
		||||
					topicdbl[i] = make([]string, len(argarray))
 | 
			
		||||
					for j, jv := range argarray {
 | 
			
		||||
						if v, ok := jv.(string); ok {
 | 
			
		||||
							topicdbl[i][j] = v
 | 
			
		||||
						} else if jv == nil {
 | 
			
		||||
							topicdbl[i][j] = ""
 | 
			
		||||
						} else {
 | 
			
		||||
							return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", i, j), "is not a string")
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else if iv == nil {
 | 
			
		||||
					topicdbl[i] = []string{""}
 | 
			
		||||
				} else {
 | 
			
		||||
					return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d]", i), "not a string or array")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			args.Topics = topicdbl
 | 
			
		||||
			return nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return shared.NewInvalidTypeError("topic", "is not a string or array")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FilterIdArgs struct {
 | 
			
		||||
	Id int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err := json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 1 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var num *big.Int
 | 
			
		||||
	if num, err = numString(obj[0]); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	args.Id = int(num.Int64())
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type LogRes struct {
 | 
			
		||||
	Address          *hexdata   `json:"address"`
 | 
			
		||||
	Topics           []*hexdata `json:"topics"`
 | 
			
		||||
	Data             *hexdata   `json:"data"`
 | 
			
		||||
	BlockNumber      *hexnum    `json:"blockNumber"`
 | 
			
		||||
	LogIndex         *hexnum    `json:"logIndex"`
 | 
			
		||||
	BlockHash        *hexdata   `json:"blockHash"`
 | 
			
		||||
	TransactionHash  *hexdata   `json:"transactionHash"`
 | 
			
		||||
	TransactionIndex *hexnum    `json:"transactionIndex"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewLogRes(log *state.Log) LogRes {
 | 
			
		||||
	var l LogRes
 | 
			
		||||
	l.Topics = make([]*hexdata, len(log.Topics))
 | 
			
		||||
	for j, topic := range log.Topics {
 | 
			
		||||
		l.Topics[j] = newHexData(topic)
 | 
			
		||||
	}
 | 
			
		||||
	l.Address = newHexData(log.Address)
 | 
			
		||||
	l.Data = newHexData(log.Data)
 | 
			
		||||
	l.BlockNumber = newHexNum(log.Number)
 | 
			
		||||
	l.LogIndex = newHexNum(log.Index)
 | 
			
		||||
	l.TransactionHash = newHexData(log.TxHash)
 | 
			
		||||
	l.TransactionIndex = newHexNum(log.TxIndex)
 | 
			
		||||
	l.BlockHash = newHexData(log.BlockHash)
 | 
			
		||||
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewLogsRes(logs state.Logs) (ls []LogRes) {
 | 
			
		||||
	ls = make([]LogRes, len(logs))
 | 
			
		||||
 | 
			
		||||
	for i, log := range logs {
 | 
			
		||||
		ls[i] = NewLogRes(log)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHashesRes(hs []common.Hash) []string {
 | 
			
		||||
	hashes := make([]string, len(hs))
 | 
			
		||||
 | 
			
		||||
	for i, hash := range hs {
 | 
			
		||||
		hashes[i] = hash.Hex()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hashes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SubmitWorkArgs struct {
 | 
			
		||||
	Nonce  uint64
 | 
			
		||||
	Header string
 | 
			
		||||
	Digest string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
 | 
			
		||||
	var obj []interface{}
 | 
			
		||||
	if err = json.Unmarshal(b, &obj); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(obj) < 3 {
 | 
			
		||||
		return shared.NewInsufficientParamsError(len(obj), 3)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var objstr string
 | 
			
		||||
	var ok bool
 | 
			
		||||
	if objstr, ok = obj[0].(string); !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("nonce", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.Nonce = common.String2Big(objstr).Uint64()
 | 
			
		||||
	if objstr, ok = obj[1].(string); !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("header", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.Header = objstr
 | 
			
		||||
 | 
			
		||||
	if objstr, ok = obj[2].(string); !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("digest", "not a string")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args.Digest = objstr
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								rpc/api/eth_js.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								rpc/api/eth_js.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
// JS api provided by web3.js
 | 
			
		||||
							
								
								
									
										460
									
								
								rpc/api/parsing.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								rpc/api/parsing.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,460 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/common"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type hexdata struct {
 | 
			
		||||
	data  []byte
 | 
			
		||||
	isNil bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *hexdata) String() string {
 | 
			
		||||
	return "0x" + common.Bytes2Hex(d.data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *hexdata) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	if d.isNil {
 | 
			
		||||
		return json.Marshal(nil)
 | 
			
		||||
	}
 | 
			
		||||
	return json.Marshal(d.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newHexData(input interface{}) *hexdata {
 | 
			
		||||
	d := new(hexdata)
 | 
			
		||||
 | 
			
		||||
	if input == nil {
 | 
			
		||||
		d.isNil = true
 | 
			
		||||
		return d
 | 
			
		||||
	}
 | 
			
		||||
	switch input := input.(type) {
 | 
			
		||||
	case []byte:
 | 
			
		||||
		d.data = input
 | 
			
		||||
	case common.Hash:
 | 
			
		||||
		d.data = input.Bytes()
 | 
			
		||||
	case *common.Hash:
 | 
			
		||||
		if input == nil {
 | 
			
		||||
			d.isNil = true
 | 
			
		||||
		} else {
 | 
			
		||||
			d.data = input.Bytes()
 | 
			
		||||
		}
 | 
			
		||||
	case common.Address:
 | 
			
		||||
		d.data = input.Bytes()
 | 
			
		||||
	case *common.Address:
 | 
			
		||||
		if input == nil {
 | 
			
		||||
			d.isNil = true
 | 
			
		||||
		} else {
 | 
			
		||||
			d.data = input.Bytes()
 | 
			
		||||
		}
 | 
			
		||||
	case types.Bloom:
 | 
			
		||||
		d.data = input.Bytes()
 | 
			
		||||
	case *types.Bloom:
 | 
			
		||||
		if input == nil {
 | 
			
		||||
			d.isNil = true
 | 
			
		||||
		} else {
 | 
			
		||||
			d.data = input.Bytes()
 | 
			
		||||
		}
 | 
			
		||||
	case *big.Int:
 | 
			
		||||
		if input == nil {
 | 
			
		||||
			d.isNil = true
 | 
			
		||||
		} else {
 | 
			
		||||
			d.data = input.Bytes()
 | 
			
		||||
		}
 | 
			
		||||
	case int64:
 | 
			
		||||
		d.data = big.NewInt(input).Bytes()
 | 
			
		||||
	case uint64:
 | 
			
		||||
		buff := make([]byte, 8)
 | 
			
		||||
		binary.BigEndian.PutUint64(buff, input)
 | 
			
		||||
		d.data = buff
 | 
			
		||||
	case int:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case uint:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case int8:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case uint8:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case int16:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case uint16:
 | 
			
		||||
		buff := make([]byte, 2)
 | 
			
		||||
		binary.BigEndian.PutUint16(buff, input)
 | 
			
		||||
		d.data = buff
 | 
			
		||||
	case int32:
 | 
			
		||||
		d.data = big.NewInt(int64(input)).Bytes()
 | 
			
		||||
	case uint32:
 | 
			
		||||
		buff := make([]byte, 4)
 | 
			
		||||
		binary.BigEndian.PutUint32(buff, input)
 | 
			
		||||
		d.data = buff
 | 
			
		||||
	case string: // hexstring
 | 
			
		||||
		// aaargh ffs TODO: avoid back-and-forth hex encodings where unneeded
 | 
			
		||||
		bytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			d.isNil = true
 | 
			
		||||
		} else {
 | 
			
		||||
			d.data = bytes
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		d.isNil = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type hexnum struct {
 | 
			
		||||
	data  []byte
 | 
			
		||||
	isNil bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *hexnum) String() string {
 | 
			
		||||
	// Get hex string from bytes
 | 
			
		||||
	out := common.Bytes2Hex(d.data)
 | 
			
		||||
	// Trim leading 0s
 | 
			
		||||
	out = strings.TrimLeft(out, "0")
 | 
			
		||||
	// Output "0x0" when value is 0
 | 
			
		||||
	if len(out) == 0 {
 | 
			
		||||
		out = "0"
 | 
			
		||||
	}
 | 
			
		||||
	return "0x" + out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *hexnum) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	if d.isNil {
 | 
			
		||||
		return json.Marshal(nil)
 | 
			
		||||
	}
 | 
			
		||||
	return json.Marshal(d.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newHexNum(input interface{}) *hexnum {
 | 
			
		||||
	d := new(hexnum)
 | 
			
		||||
 | 
			
		||||
	d.data = newHexData(input).data
 | 
			
		||||
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BlockRes struct {
 | 
			
		||||
	fullTx bool
 | 
			
		||||
 | 
			
		||||
	BlockNumber     *hexnum           `json:"number"`
 | 
			
		||||
	BlockHash       *hexdata          `json:"hash"`
 | 
			
		||||
	ParentHash      *hexdata          `json:"parentHash"`
 | 
			
		||||
	Nonce           *hexdata          `json:"nonce"`
 | 
			
		||||
	Sha3Uncles      *hexdata          `json:"sha3Uncles"`
 | 
			
		||||
	LogsBloom       *hexdata          `json:"logsBloom"`
 | 
			
		||||
	TransactionRoot *hexdata          `json:"transactionsRoot"`
 | 
			
		||||
	StateRoot       *hexdata          `json:"stateRoot"`
 | 
			
		||||
	Miner           *hexdata          `json:"miner"`
 | 
			
		||||
	Difficulty      *hexnum           `json:"difficulty"`
 | 
			
		||||
	TotalDifficulty *hexnum           `json:"totalDifficulty"`
 | 
			
		||||
	Size            *hexnum           `json:"size"`
 | 
			
		||||
	ExtraData       *hexdata          `json:"extraData"`
 | 
			
		||||
	GasLimit        *hexnum           `json:"gasLimit"`
 | 
			
		||||
	GasUsed         *hexnum           `json:"gasUsed"`
 | 
			
		||||
	UnixTimestamp   *hexnum           `json:"timestamp"`
 | 
			
		||||
	Transactions    []*TransactionRes `json:"transactions"`
 | 
			
		||||
	Uncles          []*UncleRes       `json:"uncles"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *BlockRes) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	if b.fullTx {
 | 
			
		||||
		var ext struct {
 | 
			
		||||
			BlockNumber     *hexnum           `json:"number"`
 | 
			
		||||
			BlockHash       *hexdata          `json:"hash"`
 | 
			
		||||
			ParentHash      *hexdata          `json:"parentHash"`
 | 
			
		||||
			Nonce           *hexdata          `json:"nonce"`
 | 
			
		||||
			Sha3Uncles      *hexdata          `json:"sha3Uncles"`
 | 
			
		||||
			LogsBloom       *hexdata          `json:"logsBloom"`
 | 
			
		||||
			TransactionRoot *hexdata          `json:"transactionsRoot"`
 | 
			
		||||
			StateRoot       *hexdata          `json:"stateRoot"`
 | 
			
		||||
			Miner           *hexdata          `json:"miner"`
 | 
			
		||||
			Difficulty      *hexnum           `json:"difficulty"`
 | 
			
		||||
			TotalDifficulty *hexnum           `json:"totalDifficulty"`
 | 
			
		||||
			Size            *hexnum           `json:"size"`
 | 
			
		||||
			ExtraData       *hexdata          `json:"extraData"`
 | 
			
		||||
			GasLimit        *hexnum           `json:"gasLimit"`
 | 
			
		||||
			GasUsed         *hexnum           `json:"gasUsed"`
 | 
			
		||||
			UnixTimestamp   *hexnum           `json:"timestamp"`
 | 
			
		||||
			Transactions    []*TransactionRes `json:"transactions"`
 | 
			
		||||
			Uncles          []*hexdata        `json:"uncles"`
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ext.BlockNumber = b.BlockNumber
 | 
			
		||||
		ext.BlockHash = b.BlockHash
 | 
			
		||||
		ext.ParentHash = b.ParentHash
 | 
			
		||||
		ext.Nonce = b.Nonce
 | 
			
		||||
		ext.Sha3Uncles = b.Sha3Uncles
 | 
			
		||||
		ext.LogsBloom = b.LogsBloom
 | 
			
		||||
		ext.TransactionRoot = b.TransactionRoot
 | 
			
		||||
		ext.StateRoot = b.StateRoot
 | 
			
		||||
		ext.Miner = b.Miner
 | 
			
		||||
		ext.Difficulty = b.Difficulty
 | 
			
		||||
		ext.TotalDifficulty = b.TotalDifficulty
 | 
			
		||||
		ext.Size = b.Size
 | 
			
		||||
		ext.ExtraData = b.ExtraData
 | 
			
		||||
		ext.GasLimit = b.GasLimit
 | 
			
		||||
		ext.GasUsed = b.GasUsed
 | 
			
		||||
		ext.UnixTimestamp = b.UnixTimestamp
 | 
			
		||||
		ext.Transactions = b.Transactions
 | 
			
		||||
		ext.Uncles = make([]*hexdata, len(b.Uncles))
 | 
			
		||||
		for i, u := range b.Uncles {
 | 
			
		||||
			ext.Uncles[i] = u.BlockHash
 | 
			
		||||
		}
 | 
			
		||||
		return json.Marshal(ext)
 | 
			
		||||
	} else {
 | 
			
		||||
		var ext struct {
 | 
			
		||||
			BlockNumber     *hexnum    `json:"number"`
 | 
			
		||||
			BlockHash       *hexdata   `json:"hash"`
 | 
			
		||||
			ParentHash      *hexdata   `json:"parentHash"`
 | 
			
		||||
			Nonce           *hexdata   `json:"nonce"`
 | 
			
		||||
			Sha3Uncles      *hexdata   `json:"sha3Uncles"`
 | 
			
		||||
			LogsBloom       *hexdata   `json:"logsBloom"`
 | 
			
		||||
			TransactionRoot *hexdata   `json:"transactionsRoot"`
 | 
			
		||||
			StateRoot       *hexdata   `json:"stateRoot"`
 | 
			
		||||
			Miner           *hexdata   `json:"miner"`
 | 
			
		||||
			Difficulty      *hexnum    `json:"difficulty"`
 | 
			
		||||
			TotalDifficulty *hexnum    `json:"totalDifficulty"`
 | 
			
		||||
			Size            *hexnum    `json:"size"`
 | 
			
		||||
			ExtraData       *hexdata   `json:"extraData"`
 | 
			
		||||
			GasLimit        *hexnum    `json:"gasLimit"`
 | 
			
		||||
			GasUsed         *hexnum    `json:"gasUsed"`
 | 
			
		||||
			UnixTimestamp   *hexnum    `json:"timestamp"`
 | 
			
		||||
			Transactions    []*hexdata `json:"transactions"`
 | 
			
		||||
			Uncles          []*hexdata `json:"uncles"`
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ext.BlockNumber = b.BlockNumber
 | 
			
		||||
		ext.BlockHash = b.BlockHash
 | 
			
		||||
		ext.ParentHash = b.ParentHash
 | 
			
		||||
		ext.Nonce = b.Nonce
 | 
			
		||||
		ext.Sha3Uncles = b.Sha3Uncles
 | 
			
		||||
		ext.LogsBloom = b.LogsBloom
 | 
			
		||||
		ext.TransactionRoot = b.TransactionRoot
 | 
			
		||||
		ext.StateRoot = b.StateRoot
 | 
			
		||||
		ext.Miner = b.Miner
 | 
			
		||||
		ext.Difficulty = b.Difficulty
 | 
			
		||||
		ext.TotalDifficulty = b.TotalDifficulty
 | 
			
		||||
		ext.Size = b.Size
 | 
			
		||||
		ext.ExtraData = b.ExtraData
 | 
			
		||||
		ext.GasLimit = b.GasLimit
 | 
			
		||||
		ext.GasUsed = b.GasUsed
 | 
			
		||||
		ext.UnixTimestamp = b.UnixTimestamp
 | 
			
		||||
		ext.Transactions = make([]*hexdata, len(b.Transactions))
 | 
			
		||||
		for i, tx := range b.Transactions {
 | 
			
		||||
			ext.Transactions[i] = tx.Hash
 | 
			
		||||
		}
 | 
			
		||||
		ext.Uncles = make([]*hexdata, len(b.Uncles))
 | 
			
		||||
		for i, u := range b.Uncles {
 | 
			
		||||
			ext.Uncles[i] = u.BlockHash
 | 
			
		||||
		}
 | 
			
		||||
		return json.Marshal(ext)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
 | 
			
		||||
	if block == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res := new(BlockRes)
 | 
			
		||||
	res.fullTx = fullTx
 | 
			
		||||
	res.BlockNumber = newHexNum(block.Number())
 | 
			
		||||
	res.BlockHash = newHexData(block.Hash())
 | 
			
		||||
	res.ParentHash = newHexData(block.ParentHash())
 | 
			
		||||
	res.Nonce = newHexData(block.Nonce())
 | 
			
		||||
	res.Sha3Uncles = newHexData(block.Header().UncleHash)
 | 
			
		||||
	res.LogsBloom = newHexData(block.Bloom())
 | 
			
		||||
	res.TransactionRoot = newHexData(block.Header().TxHash)
 | 
			
		||||
	res.StateRoot = newHexData(block.Root())
 | 
			
		||||
	res.Miner = newHexData(block.Header().Coinbase)
 | 
			
		||||
	res.Difficulty = newHexNum(block.Difficulty())
 | 
			
		||||
	res.TotalDifficulty = newHexNum(block.Td)
 | 
			
		||||
	res.Size = newHexNum(block.Size().Int64())
 | 
			
		||||
	res.ExtraData = newHexData(block.Header().Extra)
 | 
			
		||||
	res.GasLimit = newHexNum(block.GasLimit())
 | 
			
		||||
	res.GasUsed = newHexNum(block.GasUsed())
 | 
			
		||||
	res.UnixTimestamp = newHexNum(block.Time())
 | 
			
		||||
 | 
			
		||||
	res.Transactions = make([]*TransactionRes, len(block.Transactions()))
 | 
			
		||||
	for i, tx := range block.Transactions() {
 | 
			
		||||
		res.Transactions[i] = NewTransactionRes(tx)
 | 
			
		||||
		res.Transactions[i].BlockHash = res.BlockHash
 | 
			
		||||
		res.Transactions[i].BlockNumber = res.BlockNumber
 | 
			
		||||
		res.Transactions[i].TxIndex = newHexNum(i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res.Uncles = make([]*UncleRes, len(block.Uncles()))
 | 
			
		||||
	for i, uncle := range block.Uncles() {
 | 
			
		||||
		res.Uncles[i] = NewUncleRes(uncle)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TransactionRes struct {
 | 
			
		||||
	Hash        *hexdata `json:"hash"`
 | 
			
		||||
	Nonce       *hexnum  `json:"nonce"`
 | 
			
		||||
	BlockHash   *hexdata `json:"blockHash"`
 | 
			
		||||
	BlockNumber *hexnum  `json:"blockNumber"`
 | 
			
		||||
	TxIndex     *hexnum  `json:"transactionIndex"`
 | 
			
		||||
	From        *hexdata `json:"from"`
 | 
			
		||||
	To          *hexdata `json:"to"`
 | 
			
		||||
	Value       *hexnum  `json:"value"`
 | 
			
		||||
	Gas         *hexnum  `json:"gas"`
 | 
			
		||||
	GasPrice    *hexnum  `json:"gasPrice"`
 | 
			
		||||
	Input       *hexdata `json:"input"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewTransactionRes(tx *types.Transaction) *TransactionRes {
 | 
			
		||||
	if tx == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var v = new(TransactionRes)
 | 
			
		||||
	v.Hash = newHexData(tx.Hash())
 | 
			
		||||
	v.Nonce = newHexNum(tx.Nonce())
 | 
			
		||||
	// v.BlockHash =
 | 
			
		||||
	// v.BlockNumber =
 | 
			
		||||
	// v.TxIndex =
 | 
			
		||||
	from, _ := tx.From()
 | 
			
		||||
	v.From = newHexData(from)
 | 
			
		||||
	v.To = newHexData(tx.To())
 | 
			
		||||
	v.Value = newHexNum(tx.Value())
 | 
			
		||||
	v.Gas = newHexNum(tx.Gas())
 | 
			
		||||
	v.GasPrice = newHexNum(tx.GasPrice())
 | 
			
		||||
	v.Input = newHexData(tx.Data())
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UncleRes struct {
 | 
			
		||||
	BlockNumber     *hexnum  `json:"number"`
 | 
			
		||||
	BlockHash       *hexdata `json:"hash"`
 | 
			
		||||
	ParentHash      *hexdata `json:"parentHash"`
 | 
			
		||||
	Nonce           *hexdata `json:"nonce"`
 | 
			
		||||
	Sha3Uncles      *hexdata `json:"sha3Uncles"`
 | 
			
		||||
	ReceiptHash     *hexdata `json:"receiptHash"`
 | 
			
		||||
	LogsBloom       *hexdata `json:"logsBloom"`
 | 
			
		||||
	TransactionRoot *hexdata `json:"transactionsRoot"`
 | 
			
		||||
	StateRoot       *hexdata `json:"stateRoot"`
 | 
			
		||||
	Miner           *hexdata `json:"miner"`
 | 
			
		||||
	Difficulty      *hexnum  `json:"difficulty"`
 | 
			
		||||
	ExtraData       *hexdata `json:"extraData"`
 | 
			
		||||
	GasLimit        *hexnum  `json:"gasLimit"`
 | 
			
		||||
	GasUsed         *hexnum  `json:"gasUsed"`
 | 
			
		||||
	UnixTimestamp   *hexnum  `json:"timestamp"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewUncleRes(h *types.Header) *UncleRes {
 | 
			
		||||
	if h == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var v = new(UncleRes)
 | 
			
		||||
	v.BlockNumber = newHexNum(h.Number)
 | 
			
		||||
	v.BlockHash = newHexData(h.Hash())
 | 
			
		||||
	v.ParentHash = newHexData(h.ParentHash)
 | 
			
		||||
	v.Sha3Uncles = newHexData(h.UncleHash)
 | 
			
		||||
	v.Nonce = newHexData(h.Nonce[:])
 | 
			
		||||
	v.LogsBloom = newHexData(h.Bloom)
 | 
			
		||||
	v.TransactionRoot = newHexData(h.TxHash)
 | 
			
		||||
	v.StateRoot = newHexData(h.Root)
 | 
			
		||||
	v.Miner = newHexData(h.Coinbase)
 | 
			
		||||
	v.Difficulty = newHexNum(h.Difficulty)
 | 
			
		||||
	v.ExtraData = newHexData(h.Extra)
 | 
			
		||||
	v.GasLimit = newHexNum(h.GasLimit)
 | 
			
		||||
	v.GasUsed = newHexNum(h.GasUsed)
 | 
			
		||||
	v.UnixTimestamp = newHexNum(h.Time)
 | 
			
		||||
	v.ReceiptHash = newHexData(h.ReceiptHash)
 | 
			
		||||
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// type FilterLogRes struct {
 | 
			
		||||
// 	Hash             string `json:"hash"`
 | 
			
		||||
// 	Address          string `json:"address"`
 | 
			
		||||
// 	Data             string `json:"data"`
 | 
			
		||||
// 	BlockNumber      string `json:"blockNumber"`
 | 
			
		||||
// 	TransactionHash  string `json:"transactionHash"`
 | 
			
		||||
// 	BlockHash        string `json:"blockHash"`
 | 
			
		||||
// 	TransactionIndex string `json:"transactionIndex"`
 | 
			
		||||
// 	LogIndex         string `json:"logIndex"`
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// type FilterWhisperRes struct {
 | 
			
		||||
// 	Hash       string `json:"hash"`
 | 
			
		||||
// 	From       string `json:"from"`
 | 
			
		||||
// 	To         string `json:"to"`
 | 
			
		||||
// 	Expiry     string `json:"expiry"`
 | 
			
		||||
// 	Sent       string `json:"sent"`
 | 
			
		||||
// 	Ttl        string `json:"ttl"`
 | 
			
		||||
// 	Topics     string `json:"topics"`
 | 
			
		||||
// 	Payload    string `json:"payload"`
 | 
			
		||||
// 	WorkProved string `json:"workProved"`
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
func numString(raw interface{}) (*big.Int, error) {
 | 
			
		||||
	var number *big.Int
 | 
			
		||||
	// Parse as integer
 | 
			
		||||
	num, ok := raw.(float64)
 | 
			
		||||
	if ok {
 | 
			
		||||
		number = big.NewInt(int64(num))
 | 
			
		||||
		return number, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse as string/hexstring
 | 
			
		||||
	str, ok := raw.(string)
 | 
			
		||||
	if ok {
 | 
			
		||||
		number = common.String2Big(str)
 | 
			
		||||
		return number, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, shared.NewInvalidTypeError("", "not a number or string")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func blockHeight(raw interface{}, number *int64) error {
 | 
			
		||||
	// Parse as integer
 | 
			
		||||
	num, ok := raw.(float64)
 | 
			
		||||
	if ok {
 | 
			
		||||
		*number = int64(num)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse as string/hexstring
 | 
			
		||||
	str, ok := raw.(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return shared.NewInvalidTypeError("", "not a number or string")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch str {
 | 
			
		||||
	case "earliest":
 | 
			
		||||
		*number = 0
 | 
			
		||||
	case "latest":
 | 
			
		||||
		*number = -1
 | 
			
		||||
	case "pending":
 | 
			
		||||
		*number = -2
 | 
			
		||||
	default:
 | 
			
		||||
		if common.HasHexPrefix(str) {
 | 
			
		||||
			*number = common.String2Big(str).Int64()
 | 
			
		||||
		} else {
 | 
			
		||||
			return shared.NewInvalidTypeError("blockNumber", "is not a valid string")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func blockHeightFromJson(msg json.RawMessage, number *int64) error {
 | 
			
		||||
	var raw interface{}
 | 
			
		||||
	if err := json.Unmarshal(msg, &raw); err != nil {
 | 
			
		||||
		return shared.NewDecodeParamError(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return blockHeight(raw, number)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								rpc/api/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								rpc/api/utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/eth"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/codec"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/xeth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	EthApiName = "eth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Parse a comma separated API string to individual api's
 | 
			
		||||
func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]EthereumApi, error) {
 | 
			
		||||
	if len(strings.TrimSpace(apistr)) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Empty apistr provided")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	names := strings.Split(apistr, ",")
 | 
			
		||||
	apis := make([]EthereumApi, len(names))
 | 
			
		||||
 | 
			
		||||
	for i, name := range names {
 | 
			
		||||
		switch strings.ToLower(strings.TrimSpace(name)) {
 | 
			
		||||
		case EthApiName:
 | 
			
		||||
			apis[i] = NewEthApi(xeth, codec)
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, fmt.Errorf("Unknown API '%s'", name)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return apis, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								rpc/codec/codec.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								rpc/codec/codec.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
package codec
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Codec int
 | 
			
		||||
 | 
			
		||||
// (de)serialization support for rpc interface
 | 
			
		||||
type ApiCoder interface {
 | 
			
		||||
	// Parse message to request from underlying stream
 | 
			
		||||
	ReadRequest() (*shared.Request, error)
 | 
			
		||||
	// Parse response message from underlying stream
 | 
			
		||||
	ReadResponse() (interface{}, error)
 | 
			
		||||
	// Encode response to encoded form in underlying stream
 | 
			
		||||
	WriteResponse(interface{}) error
 | 
			
		||||
	// Decode single message from data
 | 
			
		||||
	Decode([]byte, interface{}) error
 | 
			
		||||
	// Encode msg to encoded form
 | 
			
		||||
	Encode(msg interface{}) ([]byte, error)
 | 
			
		||||
	// close the underlying stream
 | 
			
		||||
	Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// supported codecs
 | 
			
		||||
const (
 | 
			
		||||
	JSON Codec = iota
 | 
			
		||||
	nCodecs
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// collection with supported coders
 | 
			
		||||
	coders = make([]func(net.Conn) ApiCoder, nCodecs)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// create a new coder instance
 | 
			
		||||
func (c Codec) New(conn net.Conn) ApiCoder {
 | 
			
		||||
	switch c {
 | 
			
		||||
	case JSON:
 | 
			
		||||
		return NewJsonCoder(conn)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	panic("codec: request for codec #" + strconv.Itoa(int(c)) + " is unavailable")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								rpc/codec/json.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								rpc/codec/json.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
package codec
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MAX_RESPONSE_SIZE = 64 * 1024
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Json serialization support
 | 
			
		||||
type JsonCodec struct {
 | 
			
		||||
	c net.Conn
 | 
			
		||||
	d *json.Decoder
 | 
			
		||||
	e *json.Encoder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create new JSON coder instance
 | 
			
		||||
func NewJsonCoder(conn net.Conn) ApiCoder {
 | 
			
		||||
	return &JsonCodec{
 | 
			
		||||
		c: conn,
 | 
			
		||||
		d: json.NewDecoder(conn),
 | 
			
		||||
		e: json.NewEncoder(conn),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Serialize obj to JSON and write it to conn
 | 
			
		||||
func (self *JsonCodec) ReadRequest() (*shared.Request, error) {
 | 
			
		||||
	req := shared.Request{}
 | 
			
		||||
	err := self.d.Decode(&req)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return &req, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *JsonCodec) ReadResponse() (interface{}, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	buf := make([]byte, MAX_RESPONSE_SIZE)
 | 
			
		||||
	n, _ := self.c.Read(buf)
 | 
			
		||||
 | 
			
		||||
	var failure shared.ErrorResponse
 | 
			
		||||
	if err = json.Unmarshal(buf[:n], &failure); err == nil && failure.Error != nil {
 | 
			
		||||
		return failure, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var success shared.SuccessResponse
 | 
			
		||||
	if err = json.Unmarshal(buf[:n], &success); err == nil {
 | 
			
		||||
		return success, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode response to encoded form in underlying stream
 | 
			
		||||
func (self *JsonCodec) Decode(data []byte, msg interface{}) error {
 | 
			
		||||
	return json.Unmarshal(data, msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *JsonCodec) Encode(msg interface{}) ([]byte, error) {
 | 
			
		||||
	return json.Marshal(msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse JSON data from conn to obj
 | 
			
		||||
func (self *JsonCodec) WriteResponse(res interface{}) error {
 | 
			
		||||
	return self.e.Encode(&res)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close decoder and encoder
 | 
			
		||||
func (self *JsonCodec) Close() {
 | 
			
		||||
	self.c.Close()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								rpc/shared/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								rpc/shared/errors.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package shared
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type InvalidTypeError struct {
 | 
			
		||||
	method string
 | 
			
		||||
	msg    string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *InvalidTypeError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("invalid type on field %s: %s", e.method, e.msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewInvalidTypeError(method, msg string) *InvalidTypeError {
 | 
			
		||||
	return &InvalidTypeError{
 | 
			
		||||
		method: method,
 | 
			
		||||
		msg:    msg,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InsufficientParamsError struct {
 | 
			
		||||
	have int
 | 
			
		||||
	want int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *InsufficientParamsError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("insufficient params, want %d have %d", e.want, e.have)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewInsufficientParamsError(have int, want int) *InsufficientParamsError {
 | 
			
		||||
	return &InsufficientParamsError{
 | 
			
		||||
		have: have,
 | 
			
		||||
		want: want,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NotImplementedError struct {
 | 
			
		||||
	Method string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *NotImplementedError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("%s method not implemented", e.Method)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewNotImplementedError(method string) *NotImplementedError {
 | 
			
		||||
	return &NotImplementedError{
 | 
			
		||||
		Method: method,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DecodeParamError struct {
 | 
			
		||||
	err string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *DecodeParamError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("could not decode, %s", e.err)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDecodeParamError(errstr string) error {
 | 
			
		||||
	return &DecodeParamError{
 | 
			
		||||
		err: errstr,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ValidationError struct {
 | 
			
		||||
	ParamName string
 | 
			
		||||
	msg       string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *ValidationError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("%s not valid, %s", e.ParamName, e.msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewValidationError(param string, msg string) error {
 | 
			
		||||
	return &ValidationError{
 | 
			
		||||
		ParamName: param,
 | 
			
		||||
		msg:       msg,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NotAvailableError struct {
 | 
			
		||||
	Method string
 | 
			
		||||
	Reason string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *NotAvailableError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("%s method not available: %s", e.Method, e.Reason)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewNotAvailableError(method string, reason string) *NotAvailableError {
 | 
			
		||||
	return &NotAvailableError{
 | 
			
		||||
		Method: method,
 | 
			
		||||
		Reason: reason,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								rpc/shared/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								rpc/shared/types.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
package shared
 | 
			
		||||
 | 
			
		||||
import "encoding/json"
 | 
			
		||||
 | 
			
		||||
// RPC request
 | 
			
		||||
type Request struct {
 | 
			
		||||
	Id      interface{}     `json:"id"`
 | 
			
		||||
	Jsonrpc string          `json:"jsonrpc"`
 | 
			
		||||
	Method  string          `json:"method"`
 | 
			
		||||
	Params  json.RawMessage `json:"params"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RPC response
 | 
			
		||||
type Response struct {
 | 
			
		||||
	Id      interface{} `json:"id"`
 | 
			
		||||
	Jsonrpc string      `json:"jsonrpc"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RPC success response
 | 
			
		||||
type SuccessResponse struct {
 | 
			
		||||
	Id      interface{} `json:"id"`
 | 
			
		||||
	Jsonrpc string      `json:"jsonrpc"`
 | 
			
		||||
	Result  interface{} `json:"result"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RPC error response
 | 
			
		||||
type ErrorResponse struct {
 | 
			
		||||
	Id      interface{}  `json:"id"`
 | 
			
		||||
	Jsonrpc string       `json:"jsonrpc"`
 | 
			
		||||
	Error   *ErrorObject `json:"error"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RPC error response details
 | 
			
		||||
type ErrorObject struct {
 | 
			
		||||
	Code    int    `json:"code"`
 | 
			
		||||
	Message string `json:"message"`
 | 
			
		||||
	// Data    interface{} `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user