commit
607fc788e3
|
@ -17,6 +17,10 @@ func (self StorageSize) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (self StorageSize) Int64() int64 {
|
||||
return int64(self)
|
||||
}
|
||||
|
||||
// The different number of units
|
||||
var (
|
||||
Douglas = BigPow(10, 42)
|
||||
|
|
28
rpc/api.go
28
rpc/api.go
|
@ -106,15 +106,15 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
count := api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
|
||||
*reply = common.ToHex(big.NewInt(int64(count)).Bytes())
|
||||
case "eth_getBlockTransactionCountByHash":
|
||||
args := new(GetBlockByHashArgs)
|
||||
args := new(HashArgs)
|
||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block := NewBlockRes(api.xeth().EthBlockByHash(args.BlockHash), false)
|
||||
block := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false)
|
||||
*reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes())
|
||||
case "eth_getBlockTransactionCountByNumber":
|
||||
args := new(GetBlockByNumberArgs)
|
||||
args := new(BlockNumArg)
|
||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -122,16 +122,16 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
block := NewBlockRes(api.xeth().EthBlockByNumber(args.BlockNumber), false)
|
||||
*reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes())
|
||||
case "eth_getUncleCountByBlockHash":
|
||||
args := new(GetBlockByHashArgs)
|
||||
args := new(HashArgs)
|
||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block := api.xeth().EthBlockByHash(args.BlockHash)
|
||||
block := api.xeth().EthBlockByHash(args.Hash)
|
||||
br := NewBlockRes(block, false)
|
||||
*reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes())
|
||||
case "eth_getUncleCountByBlockNumber":
|
||||
args := new(GetBlockByNumberArgs)
|
||||
args := new(BlockNumArg)
|
||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -144,7 +144,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
return err
|
||||
}
|
||||
*reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address)
|
||||
v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
|
||||
*reply = newHexData(v)
|
||||
case "eth_sendTransaction", "eth_transact":
|
||||
args := new(NewTxArgs)
|
||||
if err := json.Unmarshal(req.Params, &args); err != nil {
|
||||
|
@ -177,7 +178,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
}
|
||||
|
||||
block := api.xeth().EthBlockByHash(args.BlockHash)
|
||||
br := NewBlockRes(block, true)
|
||||
br := NewBlockRes(block, args.IncludeTxs)
|
||||
|
||||
*reply = br
|
||||
case "eth_getBlockByNumber":
|
||||
|
@ -187,7 +188,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
}
|
||||
|
||||
block := api.xeth().EthBlockByNumber(args.BlockNumber)
|
||||
br := NewBlockRes(block, true)
|
||||
br := NewBlockRes(block, args.IncludeTxs)
|
||||
|
||||
*reply = br
|
||||
case "eth_getTransactionByHash":
|
||||
|
@ -236,6 +237,10 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
}
|
||||
|
||||
br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false)
|
||||
if br == nil {
|
||||
*reply = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if args.Index >= int64(len(br.Uncles)) || args.Index < 0 {
|
||||
return NewValidationError("Index", "does not exist")
|
||||
|
@ -254,6 +259,11 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
block := api.xeth().EthBlockByNumber(args.BlockNumber)
|
||||
v := NewBlockRes(block, true)
|
||||
|
||||
if v == nil {
|
||||
*reply = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if args.Index >= int64(len(v.Uncles)) || args.Index < 0 {
|
||||
return NewValidationError("Index", "does not exist")
|
||||
}
|
||||
|
|
112
rpc/args.go
112
rpc/args.go
|
@ -108,8 +108,8 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 1 {
|
||||
return NewInsufficientParamsError(len(obj), 1)
|
||||
if len(obj) < 2 {
|
||||
return NewInsufficientParamsError(len(obj), 2)
|
||||
}
|
||||
|
||||
argstr, ok := obj[0].(string)
|
||||
|
@ -118,9 +118,7 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
}
|
||||
args.BlockHash = argstr
|
||||
|
||||
if len(obj) > 1 {
|
||||
args.IncludeTxs = obj[1].(bool)
|
||||
}
|
||||
args.IncludeTxs = obj[1].(bool)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -136,8 +134,8 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 1 {
|
||||
return NewInsufficientParamsError(len(obj), 1)
|
||||
if len(obj) < 2 {
|
||||
return NewInsufficientParamsError(len(obj), 2)
|
||||
}
|
||||
|
||||
if v, ok := obj[0].(float64); ok {
|
||||
|
@ -148,9 +146,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return NewInvalidTypeError("blockNumber", "not a number or string")
|
||||
}
|
||||
|
||||
if len(obj) > 1 {
|
||||
args.IncludeTxs = obj[1].(bool)
|
||||
}
|
||||
args.IncludeTxs = obj[1].(bool)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -202,7 +198,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
|
||||
var num int64
|
||||
if ext.Value == nil {
|
||||
return NewValidationError("value", "is required")
|
||||
num = 0
|
||||
} else {
|
||||
if err := numString(ext.Value, &num); err != nil {
|
||||
return err
|
||||
|
@ -211,7 +207,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
args.Value = big.NewInt(num)
|
||||
|
||||
if ext.Gas == nil {
|
||||
return NewValidationError("gas", "is required")
|
||||
num = 0
|
||||
} else {
|
||||
if err := numString(ext.Gas, &num); err != nil {
|
||||
return err
|
||||
|
@ -220,7 +216,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
args.Gas = big.NewInt(num)
|
||||
|
||||
if ext.GasPrice == nil {
|
||||
return NewValidationError("gasprice", "is required")
|
||||
num = 0
|
||||
} else {
|
||||
if err := numString(ext.GasPrice, &num); err != nil {
|
||||
return err
|
||||
|
@ -233,6 +229,8 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -320,6 +318,8 @@ func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -350,6 +350,8 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -387,6 +389,8 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeight(obj[2], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -417,6 +421,8 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -447,6 +453,8 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -477,6 +485,29 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
args.BlockNumber = -1
|
||||
}
|
||||
|
||||
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 NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 1 {
|
||||
return NewInsufficientParamsError(len(obj), 1)
|
||||
}
|
||||
|
||||
if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -493,31 +524,28 @@ func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
return NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 1 {
|
||||
return NewInsufficientParamsError(len(obj), 1)
|
||||
if len(obj) < 2 {
|
||||
return NewInsufficientParamsError(len(obj), 2)
|
||||
}
|
||||
|
||||
if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(obj) > 1 {
|
||||
arg1, ok := obj[1].(string)
|
||||
if !ok {
|
||||
return NewInvalidTypeError("index", "not a string")
|
||||
}
|
||||
args.Index = common.Big(arg1).Int64()
|
||||
arg1, ok := obj[1].(string)
|
||||
if !ok {
|
||||
return NewInvalidTypeError("index", "not a string")
|
||||
}
|
||||
args.Index = common.Big(arg1).Int64()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type HashIndexArgs struct {
|
||||
Hash string
|
||||
Index int64
|
||||
type HashArgs struct {
|
||||
Hash string
|
||||
}
|
||||
|
||||
func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
func (args *HashArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
var obj []interface{}
|
||||
if err := json.Unmarshal(b, &obj); err != nil {
|
||||
return NewDecodeParamError(err.Error())
|
||||
|
@ -533,14 +561,36 @@ func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
}
|
||||
args.Hash = arg0
|
||||
|
||||
if len(obj) > 1 {
|
||||
arg1, ok := obj[1].(string)
|
||||
if !ok {
|
||||
return NewInvalidTypeError("index", "not a string")
|
||||
}
|
||||
args.Index = common.Big(arg1).Int64()
|
||||
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 NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
if len(obj) < 2 {
|
||||
return NewInsufficientParamsError(len(obj), 2)
|
||||
}
|
||||
|
||||
arg0, ok := obj[0].(string)
|
||||
if !ok {
|
||||
return NewInvalidTypeError("hash", "not a string")
|
||||
}
|
||||
args.Hash = arg0
|
||||
|
||||
arg1, ok := obj[1].(string)
|
||||
if !ok {
|
||||
return NewInvalidTypeError("index", "not a string")
|
||||
}
|
||||
args.Index = common.Big(arg1).Int64()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ func TestGetBlockByHashArgsHashInt(t *testing.T) {
|
|||
input := `[8]`
|
||||
|
||||
args := new(GetBlockByHashArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
|
@ -281,6 +281,16 @@ func TestGetBlockByNumberEmpty(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetBlockByNumberShort(t *testing.T) {
|
||||
input := `["0xbbb"]`
|
||||
|
||||
args := new(GetBlockByNumberArgs)
|
||||
str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBlockByNumberBool(t *testing.T) {
|
||||
input := `[true, true]`
|
||||
|
||||
|
@ -458,11 +468,16 @@ func TestNewTxArgsGasMissing(t *testing.T) {
|
|||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
expected := new(NewTxArgs)
|
||||
expected.Gas = big.NewInt(0)
|
||||
|
||||
args := new(NewTxArgs)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 {
|
||||
t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,12 +489,18 @@ func TestNewTxArgsBlockGaspriceMissing(t *testing.T) {
|
|||
"value": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
expected := new(NewTxArgs)
|
||||
expected.GasPrice = big.NewInt(0)
|
||||
|
||||
args := new(NewTxArgs)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 {
|
||||
t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNewTxArgsValueMissing(t *testing.T) {
|
||||
|
@ -490,12 +511,18 @@ func TestNewTxArgsValueMissing(t *testing.T) {
|
|||
"gasPrice": "0x9184e72a000",
|
||||
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
|
||||
}]`
|
||||
expected := new(NewTxArgs)
|
||||
expected.Value = big.NewInt(0)
|
||||
|
||||
args := new(NewTxArgs)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 {
|
||||
t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNewTxArgsEmpty(t *testing.T) {
|
||||
|
|
105
rpc/responses.go
105
rpc/responses.go
|
@ -1,6 +1,8 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
@ -11,10 +13,10 @@ type BlockRes struct {
|
|||
BlockNumber *hexnum `json:"number"`
|
||||
BlockHash *hexdata `json:"hash"`
|
||||
ParentHash *hexdata `json:"parentHash"`
|
||||
Nonce *hexnum `json:"nonce"`
|
||||
Nonce *hexdata `json:"nonce"`
|
||||
Sha3Uncles *hexdata `json:"sha3Uncles"`
|
||||
LogsBloom *hexdata `json:"logsBloom"`
|
||||
TransactionRoot *hexdata `json:"transactionRoot"`
|
||||
TransactionRoot *hexdata `json:"transactionsRoot"`
|
||||
StateRoot *hexdata `json:"stateRoot"`
|
||||
Miner *hexdata `json:"miner"`
|
||||
Difficulty *hexnum `json:"difficulty"`
|
||||
|
@ -29,11 +31,104 @@ type BlockRes struct {
|
|||
Uncles []*hexdata `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"`
|
||||
MinGasPrice *hexnum `json:"minGasPrice"`
|
||||
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.MinGasPrice = b.MinGasPrice
|
||||
ext.GasUsed = b.GasUsed
|
||||
ext.UnixTimestamp = b.UnixTimestamp
|
||||
ext.Transactions = b.Transactions
|
||||
ext.Uncles = b.Uncles
|
||||
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"`
|
||||
MinGasPrice *hexnum `json:"minGasPrice"`
|
||||
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.MinGasPrice = b.MinGasPrice
|
||||
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 = b.Uncles
|
||||
return json.Marshal(ext)
|
||||
}
|
||||
}
|
||||
|
||||
func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
|
||||
// TODO respect fullTx flag
|
||||
|
||||
if block == nil {
|
||||
return &BlockRes{}
|
||||
return nil
|
||||
}
|
||||
|
||||
res := new(BlockRes)
|
||||
|
@ -41,7 +136,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
|
|||
res.BlockNumber = newHexNum(block.Number())
|
||||
res.BlockHash = newHexData(block.Hash())
|
||||
res.ParentHash = newHexData(block.ParentHash())
|
||||
res.Nonce = newHexNum(block.Header().Nonce)
|
||||
res.Nonce = newHexData(block.Nonce())
|
||||
res.Sha3Uncles = newHexData(block.Header().UncleHash)
|
||||
res.LogsBloom = newHexData(block.Bloom())
|
||||
res.TransactionRoot = newHexData(block.Header().TxHash)
|
||||
|
@ -49,7 +144,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
|
|||
res.Miner = newHexData(block.Header().Coinbase)
|
||||
res.Difficulty = newHexNum(block.Difficulty())
|
||||
res.TotalDifficulty = newHexNum(block.Td)
|
||||
res.Size = newHexNum(block.Size())
|
||||
res.Size = newHexNum(block.Size().Int64())
|
||||
res.ExtraData = newHexData(block.Header().Extra)
|
||||
res.GasLimit = newHexNum(block.GasLimit())
|
||||
// res.MinGasPrice =
|
||||
|
|
|
@ -13,12 +13,16 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
reHash = `"0x[0-9a-f]{64}"` // 32 bytes
|
||||
reHashOpt = `"(0x[0-9a-f]{64})"|null` // 32 bytes or null
|
||||
reAddress = `"0x[0-9a-f]{40}"` // 20 bytes
|
||||
reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null
|
||||
reNum = `"0x([1-9a-f][0-9a-f]{1,15})|0"` // must not have left-padded zeros
|
||||
reData = `"0x[0-9a-f]*"` // can be "empty"
|
||||
reHash = `"0x[0-9a-f]{64}"` // 32 bytes
|
||||
reHashOpt = `"(0x[0-9a-f]{64})"|null` // 32 bytes or null
|
||||
reAddress = `"0x[0-9a-f]{40}"` // 20 bytes
|
||||
reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null
|
||||
reNum = `"0x([1-9a-f][0-9a-f]{0,15})|0"` // must not have left-padded zeros
|
||||
reNumNonZero = `"0x([1-9a-f][0-9a-f]{0,15})"` // non-zero required must not have left-padded zeros
|
||||
reNumOpt = `"0x([1-9a-f][0-9a-f]{0,15})|0"|null` // must not have left-padded zeros or null
|
||||
reData = `"0x[0-9a-f]*"` // can be "empty"
|
||||
// reListHash = `[("\w":"0x[0-9a-f]{64}",?)*]`
|
||||
// reListObj = `[("\w":(".+"|null),?)*]`
|
||||
)
|
||||
|
||||
func TestNewBlockRes(t *testing.T) {
|
||||
|
@ -30,26 +34,87 @@ func TestNewBlockRes(t *testing.T) {
|
|||
extra := ""
|
||||
block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra)
|
||||
tests := map[string]string{
|
||||
"number": reNum,
|
||||
"hash": reHash,
|
||||
"parentHash": reHash,
|
||||
"nonce": reNum,
|
||||
"sha3Uncles": reHash,
|
||||
"logsBloom": reData,
|
||||
"transactionRoot": reHash,
|
||||
"stateRoot": reHash,
|
||||
"miner": reAddress,
|
||||
"difficulty": `"0x1"`,
|
||||
"totalDifficulty": reNum,
|
||||
"size": reNum,
|
||||
"extraData": reData,
|
||||
"gasLimit": reNum,
|
||||
"number": reNum,
|
||||
"hash": reHash,
|
||||
"parentHash": reHash,
|
||||
"nonce": reData,
|
||||
"sha3Uncles": reHash,
|
||||
"logsBloom": reData,
|
||||
"transactionsRoot": reHash,
|
||||
"stateRoot": reHash,
|
||||
"miner": reAddress,
|
||||
"difficulty": `"0x1"`,
|
||||
"totalDifficulty": reNum,
|
||||
"size": reNumNonZero,
|
||||
"extraData": reData,
|
||||
"gasLimit": reNum,
|
||||
// "minGasPrice": "0x",
|
||||
"gasUsed": reNum,
|
||||
"timestamp": reNum,
|
||||
// "transactions": reListHash,
|
||||
// "uncles": reListHash,
|
||||
}
|
||||
|
||||
to := common.HexToAddress("0x02")
|
||||
amount := big.NewInt(1)
|
||||
gasAmount := big.NewInt(1)
|
||||
gasPrice := big.NewInt(1)
|
||||
data := []byte{1, 2, 3}
|
||||
tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data)
|
||||
|
||||
v := NewBlockRes(block, false)
|
||||
v.Transactions = make([]*TransactionRes, 1)
|
||||
v.Transactions[0] = NewTransactionRes(tx)
|
||||
j, _ := json.Marshal(v)
|
||||
|
||||
for k, re := range tests {
|
||||
match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
|
||||
if !match {
|
||||
t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewBlockResWithTrans(t *testing.T) {
|
||||
parentHash := common.HexToHash("0x01")
|
||||
coinbase := common.HexToAddress("0x01")
|
||||
root := common.HexToHash("0x01")
|
||||
difficulty := common.Big1
|
||||
nonce := uint64(1)
|
||||
extra := ""
|
||||
block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra)
|
||||
tests := map[string]string{
|
||||
"number": reNum,
|
||||
"hash": reHash,
|
||||
"parentHash": reHash,
|
||||
"nonce": reData,
|
||||
"sha3Uncles": reHash,
|
||||
"logsBloom": reData,
|
||||
"transactionsRoot": reHash,
|
||||
"stateRoot": reHash,
|
||||
"miner": reAddress,
|
||||
"difficulty": `"0x1"`,
|
||||
"totalDifficulty": reNum,
|
||||
"size": reNumNonZero,
|
||||
"extraData": reData,
|
||||
"gasLimit": reNum,
|
||||
// "minGasPrice": "0x",
|
||||
"gasUsed": reNum,
|
||||
"timestamp": reNum,
|
||||
// "transactions": `[{.*}]`,
|
||||
// "uncles": reListHash,
|
||||
}
|
||||
|
||||
to := common.HexToAddress("0x02")
|
||||
amount := big.NewInt(1)
|
||||
gasAmount := big.NewInt(1)
|
||||
gasPrice := big.NewInt(1)
|
||||
data := []byte{1, 2, 3}
|
||||
tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data)
|
||||
|
||||
v := NewBlockRes(block, true)
|
||||
v.Transactions = make([]*TransactionRes, 1)
|
||||
v.Transactions[0] = NewTransactionRes(tx)
|
||||
j, _ := json.Marshal(v)
|
||||
|
||||
for k, re := range tests {
|
||||
|
@ -71,9 +136,9 @@ func TestNewTransactionRes(t *testing.T) {
|
|||
tests := map[string]string{
|
||||
"hash": reHash,
|
||||
"nonce": reNum,
|
||||
"blockHash": reHash,
|
||||
"blockNum": reNum,
|
||||
"transactionIndex": reNum,
|
||||
"blockHash": reHashOpt,
|
||||
"blockNum": reNumOpt,
|
||||
"transactionIndex": reNumOpt,
|
||||
"from": reAddress,
|
||||
"to": reAddressOpt,
|
||||
"value": reNum,
|
||||
|
|
|
@ -17,16 +17,19 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
type hexdata struct {
|
||||
data []byte
|
||||
data []byte
|
||||
isNil bool
|
||||
}
|
||||
|
||||
func (d *hexdata) String() string {
|
||||
|
@ -34,6 +37,9 @@ func (d *hexdata) String() string {
|
|||
}
|
||||
|
||||
func (d *hexdata) MarshalJSON() ([]byte, error) {
|
||||
if d.isNil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
|
@ -45,27 +51,69 @@ func (d *hexdata) UnmarshalJSON(b []byte) (err error) {
|
|||
func newHexData(input interface{}) *hexdata {
|
||||
d := new(hexdata)
|
||||
|
||||
if input == nil {
|
||||
d.data = nil
|
||||
return d
|
||||
}
|
||||
switch input := input.(type) {
|
||||
case []byte:
|
||||
d.data = input
|
||||
case common.Hash:
|
||||
d.data = input.Bytes()
|
||||
case *common.Hash:
|
||||
d.data = input.Bytes()
|
||||
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:
|
||||
d.data = input.Bytes()
|
||||
if input == nil {
|
||||
d.isNil = true
|
||||
} else {
|
||||
d.data = input.Bytes()
|
||||
}
|
||||
case int64:
|
||||
d.data = big.NewInt(input).Bytes()
|
||||
case uint64:
|
||||
d.data = big.NewInt(int64(input)).Bytes()
|
||||
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, 8)
|
||||
binary.BigEndian.PutUint16(buff, input)
|
||||
d.data = buff
|
||||
case int32:
|
||||
d.data = big.NewInt(int64(input)).Bytes()
|
||||
case uint32:
|
||||
buff := make([]byte, 8)
|
||||
binary.BigEndian.PutUint32(buff, input)
|
||||
d.data = buff
|
||||
case string: // hexstring
|
||||
d.data = common.Big(input).Bytes()
|
||||
default:
|
||||
|
@ -76,14 +124,15 @@ func newHexData(input interface{}) *hexdata {
|
|||
}
|
||||
|
||||
type hexnum struct {
|
||||
data []byte
|
||||
data []byte
|
||||
isNil bool
|
||||
}
|
||||
|
||||
func (d *hexnum) String() string {
|
||||
// Get hex string from bytes
|
||||
out := common.Bytes2Hex(d.data)
|
||||
// Trim leading 0s
|
||||
out = strings.Trim(out, "0")
|
||||
out = strings.TrimLeft(out, "0")
|
||||
// Output "0x0" when value is 0
|
||||
if len(out) == 0 {
|
||||
out = "0"
|
||||
|
@ -92,6 +141,9 @@ func (d *hexnum) String() string {
|
|||
}
|
||||
|
||||
func (d *hexnum) MarshalJSON() ([]byte, error) {
|
||||
if d.isNil {
|
||||
return json.Marshal(nil)
|
||||
}
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
|
@ -323,6 +323,10 @@ func (self *XEth) CodeAt(address string) string {
|
|||
return common.ToHex(self.State().state.GetCode(common.HexToAddress(address)))
|
||||
}
|
||||
|
||||
func (self *XEth) CodeAtBytes(address string) []byte {
|
||||
return self.State().SafeGet(address).Code()
|
||||
}
|
||||
|
||||
func (self *XEth) IsContract(address string) bool {
|
||||
return len(self.State().SafeGet(address).Code()) > 0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue