github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/rpc/api/parsing.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"encoding/hex"
    23  	"encoding/json"
    24  	"math/big"
    25  	"strings"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/rpc/shared"
    30  )
    31  
    32  type hexdata struct {
    33  	data  []byte
    34  	isNil bool
    35  }
    36  
    37  func (d *hexdata) String() string {
    38  	return "0x" + common.Bytes2Hex(d.data)
    39  }
    40  
    41  func (d *hexdata) MarshalJSON() ([]byte, error) {
    42  	if d.isNil {
    43  		return json.Marshal(nil)
    44  	}
    45  	return json.Marshal(d.String())
    46  }
    47  
    48  func newHexData(input interface{}) *hexdata {
    49  	d := new(hexdata)
    50  
    51  	if input == nil {
    52  		d.isNil = true
    53  		return d
    54  	}
    55  	switch input := input.(type) {
    56  	case []byte:
    57  		d.data = input
    58  	case common.Hash:
    59  		d.data = input.Bytes()
    60  	case *common.Hash:
    61  		if input == nil {
    62  			d.isNil = true
    63  		} else {
    64  			d.data = input.Bytes()
    65  		}
    66  	case common.Address:
    67  		d.data = input.Bytes()
    68  	case *common.Address:
    69  		if input == nil {
    70  			d.isNil = true
    71  		} else {
    72  			d.data = input.Bytes()
    73  		}
    74  	case types.Bloom:
    75  		d.data = input.Bytes()
    76  	case *types.Bloom:
    77  		if input == nil {
    78  			d.isNil = true
    79  		} else {
    80  			d.data = input.Bytes()
    81  		}
    82  	case *big.Int:
    83  		if input == nil {
    84  			d.isNil = true
    85  		} else {
    86  			d.data = input.Bytes()
    87  		}
    88  	case int64:
    89  		d.data = big.NewInt(input).Bytes()
    90  	case uint64:
    91  		buff := make([]byte, 8)
    92  		binary.BigEndian.PutUint64(buff, input)
    93  		d.data = buff
    94  	case int:
    95  		d.data = big.NewInt(int64(input)).Bytes()
    96  	case uint:
    97  		d.data = big.NewInt(int64(input)).Bytes()
    98  	case int8:
    99  		d.data = big.NewInt(int64(input)).Bytes()
   100  	case uint8:
   101  		d.data = big.NewInt(int64(input)).Bytes()
   102  	case int16:
   103  		d.data = big.NewInt(int64(input)).Bytes()
   104  	case uint16:
   105  		buff := make([]byte, 2)
   106  		binary.BigEndian.PutUint16(buff, input)
   107  		d.data = buff
   108  	case int32:
   109  		d.data = big.NewInt(int64(input)).Bytes()
   110  	case uint32:
   111  		buff := make([]byte, 4)
   112  		binary.BigEndian.PutUint32(buff, input)
   113  		d.data = buff
   114  	case string: // hexstring
   115  		// aaargh ffs TODO: avoid back-and-forth hex encodings where unneeded
   116  		bytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
   117  		if err != nil {
   118  			d.isNil = true
   119  		} else {
   120  			d.data = bytes
   121  		}
   122  	default:
   123  		d.isNil = true
   124  	}
   125  
   126  	return d
   127  }
   128  
   129  type hexnum struct {
   130  	data  []byte
   131  	isNil bool
   132  }
   133  
   134  func (d *hexnum) String() string {
   135  	// Get hex string from bytes
   136  	out := common.Bytes2Hex(d.data)
   137  	// Trim leading 0s
   138  	out = strings.TrimLeft(out, "0")
   139  	// Output "0x0" when value is 0
   140  	if len(out) == 0 {
   141  		out = "0"
   142  	}
   143  	return "0x" + out
   144  }
   145  
   146  func (d *hexnum) MarshalJSON() ([]byte, error) {
   147  	if d.isNil {
   148  		return json.Marshal(nil)
   149  	}
   150  	return json.Marshal(d.String())
   151  }
   152  
   153  func newHexNum(input interface{}) *hexnum {
   154  	d := new(hexnum)
   155  
   156  	d.data = newHexData(input).data
   157  
   158  	return d
   159  }
   160  
   161  type BlockRes struct {
   162  	fullTx bool
   163  
   164  	BlockNumber     *hexnum           `json:"number"`
   165  	BlockHash       *hexdata          `json:"hash"`
   166  	ParentHash      *hexdata          `json:"parentHash"`
   167  	Nonce           *hexdata          `json:"nonce"`
   168  	Sha3Uncles      *hexdata          `json:"sha3Uncles"`
   169  	LogsBloom       *hexdata          `json:"logsBloom"`
   170  	TransactionRoot *hexdata          `json:"transactionsRoot"`
   171  	StateRoot       *hexdata          `json:"stateRoot"`
   172  	Miner           *hexdata          `json:"miner"`
   173  	Difficulty      *hexnum           `json:"difficulty"`
   174  	TotalDifficulty *hexnum           `json:"totalDifficulty"`
   175  	Size            *hexnum           `json:"size"`
   176  	ExtraData       *hexdata          `json:"extraData"`
   177  	GasLimit        *hexnum           `json:"gasLimit"`
   178  	GasUsed         *hexnum           `json:"gasUsed"`
   179  	UnixTimestamp   *hexnum           `json:"timestamp"`
   180  	Transactions    []*TransactionRes `json:"transactions"`
   181  	Uncles          []*UncleRes       `json:"uncles"`
   182  }
   183  
   184  func (b *BlockRes) MarshalJSON() ([]byte, error) {
   185  	if b.fullTx {
   186  		var ext struct {
   187  			BlockNumber     *hexnum           `json:"number"`
   188  			BlockHash       *hexdata          `json:"hash"`
   189  			ParentHash      *hexdata          `json:"parentHash"`
   190  			Nonce           *hexdata          `json:"nonce"`
   191  			Sha3Uncles      *hexdata          `json:"sha3Uncles"`
   192  			LogsBloom       *hexdata          `json:"logsBloom"`
   193  			TransactionRoot *hexdata          `json:"transactionsRoot"`
   194  			StateRoot       *hexdata          `json:"stateRoot"`
   195  			Miner           *hexdata          `json:"miner"`
   196  			Difficulty      *hexnum           `json:"difficulty"`
   197  			TotalDifficulty *hexnum           `json:"totalDifficulty"`
   198  			Size            *hexnum           `json:"size"`
   199  			ExtraData       *hexdata          `json:"extraData"`
   200  			GasLimit        *hexnum           `json:"gasLimit"`
   201  			GasUsed         *hexnum           `json:"gasUsed"`
   202  			UnixTimestamp   *hexnum           `json:"timestamp"`
   203  			Transactions    []*TransactionRes `json:"transactions"`
   204  			Uncles          []*hexdata        `json:"uncles"`
   205  		}
   206  
   207  		ext.BlockNumber = b.BlockNumber
   208  		ext.BlockHash = b.BlockHash
   209  		ext.ParentHash = b.ParentHash
   210  		ext.Nonce = b.Nonce
   211  		ext.Sha3Uncles = b.Sha3Uncles
   212  		ext.LogsBloom = b.LogsBloom
   213  		ext.TransactionRoot = b.TransactionRoot
   214  		ext.StateRoot = b.StateRoot
   215  		ext.Miner = b.Miner
   216  		ext.Difficulty = b.Difficulty
   217  		ext.TotalDifficulty = b.TotalDifficulty
   218  		ext.Size = b.Size
   219  		ext.ExtraData = b.ExtraData
   220  		ext.GasLimit = b.GasLimit
   221  		ext.GasUsed = b.GasUsed
   222  		ext.UnixTimestamp = b.UnixTimestamp
   223  		ext.Transactions = b.Transactions
   224  		ext.Uncles = make([]*hexdata, len(b.Uncles))
   225  		for i, u := range b.Uncles {
   226  			ext.Uncles[i] = u.BlockHash
   227  		}
   228  		return json.Marshal(ext)
   229  	} else {
   230  		var ext struct {
   231  			BlockNumber     *hexnum    `json:"number"`
   232  			BlockHash       *hexdata   `json:"hash"`
   233  			ParentHash      *hexdata   `json:"parentHash"`
   234  			Nonce           *hexdata   `json:"nonce"`
   235  			Sha3Uncles      *hexdata   `json:"sha3Uncles"`
   236  			LogsBloom       *hexdata   `json:"logsBloom"`
   237  			TransactionRoot *hexdata   `json:"transactionsRoot"`
   238  			StateRoot       *hexdata   `json:"stateRoot"`
   239  			Miner           *hexdata   `json:"miner"`
   240  			Difficulty      *hexnum    `json:"difficulty"`
   241  			TotalDifficulty *hexnum    `json:"totalDifficulty"`
   242  			Size            *hexnum    `json:"size"`
   243  			ExtraData       *hexdata   `json:"extraData"`
   244  			GasLimit        *hexnum    `json:"gasLimit"`
   245  			GasUsed         *hexnum    `json:"gasUsed"`
   246  			UnixTimestamp   *hexnum    `json:"timestamp"`
   247  			Transactions    []*hexdata `json:"transactions"`
   248  			Uncles          []*hexdata `json:"uncles"`
   249  		}
   250  
   251  		ext.BlockNumber = b.BlockNumber
   252  		ext.BlockHash = b.BlockHash
   253  		ext.ParentHash = b.ParentHash
   254  		ext.Nonce = b.Nonce
   255  		ext.Sha3Uncles = b.Sha3Uncles
   256  		ext.LogsBloom = b.LogsBloom
   257  		ext.TransactionRoot = b.TransactionRoot
   258  		ext.StateRoot = b.StateRoot
   259  		ext.Miner = b.Miner
   260  		ext.Difficulty = b.Difficulty
   261  		ext.TotalDifficulty = b.TotalDifficulty
   262  		ext.Size = b.Size
   263  		ext.ExtraData = b.ExtraData
   264  		ext.GasLimit = b.GasLimit
   265  		ext.GasUsed = b.GasUsed
   266  		ext.UnixTimestamp = b.UnixTimestamp
   267  		ext.Transactions = make([]*hexdata, len(b.Transactions))
   268  		for i, tx := range b.Transactions {
   269  			ext.Transactions[i] = tx.Hash
   270  		}
   271  		ext.Uncles = make([]*hexdata, len(b.Uncles))
   272  		for i, u := range b.Uncles {
   273  			ext.Uncles[i] = u.BlockHash
   274  		}
   275  		return json.Marshal(ext)
   276  	}
   277  }
   278  
   279  func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
   280  	if block == nil {
   281  		return nil
   282  	}
   283  
   284  	res := new(BlockRes)
   285  	res.fullTx = fullTx
   286  	res.BlockNumber = newHexNum(block.Number())
   287  	res.BlockHash = newHexData(block.Hash())
   288  	res.ParentHash = newHexData(block.ParentHash())
   289  	res.Nonce = newHexData(block.Nonce())
   290  	res.Sha3Uncles = newHexData(block.UncleHash())
   291  	res.LogsBloom = newHexData(block.Bloom())
   292  	res.TransactionRoot = newHexData(block.TxHash())
   293  	res.StateRoot = newHexData(block.Root())
   294  	res.Miner = newHexData(block.Coinbase())
   295  	res.Difficulty = newHexNum(block.Difficulty())
   296  	res.TotalDifficulty = newHexNum(block.Td)
   297  	res.Size = newHexNum(block.Size().Int64())
   298  	res.ExtraData = newHexData(block.Extra())
   299  	res.GasLimit = newHexNum(block.GasLimit())
   300  	res.GasUsed = newHexNum(block.GasUsed())
   301  	res.UnixTimestamp = newHexNum(block.Time())
   302  
   303  	txs := block.Transactions()
   304  	res.Transactions = make([]*TransactionRes, len(txs))
   305  	for i, tx := range txs {
   306  		res.Transactions[i] = NewTransactionRes(tx)
   307  		res.Transactions[i].BlockHash = res.BlockHash
   308  		res.Transactions[i].BlockNumber = res.BlockNumber
   309  		res.Transactions[i].TxIndex = newHexNum(i)
   310  	}
   311  
   312  	uncles := block.Uncles()
   313  	res.Uncles = make([]*UncleRes, len(uncles))
   314  	for i, uncle := range uncles {
   315  		res.Uncles[i] = NewUncleRes(uncle)
   316  	}
   317  
   318  	return res
   319  }
   320  
   321  type TransactionRes struct {
   322  	Hash        *hexdata `json:"hash"`
   323  	Nonce       *hexnum  `json:"nonce"`
   324  	BlockHash   *hexdata `json:"blockHash"`
   325  	BlockNumber *hexnum  `json:"blockNumber"`
   326  	TxIndex     *hexnum  `json:"transactionIndex"`
   327  	From        *hexdata `json:"from"`
   328  	To          *hexdata `json:"to"`
   329  	Value       *hexnum  `json:"value"`
   330  	Gas         *hexnum  `json:"gas"`
   331  	GasPrice    *hexnum  `json:"gasPrice"`
   332  	Input       *hexdata `json:"input"`
   333  }
   334  
   335  func NewTransactionRes(tx *types.Transaction) *TransactionRes {
   336  	if tx == nil {
   337  		return nil
   338  	}
   339  
   340  	var v = new(TransactionRes)
   341  	v.Hash = newHexData(tx.Hash())
   342  	v.Nonce = newHexNum(tx.Nonce())
   343  	// v.BlockHash =
   344  	// v.BlockNumber =
   345  	// v.TxIndex =
   346  	from, _ := tx.From()
   347  	v.From = newHexData(from)
   348  	v.To = newHexData(tx.To())
   349  	v.Value = newHexNum(tx.Value())
   350  	v.Gas = newHexNum(tx.Gas())
   351  	v.GasPrice = newHexNum(tx.GasPrice())
   352  	v.Input = newHexData(tx.Data())
   353  	return v
   354  }
   355  
   356  type UncleRes struct {
   357  	BlockNumber     *hexnum  `json:"number"`
   358  	BlockHash       *hexdata `json:"hash"`
   359  	ParentHash      *hexdata `json:"parentHash"`
   360  	Nonce           *hexdata `json:"nonce"`
   361  	Sha3Uncles      *hexdata `json:"sha3Uncles"`
   362  	ReceiptHash     *hexdata `json:"receiptHash"`
   363  	LogsBloom       *hexdata `json:"logsBloom"`
   364  	TransactionRoot *hexdata `json:"transactionsRoot"`
   365  	StateRoot       *hexdata `json:"stateRoot"`
   366  	Miner           *hexdata `json:"miner"`
   367  	Difficulty      *hexnum  `json:"difficulty"`
   368  	ExtraData       *hexdata `json:"extraData"`
   369  	GasLimit        *hexnum  `json:"gasLimit"`
   370  	GasUsed         *hexnum  `json:"gasUsed"`
   371  	UnixTimestamp   *hexnum  `json:"timestamp"`
   372  }
   373  
   374  func NewUncleRes(h *types.Header) *UncleRes {
   375  	if h == nil {
   376  		return nil
   377  	}
   378  
   379  	var v = new(UncleRes)
   380  	v.BlockNumber = newHexNum(h.Number)
   381  	v.BlockHash = newHexData(h.Hash())
   382  	v.ParentHash = newHexData(h.ParentHash)
   383  	v.Sha3Uncles = newHexData(h.UncleHash)
   384  	v.Nonce = newHexData(h.Nonce[:])
   385  	v.LogsBloom = newHexData(h.Bloom)
   386  	v.TransactionRoot = newHexData(h.TxHash)
   387  	v.StateRoot = newHexData(h.Root)
   388  	v.Miner = newHexData(h.Coinbase)
   389  	v.Difficulty = newHexNum(h.Difficulty)
   390  	v.ExtraData = newHexData(h.Extra)
   391  	v.GasLimit = newHexNum(h.GasLimit)
   392  	v.GasUsed = newHexNum(h.GasUsed)
   393  	v.UnixTimestamp = newHexNum(h.Time)
   394  	v.ReceiptHash = newHexData(h.ReceiptHash)
   395  
   396  	return v
   397  }
   398  
   399  // type FilterLogRes struct {
   400  // 	Hash             string `json:"hash"`
   401  // 	Address          string `json:"address"`
   402  // 	Data             string `json:"data"`
   403  // 	BlockNumber      string `json:"blockNumber"`
   404  // 	TransactionHash  string `json:"transactionHash"`
   405  // 	BlockHash        string `json:"blockHash"`
   406  // 	TransactionIndex string `json:"transactionIndex"`
   407  // 	LogIndex         string `json:"logIndex"`
   408  // }
   409  
   410  // type FilterWhisperRes struct {
   411  // 	Hash       string `json:"hash"`
   412  // 	From       string `json:"from"`
   413  // 	To         string `json:"to"`
   414  // 	Expiry     string `json:"expiry"`
   415  // 	Sent       string `json:"sent"`
   416  // 	Ttl        string `json:"ttl"`
   417  // 	Topics     string `json:"topics"`
   418  // 	Payload    string `json:"payload"`
   419  // 	WorkProved string `json:"workProved"`
   420  // }
   421  
   422  type ReceiptRes struct {
   423  	TransactionHash   *hexdata       `json:"transactionHash"`
   424  	TransactionIndex  *hexnum        `json:"transactionIndex"`
   425  	BlockNumber       *hexnum        `json:"blockNumber"`
   426  	BlockHash         *hexdata       `json:"blockHash"`
   427  	CumulativeGasUsed *hexnum        `json:"cumulativeGasUsed"`
   428  	GasUsed           *hexnum        `json:"gasUsed"`
   429  	ContractAddress   *hexdata       `json:"contractAddress"`
   430  	Logs              *[]interface{} `json:"logs"`
   431  }
   432  
   433  func NewReceiptRes(rec *types.Receipt) *ReceiptRes {
   434  	if rec == nil {
   435  		return nil
   436  	}
   437  
   438  	var v = new(ReceiptRes)
   439  	v.TransactionHash = newHexData(rec.TxHash)
   440  	if rec.GasUsed != nil {
   441  		v.GasUsed = newHexNum(rec.GasUsed.Bytes())
   442  	}
   443  	v.CumulativeGasUsed = newHexNum(rec.CumulativeGasUsed)
   444  
   445  	// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
   446  	if bytes.Compare(rec.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 {
   447  		v.ContractAddress = newHexData(rec.ContractAddress)
   448  	}
   449  
   450  	logs := make([]interface{}, len(rec.Logs()))
   451  	for i, log := range rec.Logs() {
   452  		logs[i] = NewLogRes(log)
   453  	}
   454  	v.Logs = &logs
   455  
   456  	return v
   457  }
   458  
   459  func numString(raw interface{}) (*big.Int, error) {
   460  	var number *big.Int
   461  	// Parse as integer
   462  	num, ok := raw.(float64)
   463  	if ok {
   464  		number = big.NewInt(int64(num))
   465  		return number, nil
   466  	}
   467  
   468  	// Parse as string/hexstring
   469  	str, ok := raw.(string)
   470  	if ok {
   471  		number = common.String2Big(str)
   472  		return number, nil
   473  	}
   474  
   475  	return nil, shared.NewInvalidTypeError("", "not a number or string")
   476  }
   477  
   478  func blockHeight(raw interface{}, number *int64) error {
   479  	// Parse as integer
   480  	num, ok := raw.(float64)
   481  	if ok {
   482  		*number = int64(num)
   483  		return nil
   484  	}
   485  
   486  	// Parse as string/hexstring
   487  	str, ok := raw.(string)
   488  	if !ok {
   489  		return shared.NewInvalidTypeError("", "not a number or string")
   490  	}
   491  
   492  	switch str {
   493  	case "earliest":
   494  		*number = 0
   495  	case "latest":
   496  		*number = -1
   497  	case "pending":
   498  		*number = -2
   499  	default:
   500  		if common.HasHexPrefix(str) {
   501  			*number = common.String2Big(str).Int64()
   502  		} else {
   503  			return shared.NewInvalidTypeError("blockNumber", "is not a valid string")
   504  		}
   505  	}
   506  
   507  	return nil
   508  }
   509  
   510  func blockHeightFromJson(msg json.RawMessage, number *int64) error {
   511  	var raw interface{}
   512  	if err := json.Unmarshal(msg, &raw); err != nil {
   513  		return shared.NewDecodeParamError(err.Error())
   514  	}
   515  	return blockHeight(raw, number)
   516  }