core/types: use gencodec for JSON marshaling code
This commit is contained in:
parent
eee96a5bb7
commit
8cf08e4b25
@ -19,8 +19,6 @@ package types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
@ -39,12 +37,6 @@ var (
|
||||
EmptyUncleHash = CalcUncleHash(nil)
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingHeaderMixDigest = errors.New("missing mixHash in JSON block header")
|
||||
errMissingHeaderFields = errors.New("missing required JSON block header fields")
|
||||
errBadNonceSize = errors.New("invalid block nonce size, want 8 bytes")
|
||||
)
|
||||
|
||||
// A BlockNonce is a 64-bit hash which proves (combined with the
|
||||
// mix-hash) that a sufficient amount of computation has been carried
|
||||
// out on a block.
|
||||
@ -72,41 +64,35 @@ func (n *BlockNonce) UnmarshalText(input []byte) error {
|
||||
return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
|
||||
}
|
||||
|
||||
//go:generate gencodec -type Header -field-override headerMarshaling -out gen_header_json.go
|
||||
|
||||
// Header represents a block header in the Ethereum blockchain.
|
||||
type Header struct {
|
||||
ParentHash common.Hash // Hash to the previous block
|
||||
UncleHash common.Hash // Uncles of this block
|
||||
Coinbase common.Address // The coin base address
|
||||
Root common.Hash // Block Trie state
|
||||
TxHash common.Hash // Tx sha
|
||||
ReceiptHash common.Hash // Receipt sha
|
||||
Bloom Bloom // Bloom
|
||||
Difficulty *big.Int // Difficulty for the current block
|
||||
Number *big.Int // The block number
|
||||
GasLimit *big.Int // Gas limit
|
||||
GasUsed *big.Int // Gas used
|
||||
Time *big.Int // Creation time
|
||||
Extra []byte // Extra data
|
||||
MixDigest common.Hash // for quick difficulty verification
|
||||
Nonce BlockNonce
|
||||
ParentHash common.Hash `json:"parentHash"`
|
||||
UncleHash common.Hash `json:"sha3Uncles"`
|
||||
Coinbase common.Address `json:"miner"`
|
||||
Root common.Hash `json:"stateRoot"`
|
||||
TxHash common.Hash `json:"transactionsRoot"`
|
||||
ReceiptHash common.Hash `json:"receiptsRoot"`
|
||||
Bloom Bloom `json:"logsBloom"`
|
||||
Difficulty *big.Int `json:"difficulty"`
|
||||
Number *big.Int `json:"number"`
|
||||
GasLimit *big.Int `json:"gasLimit"`
|
||||
GasUsed *big.Int `json:"gasUsed"`
|
||||
Time *big.Int `json:"timestamp"`
|
||||
Extra []byte `json:"extraData"`
|
||||
MixDigest common.Hash `json:"mixHash"`
|
||||
Nonce BlockNonce `json:"nonce"`
|
||||
}
|
||||
|
||||
type jsonHeader struct {
|
||||
ParentHash *common.Hash `json:"parentHash"`
|
||||
UncleHash *common.Hash `json:"sha3Uncles"`
|
||||
Coinbase *common.Address `json:"miner"`
|
||||
Root *common.Hash `json:"stateRoot"`
|
||||
TxHash *common.Hash `json:"transactionsRoot"`
|
||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Difficulty *hexutil.Big `json:"difficulty"`
|
||||
Number *hexutil.Big `json:"number"`
|
||||
GasLimit *hexutil.Big `json:"gasLimit"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
Time *hexutil.Big `json:"timestamp"`
|
||||
Extra *hexutil.Bytes `json:"extraData"`
|
||||
MixDigest *common.Hash `json:"mixHash"`
|
||||
Nonce *BlockNonce `json:"nonce"`
|
||||
// field type overrides for gencodec
|
||||
type headerMarshaling struct {
|
||||
Difficulty *hexutil.Big
|
||||
Number *hexutil.Big
|
||||
GasLimit *hexutil.Big
|
||||
GasUsed *hexutil.Big
|
||||
Time *hexutil.Big
|
||||
Extra hexutil.Bytes
|
||||
}
|
||||
|
||||
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
|
||||
@ -134,65 +120,6 @@ func (h *Header) HashNoNonce() common.Hash {
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalJSON encodes headers into the web3 RPC response block format.
|
||||
func (h *Header) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&jsonHeader{
|
||||
ParentHash: &h.ParentHash,
|
||||
UncleHash: &h.UncleHash,
|
||||
Coinbase: &h.Coinbase,
|
||||
Root: &h.Root,
|
||||
TxHash: &h.TxHash,
|
||||
ReceiptHash: &h.ReceiptHash,
|
||||
Bloom: &h.Bloom,
|
||||
Difficulty: (*hexutil.Big)(h.Difficulty),
|
||||
Number: (*hexutil.Big)(h.Number),
|
||||
GasLimit: (*hexutil.Big)(h.GasLimit),
|
||||
GasUsed: (*hexutil.Big)(h.GasUsed),
|
||||
Time: (*hexutil.Big)(h.Time),
|
||||
Extra: (*hexutil.Bytes)(&h.Extra),
|
||||
MixDigest: &h.MixDigest,
|
||||
Nonce: &h.Nonce,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes headers from the web3 RPC response block format.
|
||||
func (h *Header) UnmarshalJSON(input []byte) error {
|
||||
var dec jsonHeader
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure that all fields are set. MixDigest is checked separately because
|
||||
// it is a recent addition to the spec (as of August 2016) and older RPC server
|
||||
// implementations might not provide it.
|
||||
if dec.MixDigest == nil {
|
||||
return errMissingHeaderMixDigest
|
||||
}
|
||||
if dec.ParentHash == nil || dec.UncleHash == nil || dec.Coinbase == nil ||
|
||||
dec.Root == nil || dec.TxHash == nil || dec.ReceiptHash == nil ||
|
||||
dec.Bloom == nil || dec.Difficulty == nil || dec.Number == nil ||
|
||||
dec.GasLimit == nil || dec.GasUsed == nil || dec.Time == nil ||
|
||||
dec.Extra == nil || dec.Nonce == nil {
|
||||
return errMissingHeaderFields
|
||||
}
|
||||
// Assign all values.
|
||||
h.ParentHash = *dec.ParentHash
|
||||
h.UncleHash = *dec.UncleHash
|
||||
h.Coinbase = *dec.Coinbase
|
||||
h.Root = *dec.Root
|
||||
h.TxHash = *dec.TxHash
|
||||
h.ReceiptHash = *dec.ReceiptHash
|
||||
h.Bloom = *dec.Bloom
|
||||
h.Difficulty = (*big.Int)(dec.Difficulty)
|
||||
h.Number = (*big.Int)(dec.Number)
|
||||
h.GasLimit = (*big.Int)(dec.GasLimit)
|
||||
h.GasUsed = (*big.Int)(dec.GasUsed)
|
||||
h.Time = (*big.Int)(dec.Time)
|
||||
h.Extra = *dec.Extra
|
||||
h.MixDigest = *dec.MixDigest
|
||||
h.Nonce = *dec.Nonce
|
||||
return nil
|
||||
}
|
||||
|
||||
func rlpHash(x interface{}) (h common.Hash) {
|
||||
hw := sha3.NewKeccak256()
|
||||
rlp.Encode(hw, x)
|
||||
|
136
core/types/gen_header_json.go
Normal file
136
core/types/gen_header_json.go
Normal file
@ -0,0 +1,136 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func (h *Header) MarshalJSON() ([]byte, error) {
|
||||
type HeaderJSON struct {
|
||||
ParentHash *common.Hash `json:"parentHash"`
|
||||
UncleHash *common.Hash `json:"sha3Uncles"`
|
||||
Coinbase *common.Address `json:"miner"`
|
||||
Root *common.Hash `json:"stateRoot"`
|
||||
TxHash *common.Hash `json:"transactionsRoot"`
|
||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Difficulty *hexutil.Big `json:"difficulty"`
|
||||
Number *hexutil.Big `json:"number"`
|
||||
GasLimit *hexutil.Big `json:"gasLimit"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
Time *hexutil.Big `json:"timestamp"`
|
||||
Extra hexutil.Bytes `json:"extraData"`
|
||||
MixDigest *common.Hash `json:"mixHash"`
|
||||
Nonce *BlockNonce `json:"nonce"`
|
||||
}
|
||||
var enc HeaderJSON
|
||||
enc.ParentHash = &h.ParentHash
|
||||
enc.UncleHash = &h.UncleHash
|
||||
enc.Coinbase = &h.Coinbase
|
||||
enc.Root = &h.Root
|
||||
enc.TxHash = &h.TxHash
|
||||
enc.ReceiptHash = &h.ReceiptHash
|
||||
enc.Bloom = &h.Bloom
|
||||
enc.Difficulty = (*hexutil.Big)(h.Difficulty)
|
||||
enc.Number = (*hexutil.Big)(h.Number)
|
||||
enc.GasLimit = (*hexutil.Big)(h.GasLimit)
|
||||
enc.GasUsed = (*hexutil.Big)(h.GasUsed)
|
||||
enc.Time = (*hexutil.Big)(h.Time)
|
||||
enc.Extra = h.Extra
|
||||
enc.MixDigest = &h.MixDigest
|
||||
enc.Nonce = &h.Nonce
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (h *Header) UnmarshalJSON(input []byte) error {
|
||||
type HeaderJSON struct {
|
||||
ParentHash *common.Hash `json:"parentHash"`
|
||||
UncleHash *common.Hash `json:"sha3Uncles"`
|
||||
Coinbase *common.Address `json:"miner"`
|
||||
Root *common.Hash `json:"stateRoot"`
|
||||
TxHash *common.Hash `json:"transactionsRoot"`
|
||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Difficulty *hexutil.Big `json:"difficulty"`
|
||||
Number *hexutil.Big `json:"number"`
|
||||
GasLimit *hexutil.Big `json:"gasLimit"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
Time *hexutil.Big `json:"timestamp"`
|
||||
Extra hexutil.Bytes `json:"extraData"`
|
||||
MixDigest *common.Hash `json:"mixHash"`
|
||||
Nonce *BlockNonce `json:"nonce"`
|
||||
}
|
||||
var dec HeaderJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x Header
|
||||
if dec.ParentHash == nil {
|
||||
return errors.New("missing required field 'parentHash' for Header")
|
||||
}
|
||||
x.ParentHash = *dec.ParentHash
|
||||
if dec.UncleHash == nil {
|
||||
return errors.New("missing required field 'sha3Uncles' for Header")
|
||||
}
|
||||
x.UncleHash = *dec.UncleHash
|
||||
if dec.Coinbase == nil {
|
||||
return errors.New("missing required field 'miner' for Header")
|
||||
}
|
||||
x.Coinbase = *dec.Coinbase
|
||||
if dec.Root == nil {
|
||||
return errors.New("missing required field 'stateRoot' for Header")
|
||||
}
|
||||
x.Root = *dec.Root
|
||||
if dec.TxHash == nil {
|
||||
return errors.New("missing required field 'transactionsRoot' for Header")
|
||||
}
|
||||
x.TxHash = *dec.TxHash
|
||||
if dec.ReceiptHash == nil {
|
||||
return errors.New("missing required field 'receiptsRoot' for Header")
|
||||
}
|
||||
x.ReceiptHash = *dec.ReceiptHash
|
||||
if dec.Bloom == nil {
|
||||
return errors.New("missing required field 'logsBloom' for Header")
|
||||
}
|
||||
x.Bloom = *dec.Bloom
|
||||
if dec.Difficulty == nil {
|
||||
return errors.New("missing required field 'difficulty' for Header")
|
||||
}
|
||||
x.Difficulty = (*big.Int)(dec.Difficulty)
|
||||
if dec.Number == nil {
|
||||
return errors.New("missing required field 'number' for Header")
|
||||
}
|
||||
x.Number = (*big.Int)(dec.Number)
|
||||
if dec.GasLimit == nil {
|
||||
return errors.New("missing required field 'gasLimit' for Header")
|
||||
}
|
||||
x.GasLimit = (*big.Int)(dec.GasLimit)
|
||||
if dec.GasUsed == nil {
|
||||
return errors.New("missing required field 'gasUsed' for Header")
|
||||
}
|
||||
x.GasUsed = (*big.Int)(dec.GasUsed)
|
||||
if dec.Time == nil {
|
||||
return errors.New("missing required field 'timestamp' for Header")
|
||||
}
|
||||
x.Time = (*big.Int)(dec.Time)
|
||||
if dec.Extra == nil {
|
||||
return errors.New("missing required field 'extraData' for Header")
|
||||
}
|
||||
x.Extra = dec.Extra
|
||||
if dec.MixDigest == nil {
|
||||
return errors.New("missing required field 'mixHash' for Header")
|
||||
}
|
||||
x.MixDigest = *dec.MixDigest
|
||||
if dec.Nonce == nil {
|
||||
return errors.New("missing required field 'nonce' for Header")
|
||||
}
|
||||
x.Nonce = *dec.Nonce
|
||||
*h = x
|
||||
return nil
|
||||
}
|
90
core/types/gen_log_json.go
Normal file
90
core/types/gen_log_json.go
Normal file
@ -0,0 +1,90 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func (l *Log) MarshalJSON() ([]byte, error) {
|
||||
type LogJSON struct {
|
||||
Address *common.Address `json:"address"`
|
||||
Topics []common.Hash `json:"topics"`
|
||||
Data hexutil.Bytes `json:"data"`
|
||||
BlockNumber *hexutil.Uint64 `json:"blockNumber" optional:"yes"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
TxIndex *hexutil.Uint `json:"transactionIndex"`
|
||||
BlockHash *common.Hash `json:"blockHash" optional:"yes"`
|
||||
Index *hexutil.Uint `json:"logIndex"`
|
||||
Removed *bool `json:"removed" optional:"yes"`
|
||||
}
|
||||
var enc LogJSON
|
||||
enc.Address = &l.Address
|
||||
enc.Topics = l.Topics
|
||||
enc.Data = l.Data
|
||||
enc.BlockNumber = (*hexutil.Uint64)(&l.BlockNumber)
|
||||
enc.TxHash = &l.TxHash
|
||||
enc.TxIndex = (*hexutil.Uint)(&l.TxIndex)
|
||||
enc.BlockHash = &l.BlockHash
|
||||
enc.Index = (*hexutil.Uint)(&l.Index)
|
||||
enc.Removed = &l.Removed
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (l *Log) UnmarshalJSON(input []byte) error {
|
||||
type LogJSON struct {
|
||||
Address *common.Address `json:"address"`
|
||||
Topics []common.Hash `json:"topics"`
|
||||
Data hexutil.Bytes `json:"data"`
|
||||
BlockNumber *hexutil.Uint64 `json:"blockNumber" optional:"yes"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
TxIndex *hexutil.Uint `json:"transactionIndex"`
|
||||
BlockHash *common.Hash `json:"blockHash" optional:"yes"`
|
||||
Index *hexutil.Uint `json:"logIndex"`
|
||||
Removed *bool `json:"removed" optional:"yes"`
|
||||
}
|
||||
var dec LogJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x Log
|
||||
if dec.Address == nil {
|
||||
return errors.New("missing required field 'address' for Log")
|
||||
}
|
||||
x.Address = *dec.Address
|
||||
if dec.Topics == nil {
|
||||
return errors.New("missing required field 'topics' for Log")
|
||||
}
|
||||
x.Topics = dec.Topics
|
||||
if dec.Data == nil {
|
||||
return errors.New("missing required field 'data' for Log")
|
||||
}
|
||||
x.Data = dec.Data
|
||||
if dec.BlockNumber != nil {
|
||||
x.BlockNumber = uint64(*dec.BlockNumber)
|
||||
}
|
||||
if dec.TxHash == nil {
|
||||
return errors.New("missing required field 'transactionHash' for Log")
|
||||
}
|
||||
x.TxHash = *dec.TxHash
|
||||
if dec.TxIndex == nil {
|
||||
return errors.New("missing required field 'transactionIndex' for Log")
|
||||
}
|
||||
x.TxIndex = uint(*dec.TxIndex)
|
||||
if dec.BlockHash != nil {
|
||||
x.BlockHash = *dec.BlockHash
|
||||
}
|
||||
if dec.Index == nil {
|
||||
return errors.New("missing required field 'logIndex' for Log")
|
||||
}
|
||||
x.Index = uint(*dec.Index)
|
||||
if dec.Removed != nil {
|
||||
x.Removed = *dec.Removed
|
||||
}
|
||||
*l = x
|
||||
return nil
|
||||
}
|
79
core/types/gen_receipt_json.go
Normal file
79
core/types/gen_receipt_json.go
Normal file
@ -0,0 +1,79 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func (r *Receipt) MarshalJSON() ([]byte, error) {
|
||||
type ReceiptJSON struct {
|
||||
PostState hexutil.Bytes `json:"root"`
|
||||
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Logs []*Log `json:"logs"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
ContractAddress *common.Address `json:"contractAddress" optional:"true"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
}
|
||||
var enc ReceiptJSON
|
||||
enc.PostState = r.PostState
|
||||
enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed)
|
||||
enc.Bloom = &r.Bloom
|
||||
enc.Logs = r.Logs
|
||||
enc.TxHash = &r.TxHash
|
||||
enc.ContractAddress = &r.ContractAddress
|
||||
enc.GasUsed = (*hexutil.Big)(r.GasUsed)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (r *Receipt) UnmarshalJSON(input []byte) error {
|
||||
type ReceiptJSON struct {
|
||||
PostState hexutil.Bytes `json:"root"`
|
||||
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Logs []*Log `json:"logs"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
ContractAddress *common.Address `json:"contractAddress" optional:"true"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
}
|
||||
var dec ReceiptJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x Receipt
|
||||
if dec.PostState == nil {
|
||||
return errors.New("missing required field 'root' for Receipt")
|
||||
}
|
||||
x.PostState = dec.PostState
|
||||
if dec.CumulativeGasUsed == nil {
|
||||
return errors.New("missing required field 'cumulativeGasUsed' for Receipt")
|
||||
}
|
||||
x.CumulativeGasUsed = (*big.Int)(dec.CumulativeGasUsed)
|
||||
if dec.Bloom == nil {
|
||||
return errors.New("missing required field 'logsBloom' for Receipt")
|
||||
}
|
||||
x.Bloom = *dec.Bloom
|
||||
if dec.Logs == nil {
|
||||
return errors.New("missing required field 'logs' for Receipt")
|
||||
}
|
||||
x.Logs = dec.Logs
|
||||
if dec.TxHash == nil {
|
||||
return errors.New("missing required field 'transactionHash' for Receipt")
|
||||
}
|
||||
x.TxHash = *dec.TxHash
|
||||
if dec.ContractAddress != nil {
|
||||
x.ContractAddress = *dec.ContractAddress
|
||||
}
|
||||
if dec.GasUsed == nil {
|
||||
return errors.New("missing required field 'gasUsed' for Receipt")
|
||||
}
|
||||
x.GasUsed = (*big.Int)(dec.GasUsed)
|
||||
*r = x
|
||||
return nil
|
||||
}
|
99
core/types/gen_tx_json.go
Normal file
99
core/types/gen_tx_json.go
Normal file
@ -0,0 +1,99 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func (t *txdata) MarshalJSON() ([]byte, error) {
|
||||
type txdataJSON struct {
|
||||
AccountNonce *hexutil.Uint64 `json:"nonce"`
|
||||
Price *hexutil.Big `json:"gasPrice"`
|
||||
GasLimit *hexutil.Big `json:"gasLimit"`
|
||||
Recipient *common.Address `json:"to" optional:"yes" rlp:"nil"`
|
||||
Amount *hexutil.Big `json:"value"`
|
||||
Payload hexutil.Bytes `json:"input"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
Hash *common.Hash `json:"hash" optional:"yes" rlp:"-"`
|
||||
}
|
||||
var enc txdataJSON
|
||||
enc.AccountNonce = (*hexutil.Uint64)(&t.AccountNonce)
|
||||
enc.Price = (*hexutil.Big)(t.Price)
|
||||
enc.GasLimit = (*hexutil.Big)(t.GasLimit)
|
||||
enc.Recipient = t.Recipient
|
||||
enc.Amount = (*hexutil.Big)(t.Amount)
|
||||
enc.Payload = t.Payload
|
||||
enc.V = (*hexutil.Big)(t.V)
|
||||
enc.R = (*hexutil.Big)(t.R)
|
||||
enc.S = (*hexutil.Big)(t.S)
|
||||
enc.Hash = t.Hash
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (t *txdata) UnmarshalJSON(input []byte) error {
|
||||
type txdataJSON struct {
|
||||
AccountNonce *hexutil.Uint64 `json:"nonce"`
|
||||
Price *hexutil.Big `json:"gasPrice"`
|
||||
GasLimit *hexutil.Big `json:"gasLimit"`
|
||||
Recipient *common.Address `json:"to" optional:"yes" rlp:"nil"`
|
||||
Amount *hexutil.Big `json:"value"`
|
||||
Payload hexutil.Bytes `json:"input"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
Hash *common.Hash `json:"hash" optional:"yes" rlp:"-"`
|
||||
}
|
||||
var dec txdataJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x txdata
|
||||
if dec.AccountNonce == nil {
|
||||
return errors.New("missing required field 'nonce' for txdata")
|
||||
}
|
||||
x.AccountNonce = uint64(*dec.AccountNonce)
|
||||
if dec.Price == nil {
|
||||
return errors.New("missing required field 'gasPrice' for txdata")
|
||||
}
|
||||
x.Price = (*big.Int)(dec.Price)
|
||||
if dec.GasLimit == nil {
|
||||
return errors.New("missing required field 'gasLimit' for txdata")
|
||||
}
|
||||
x.GasLimit = (*big.Int)(dec.GasLimit)
|
||||
if dec.Recipient != nil {
|
||||
x.Recipient = dec.Recipient
|
||||
}
|
||||
if dec.Amount == nil {
|
||||
return errors.New("missing required field 'value' for txdata")
|
||||
}
|
||||
x.Amount = (*big.Int)(dec.Amount)
|
||||
if dec.Payload == nil {
|
||||
return errors.New("missing required field 'input' for txdata")
|
||||
}
|
||||
x.Payload = dec.Payload
|
||||
if dec.V == nil {
|
||||
return errors.New("missing required field 'v' for txdata")
|
||||
}
|
||||
x.V = (*big.Int)(dec.V)
|
||||
if dec.R == nil {
|
||||
return errors.New("missing required field 'r' for txdata")
|
||||
}
|
||||
x.R = (*big.Int)(dec.R)
|
||||
if dec.S == nil {
|
||||
return errors.New("missing required field 's' for txdata")
|
||||
}
|
||||
x.S = (*big.Int)(dec.S)
|
||||
if dec.Hash != nil {
|
||||
x.Hash = dec.Hash
|
||||
}
|
||||
*t = x
|
||||
return nil
|
||||
}
|
@ -17,8 +17,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@ -27,27 +25,42 @@ import (
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var errMissingLogFields = errors.New("missing required JSON log fields")
|
||||
//go:generate gencodec -type Log -field-override logMarshaling -out gen_log_json.go
|
||||
|
||||
// Log represents a contract log event. These events are generated by the LOG opcode and
|
||||
// stored/indexed by the node.
|
||||
type Log struct {
|
||||
// Consensus fields.
|
||||
Address common.Address // address of the contract that generated the event
|
||||
Topics []common.Hash // list of topics provided by the contract.
|
||||
Data []byte // supplied by the contract, usually ABI-encoded
|
||||
// Consensus fields:
|
||||
// address of the contract that generated the event
|
||||
Address common.Address `json:"address"`
|
||||
// list of topics provided by the contract.
|
||||
Topics []common.Hash `json:"topics"`
|
||||
// supplied by the contract, usually ABI-encoded
|
||||
Data []byte `json:"data"`
|
||||
|
||||
// Derived fields. These fields are filled in by the node
|
||||
// but not secured by consensus.
|
||||
BlockNumber uint64 // block in which the transaction was included
|
||||
TxHash common.Hash // hash of the transaction
|
||||
TxIndex uint // index of the transaction in the block
|
||||
BlockHash common.Hash // hash of the block in which the transaction was included
|
||||
Index uint // index of the log in the receipt
|
||||
// block in which the transaction was included
|
||||
BlockNumber uint64 `json:"blockNumber" optional:"yes"`
|
||||
// hash of the transaction
|
||||
TxHash common.Hash `json:"transactionHash"`
|
||||
// index of the transaction in the block
|
||||
TxIndex uint `json:"transactionIndex"`
|
||||
// hash of the block in which the transaction was included
|
||||
BlockHash common.Hash `json:"blockHash" optional:"yes"`
|
||||
// index of the log in the receipt
|
||||
Index uint `json:"logIndex"`
|
||||
|
||||
// The Removed field is true if this log was reverted due to a chain reorganisation.
|
||||
// You must pay attention to this field if you receive logs through a filter query.
|
||||
Removed bool
|
||||
Removed bool `json:"removed" optional:"yes"`
|
||||
}
|
||||
|
||||
type logMarshaling struct {
|
||||
Data hexutil.Bytes
|
||||
BlockNumber hexutil.Uint64
|
||||
TxIndex hexutil.Uint
|
||||
Index hexutil.Uint
|
||||
}
|
||||
|
||||
type rlpLog struct {
|
||||
@ -67,18 +80,6 @@ type rlpStorageLog struct {
|
||||
Index uint
|
||||
}
|
||||
|
||||
type jsonLog struct {
|
||||
Address *common.Address `json:"address"`
|
||||
Topics *[]common.Hash `json:"topics"`
|
||||
Data *hexutil.Bytes `json:"data"`
|
||||
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
|
||||
TxIndex *hexutil.Uint `json:"transactionIndex"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
BlockHash *common.Hash `json:"blockHash"`
|
||||
Index *hexutil.Uint `json:"logIndex"`
|
||||
Removed bool `json:"removed"`
|
||||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (l *Log) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
||||
@ -98,54 +99,6 @@ func (l *Log) String() string {
|
||||
return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, l.Address, l.Topics, l.Data, l.TxHash, l.TxIndex, l.BlockHash, l.Index)
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (l *Log) MarshalJSON() ([]byte, error) {
|
||||
jslog := &jsonLog{
|
||||
Address: &l.Address,
|
||||
Topics: &l.Topics,
|
||||
Data: (*hexutil.Bytes)(&l.Data),
|
||||
TxIndex: (*hexutil.Uint)(&l.TxIndex),
|
||||
TxHash: &l.TxHash,
|
||||
Index: (*hexutil.Uint)(&l.Index),
|
||||
Removed: l.Removed,
|
||||
}
|
||||
// Set block information for mined logs.
|
||||
if (l.BlockHash != common.Hash{}) {
|
||||
jslog.BlockHash = &l.BlockHash
|
||||
jslog.BlockNumber = (*hexutil.Uint64)(&l.BlockNumber)
|
||||
}
|
||||
return json.Marshal(jslog)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Umarshaler.
|
||||
func (l *Log) UnmarshalJSON(input []byte) error {
|
||||
var dec jsonLog
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
if dec.Address == nil || dec.Topics == nil || dec.Data == nil ||
|
||||
dec.TxIndex == nil || dec.TxHash == nil || dec.Index == nil {
|
||||
return errMissingLogFields
|
||||
}
|
||||
declog := Log{
|
||||
Address: *dec.Address,
|
||||
Topics: *dec.Topics,
|
||||
Data: *dec.Data,
|
||||
TxHash: *dec.TxHash,
|
||||
TxIndex: uint(*dec.TxIndex),
|
||||
Index: uint(*dec.Index),
|
||||
Removed: dec.Removed,
|
||||
}
|
||||
// Block information may be missing if the log is received through
|
||||
// the pending log filter, so it's handled specially here.
|
||||
if dec.BlockHash != nil && dec.BlockNumber != nil {
|
||||
declog.BlockHash = *dec.BlockHash
|
||||
declog.BlockNumber = uint64(*dec.BlockNumber)
|
||||
}
|
||||
*l = declog
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
|
||||
// a log including non-consensus fields.
|
||||
type LogForStorage Log
|
||||
|
@ -18,6 +18,7 @@ package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@ -96,7 +97,7 @@ var unmarshalLogTests = map[string]struct {
|
||||
},
|
||||
"missing data": {
|
||||
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
|
||||
wantError: errMissingLogFields,
|
||||
wantError: fmt.Errorf("missing required field 'data' for Log"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
@ -28,33 +26,26 @@ import (
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingReceiptPostState = errors.New("missing post state root in JSON receipt")
|
||||
errMissingReceiptFields = errors.New("missing required JSON receipt fields")
|
||||
)
|
||||
//go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go
|
||||
|
||||
// Receipt represents the results of a transaction.
|
||||
type Receipt struct {
|
||||
// Consensus fields
|
||||
PostState []byte
|
||||
CumulativeGasUsed *big.Int
|
||||
Bloom Bloom
|
||||
Logs []*Log
|
||||
PostState []byte `json:"root"`
|
||||
CumulativeGasUsed *big.Int `json:"cumulativeGasUsed"`
|
||||
Bloom Bloom `json:"logsBloom"`
|
||||
Logs []*Log `json:"logs"`
|
||||
|
||||
// Implementation fields (don't reorder!)
|
||||
TxHash common.Hash
|
||||
ContractAddress common.Address
|
||||
GasUsed *big.Int
|
||||
TxHash common.Hash `json:"transactionHash"`
|
||||
ContractAddress common.Address `json:"contractAddress" optional:"true"`
|
||||
GasUsed *big.Int `json:"gasUsed"`
|
||||
}
|
||||
|
||||
type jsonReceipt struct {
|
||||
PostState *common.Hash `json:"root"`
|
||||
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
|
||||
Bloom *Bloom `json:"logsBloom"`
|
||||
Logs []*Log `json:"logs"`
|
||||
TxHash *common.Hash `json:"transactionHash"`
|
||||
ContractAddress *common.Address `json:"contractAddress"`
|
||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
||||
type receiptMarshaling struct {
|
||||
PostState hexutil.Bytes
|
||||
CumulativeGasUsed *hexutil.Big
|
||||
GasUsed *hexutil.Big
|
||||
}
|
||||
|
||||
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
||||
@ -84,51 +75,6 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON encodes receipts into the web3 RPC response block format.
|
||||
func (r *Receipt) MarshalJSON() ([]byte, error) {
|
||||
root := common.BytesToHash(r.PostState)
|
||||
|
||||
return json.Marshal(&jsonReceipt{
|
||||
PostState: &root,
|
||||
CumulativeGasUsed: (*hexutil.Big)(r.CumulativeGasUsed),
|
||||
Bloom: &r.Bloom,
|
||||
Logs: r.Logs,
|
||||
TxHash: &r.TxHash,
|
||||
ContractAddress: &r.ContractAddress,
|
||||
GasUsed: (*hexutil.Big)(r.GasUsed),
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes the web3 RPC receipt format.
|
||||
func (r *Receipt) UnmarshalJSON(input []byte) error {
|
||||
var dec jsonReceipt
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure that all fields are set. PostState is checked separately because it is a
|
||||
// recent addition to the RPC spec (as of August 2016) and older implementations might
|
||||
// not provide it. Note that ContractAddress is not checked because it can be null.
|
||||
if dec.PostState == nil {
|
||||
return errMissingReceiptPostState
|
||||
}
|
||||
if dec.CumulativeGasUsed == nil || dec.Bloom == nil ||
|
||||
dec.Logs == nil || dec.TxHash == nil || dec.GasUsed == nil {
|
||||
return errMissingReceiptFields
|
||||
}
|
||||
*r = Receipt{
|
||||
PostState: (*dec.PostState)[:],
|
||||
CumulativeGasUsed: (*big.Int)(dec.CumulativeGasUsed),
|
||||
Bloom: *dec.Bloom,
|
||||
Logs: dec.Logs,
|
||||
TxHash: *dec.TxHash,
|
||||
GasUsed: (*big.Int)(dec.GasUsed),
|
||||
}
|
||||
if dec.ContractAddress != nil {
|
||||
r.ContractAddress = *dec.ContractAddress
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (r *Receipt) String() string {
|
||||
return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs)
|
||||
|
@ -18,7 +18,6 @@ package types
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -32,12 +31,11 @@ import (
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var ErrInvalidSig = errors.New("invalid transaction v, r, s values")
|
||||
//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
|
||||
|
||||
var (
|
||||
errMissingTxSignatureFields = errors.New("missing required JSON transaction signature fields")
|
||||
errMissingTxFields = errors.New("missing required JSON transaction fields")
|
||||
errNoSigner = errors.New("missing signing methods")
|
||||
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
|
||||
errNoSigner = errors.New("missing signing methods")
|
||||
)
|
||||
|
||||
// deriveSigner makes a *best* guess about which signer to use.
|
||||
@ -58,26 +56,31 @@ type Transaction struct {
|
||||
}
|
||||
|
||||
type txdata struct {
|
||||
AccountNonce uint64
|
||||
Price, GasLimit *big.Int
|
||||
Recipient *common.Address `rlp:"nil"` // nil means contract creation
|
||||
Amount *big.Int
|
||||
Payload []byte
|
||||
V *big.Int // signature
|
||||
R, S *big.Int // signature
|
||||
AccountNonce uint64 `json:"nonce"`
|
||||
Price *big.Int `json:"gasPrice"`
|
||||
GasLimit *big.Int `json:"gasLimit"`
|
||||
Recipient *common.Address `json:"to" optional:"yes" rlp:"nil"` // nil means contract creation
|
||||
Amount *big.Int `json:"value"`
|
||||
Payload []byte `json:"input"`
|
||||
|
||||
// Signature values
|
||||
V *big.Int `json:"v"`
|
||||
R *big.Int `json:"r"`
|
||||
S *big.Int `json:"s"`
|
||||
|
||||
// This is only used when marshaling to JSON.
|
||||
Hash *common.Hash `json:"hash" optional:"yes" rlp:"-"`
|
||||
}
|
||||
|
||||
type jsonTransaction struct {
|
||||
Hash *common.Hash `json:"hash"`
|
||||
AccountNonce *hexutil.Uint64 `json:"nonce"`
|
||||
Price *hexutil.Big `json:"gasPrice"`
|
||||
GasLimit *hexutil.Big `json:"gas"`
|
||||
Recipient *common.Address `json:"to"`
|
||||
Amount *hexutil.Big `json:"value"`
|
||||
Payload *hexutil.Bytes `json:"input"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
type txdataMarshaling struct {
|
||||
AccountNonce hexutil.Uint64
|
||||
Price *hexutil.Big
|
||||
GasLimit *hexutil.Big
|
||||
Amount *hexutil.Big
|
||||
Payload hexutil.Bytes
|
||||
V *hexutil.Big
|
||||
R *hexutil.Big
|
||||
S *hexutil.Big
|
||||
}
|
||||
|
||||
func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
|
||||
@ -164,66 +167,30 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON encodes transactions into the web3 RPC response block format.
|
||||
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||
hash := tx.Hash()
|
||||
|
||||
return json.Marshal(&jsonTransaction{
|
||||
Hash: &hash,
|
||||
AccountNonce: (*hexutil.Uint64)(&tx.data.AccountNonce),
|
||||
Price: (*hexutil.Big)(tx.data.Price),
|
||||
GasLimit: (*hexutil.Big)(tx.data.GasLimit),
|
||||
Recipient: tx.data.Recipient,
|
||||
Amount: (*hexutil.Big)(tx.data.Amount),
|
||||
Payload: (*hexutil.Bytes)(&tx.data.Payload),
|
||||
V: (*hexutil.Big)(tx.data.V),
|
||||
R: (*hexutil.Big)(tx.data.R),
|
||||
S: (*hexutil.Big)(tx.data.S),
|
||||
})
|
||||
data := tx.data
|
||||
data.Hash = &hash
|
||||
return data.MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes the web3 RPC transaction format.
|
||||
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||
var dec jsonTransaction
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
var dec txdata
|
||||
if err := dec.UnmarshalJSON(input); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure that all fields are set. V, R, S are checked separately because they're a
|
||||
// recent addition to the RPC spec (as of August 2016) and older implementations might
|
||||
// not provide them. Note that Recipient is not checked because it can be missing for
|
||||
// contract creations.
|
||||
if dec.V == nil || dec.R == nil || dec.S == nil {
|
||||
return errMissingTxSignatureFields
|
||||
}
|
||||
|
||||
var V byte
|
||||
if isProtectedV((*big.Int)(dec.V)) {
|
||||
chainId := deriveChainId((*big.Int)(dec.V)).Uint64()
|
||||
V = byte(dec.V.ToInt().Uint64() - 35 - 2*chainId)
|
||||
if isProtectedV(dec.V) {
|
||||
chainId := deriveChainId(dec.V).Uint64()
|
||||
V = byte(dec.V.Uint64() - 35 - 2*chainId)
|
||||
} else {
|
||||
V = byte(((*big.Int)(dec.V)).Uint64() - 27)
|
||||
V = byte(dec.V.Uint64() - 27)
|
||||
}
|
||||
if !crypto.ValidateSignatureValues(V, (*big.Int)(dec.R), (*big.Int)(dec.S), false) {
|
||||
if !crypto.ValidateSignatureValues(V, dec.R, dec.S, false) {
|
||||
return ErrInvalidSig
|
||||
}
|
||||
|
||||
if dec.AccountNonce == nil || dec.Price == nil || dec.GasLimit == nil || dec.Amount == nil || dec.Payload == nil {
|
||||
return errMissingTxFields
|
||||
}
|
||||
// Assign the fields. This is not atomic but reusing transactions
|
||||
// for decoding isn't thread safe anyway.
|
||||
*tx = Transaction{}
|
||||
tx.data = txdata{
|
||||
AccountNonce: uint64(*dec.AccountNonce),
|
||||
Recipient: dec.Recipient,
|
||||
Amount: (*big.Int)(dec.Amount),
|
||||
GasLimit: (*big.Int)(dec.GasLimit),
|
||||
Price: (*big.Int)(dec.Price),
|
||||
Payload: *dec.Payload,
|
||||
V: (*big.Int)(dec.V),
|
||||
R: (*big.Int)(dec.R),
|
||||
S: (*big.Int)(dec.S),
|
||||
}
|
||||
*tx = Transaction{data: dec}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user