Merge pull request #3756 from fjl/core-types-gencodec
core/types: use gencodec for JSON marshaling code
This commit is contained in:
commit
06d6685eb5
9
Makefile
9
Makefile
@ -40,6 +40,15 @@ test: all
|
|||||||
clean:
|
clean:
|
||||||
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
||||||
|
|
||||||
|
# The devtools target installs tools required for 'go generate'.
|
||||||
|
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
|
||||||
|
|
||||||
|
devtools:
|
||||||
|
go get -u golang.org/x/tools/cmd/stringer
|
||||||
|
go get -u github.com/jteeuwen/go-bindata/go-bindata
|
||||||
|
go get -u github.com/fjl/gencodec
|
||||||
|
go install ./cmd/abigen
|
||||||
|
|
||||||
# Cross Compilation Targets (xgo)
|
# Cross Compilation Targets (xgo)
|
||||||
|
|
||||||
geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios
|
geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios
|
||||||
|
@ -19,8 +19,6 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -39,12 +37,6 @@ var (
|
|||||||
EmptyUncleHash = CalcUncleHash(nil)
|
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
|
// A BlockNonce is a 64-bit hash which proves (combined with the
|
||||||
// mix-hash) that a sufficient amount of computation has been carried
|
// mix-hash) that a sufficient amount of computation has been carried
|
||||||
// out on a block.
|
// out on a block.
|
||||||
@ -72,41 +64,35 @@ func (n *BlockNonce) UnmarshalText(input []byte) error {
|
|||||||
return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
|
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.
|
// Header represents a block header in the Ethereum blockchain.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
ParentHash common.Hash // Hash to the previous block
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
UncleHash common.Hash // Uncles of this block
|
UncleHash common.Hash `json:"sha3Uncles"`
|
||||||
Coinbase common.Address // The coin base address
|
Coinbase common.Address `json:"miner"`
|
||||||
Root common.Hash // Block Trie state
|
Root common.Hash `json:"stateRoot"`
|
||||||
TxHash common.Hash // Tx sha
|
TxHash common.Hash `json:"transactionsRoot"`
|
||||||
ReceiptHash common.Hash // Receipt sha
|
ReceiptHash common.Hash `json:"receiptsRoot"`
|
||||||
Bloom Bloom // Bloom
|
Bloom Bloom `json:"logsBloom"`
|
||||||
Difficulty *big.Int // Difficulty for the current block
|
Difficulty *big.Int `json:"difficulty"`
|
||||||
Number *big.Int // The block number
|
Number *big.Int `json:"number"`
|
||||||
GasLimit *big.Int // Gas limit
|
GasLimit *big.Int `json:"gasLimit"`
|
||||||
GasUsed *big.Int // Gas used
|
GasUsed *big.Int `json:"gasUsed"`
|
||||||
Time *big.Int // Creation time
|
Time *big.Int `json:"timestamp"`
|
||||||
Extra []byte // Extra data
|
Extra []byte `json:"extraData"`
|
||||||
MixDigest common.Hash // for quick difficulty verification
|
MixDigest common.Hash `json:"mixHash"`
|
||||||
Nonce BlockNonce
|
Nonce BlockNonce `json:"nonce"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type jsonHeader struct {
|
// field type overrides for gencodec
|
||||||
ParentHash *common.Hash `json:"parentHash"`
|
type headerMarshaling struct {
|
||||||
UncleHash *common.Hash `json:"sha3Uncles"`
|
Difficulty *hexutil.Big
|
||||||
Coinbase *common.Address `json:"miner"`
|
Number *hexutil.Big
|
||||||
Root *common.Hash `json:"stateRoot"`
|
GasLimit *hexutil.Big
|
||||||
TxHash *common.Hash `json:"transactionsRoot"`
|
GasUsed *hexutil.Big
|
||||||
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
Time *hexutil.Big
|
||||||
Bloom *Bloom `json:"logsBloom"`
|
Extra hexutil.Bytes
|
||||||
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"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
|
// 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) {
|
func rlpHash(x interface{}) (h common.Hash) {
|
||||||
hw := sha3.NewKeccak256()
|
hw := sha3.NewKeccak256()
|
||||||
rlp.Encode(hw, x)
|
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
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
@ -27,27 +25,42 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"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
|
// Log represents a contract log event. These events are generated by the LOG opcode and
|
||||||
// stored/indexed by the node.
|
// stored/indexed by the node.
|
||||||
type Log struct {
|
type Log struct {
|
||||||
// Consensus fields.
|
// Consensus fields:
|
||||||
Address common.Address // address of the contract that generated the event
|
// address of the contract that generated the event
|
||||||
Topics []common.Hash // list of topics provided by the contract.
|
Address common.Address `json:"address"`
|
||||||
Data []byte // supplied by the contract, usually ABI-encoded
|
// 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
|
// Derived fields. These fields are filled in by the node
|
||||||
// but not secured by consensus.
|
// but not secured by consensus.
|
||||||
BlockNumber uint64 // block in which the transaction was included
|
// block in which the transaction was included
|
||||||
TxHash common.Hash // hash of the transaction
|
BlockNumber uint64 `json:"blockNumber" optional:"yes"`
|
||||||
TxIndex uint // index of the transaction in the block
|
// hash of the transaction
|
||||||
BlockHash common.Hash // hash of the block in which the transaction was included
|
TxHash common.Hash `json:"transactionHash"`
|
||||||
Index uint // index of the log in the receipt
|
// 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.
|
// 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.
|
// 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 {
|
type rlpLog struct {
|
||||||
@ -67,18 +80,6 @@ type rlpStorageLog struct {
|
|||||||
Index uint
|
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.
|
// EncodeRLP implements rlp.Encoder.
|
||||||
func (l *Log) EncodeRLP(w io.Writer) error {
|
func (l *Log) EncodeRLP(w io.Writer) error {
|
||||||
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
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)
|
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
|
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
|
||||||
// a log including non-consensus fields.
|
// a log including non-consensus fields.
|
||||||
type LogForStorage Log
|
type LogForStorage Log
|
||||||
|
@ -18,6 +18,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ var unmarshalLogTests = map[string]struct {
|
|||||||
},
|
},
|
||||||
"missing data": {
|
"missing data": {
|
||||||
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
|
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
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -28,33 +26,26 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
//go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go
|
||||||
errMissingReceiptPostState = errors.New("missing post state root in JSON receipt")
|
|
||||||
errMissingReceiptFields = errors.New("missing required JSON receipt fields")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Receipt represents the results of a transaction.
|
// Receipt represents the results of a transaction.
|
||||||
type Receipt struct {
|
type Receipt struct {
|
||||||
// Consensus fields
|
// Consensus fields
|
||||||
PostState []byte
|
PostState []byte `json:"root"`
|
||||||
CumulativeGasUsed *big.Int
|
CumulativeGasUsed *big.Int `json:"cumulativeGasUsed"`
|
||||||
Bloom Bloom
|
Bloom Bloom `json:"logsBloom"`
|
||||||
Logs []*Log
|
Logs []*Log `json:"logs"`
|
||||||
|
|
||||||
// Implementation fields (don't reorder!)
|
// Implementation fields (don't reorder!)
|
||||||
TxHash common.Hash
|
TxHash common.Hash `json:"transactionHash"`
|
||||||
ContractAddress common.Address
|
ContractAddress common.Address `json:"contractAddress" optional:"true"`
|
||||||
GasUsed *big.Int
|
GasUsed *big.Int `json:"gasUsed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type jsonReceipt struct {
|
type receiptMarshaling struct {
|
||||||
PostState *common.Hash `json:"root"`
|
PostState hexutil.Bytes
|
||||||
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
|
CumulativeGasUsed *hexutil.Big
|
||||||
Bloom *Bloom `json:"logsBloom"`
|
GasUsed *hexutil.Big
|
||||||
Logs []*Log `json:"logs"`
|
|
||||||
TxHash *common.Hash `json:"transactionHash"`
|
|
||||||
ContractAddress *common.Address `json:"contractAddress"`
|
|
||||||
GasUsed *hexutil.Big `json:"gasUsed"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
||||||
@ -84,51 +75,6 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
|||||||
return nil
|
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.
|
// String implements the Stringer interface.
|
||||||
func (r *Receipt) String() string {
|
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)
|
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 (
|
import (
|
||||||
"container/heap"
|
"container/heap"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -32,12 +31,11 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"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 (
|
var (
|
||||||
errMissingTxSignatureFields = errors.New("missing required JSON transaction signature fields")
|
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
|
||||||
errMissingTxFields = errors.New("missing required JSON transaction fields")
|
errNoSigner = errors.New("missing signing methods")
|
||||||
errNoSigner = errors.New("missing signing methods")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// deriveSigner makes a *best* guess about which signer to use.
|
// deriveSigner makes a *best* guess about which signer to use.
|
||||||
@ -58,26 +56,31 @@ type Transaction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type txdata struct {
|
type txdata struct {
|
||||||
AccountNonce uint64
|
AccountNonce uint64 `json:"nonce"`
|
||||||
Price, GasLimit *big.Int
|
Price *big.Int `json:"gasPrice"`
|
||||||
Recipient *common.Address `rlp:"nil"` // nil means contract creation
|
GasLimit *big.Int `json:"gasLimit"`
|
||||||
Amount *big.Int
|
Recipient *common.Address `json:"to" optional:"yes" rlp:"nil"` // nil means contract creation
|
||||||
Payload []byte
|
Amount *big.Int `json:"value"`
|
||||||
V *big.Int // signature
|
Payload []byte `json:"input"`
|
||||||
R, S *big.Int // signature
|
|
||||||
|
// 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 {
|
type txdataMarshaling struct {
|
||||||
Hash *common.Hash `json:"hash"`
|
AccountNonce hexutil.Uint64
|
||||||
AccountNonce *hexutil.Uint64 `json:"nonce"`
|
Price *hexutil.Big
|
||||||
Price *hexutil.Big `json:"gasPrice"`
|
GasLimit *hexutil.Big
|
||||||
GasLimit *hexutil.Big `json:"gas"`
|
Amount *hexutil.Big
|
||||||
Recipient *common.Address `json:"to"`
|
Payload hexutil.Bytes
|
||||||
Amount *hexutil.Big `json:"value"`
|
V *hexutil.Big
|
||||||
Payload *hexutil.Bytes `json:"input"`
|
R *hexutil.Big
|
||||||
V *hexutil.Big `json:"v"`
|
S *hexutil.Big
|
||||||
R *hexutil.Big `json:"r"`
|
|
||||||
S *hexutil.Big `json:"s"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes transactions into the web3 RPC response block format.
|
|
||||||
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
func (tx *Transaction) MarshalJSON() ([]byte, error) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
|
data := tx.data
|
||||||
return json.Marshal(&jsonTransaction{
|
data.Hash = &hash
|
||||||
Hash: &hash,
|
return data.MarshalJSON()
|
||||||
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),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON decodes the web3 RPC transaction format.
|
// UnmarshalJSON decodes the web3 RPC transaction format.
|
||||||
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
func (tx *Transaction) UnmarshalJSON(input []byte) error {
|
||||||
var dec jsonTransaction
|
var dec txdata
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := dec.UnmarshalJSON(input); err != nil {
|
||||||
return err
|
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
|
var V byte
|
||||||
if isProtectedV((*big.Int)(dec.V)) {
|
if isProtectedV(dec.V) {
|
||||||
chainId := deriveChainId((*big.Int)(dec.V)).Uint64()
|
chainId := deriveChainId(dec.V).Uint64()
|
||||||
V = byte(dec.V.ToInt().Uint64() - 35 - 2*chainId)
|
V = byte(dec.V.Uint64() - 35 - 2*chainId)
|
||||||
} else {
|
} 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
|
return ErrInvalidSig
|
||||||
}
|
}
|
||||||
|
*tx = Transaction{data: dec}
|
||||||
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),
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ func bignumberJs() (*asset, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "bignumber.js", size: 17314, mode: os.FileMode(420), modTime: time.Unix(1484232218, 0)}
|
info := bindataFileInfo{name: "bignumber.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ func web3Js() (*asset, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "web3.js", size: 491740, mode: os.FileMode(420), modTime: time.Unix(1484232456, 0)}
|
info := bindataFileInfo{name: "web3.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
@ -17,4 +17,5 @@
|
|||||||
// Package deps contains the console JavaScript dependencies Go embedded.
|
// Package deps contains the console JavaScript dependencies Go embedded.
|
||||||
package deps
|
package deps
|
||||||
|
|
||||||
//go:generate go-bindata -o bindata.go bignumber.js web3.js
|
//go:generate go-bindata -nometadata -pkg deps -o bindata.go bignumber.js web3.js
|
||||||
|
//go:generate gofmt -w -s bindata.go
|
||||||
|
@ -63,12 +63,16 @@ type Decoder interface {
|
|||||||
// must contain an element for each decoded field. Decode returns an
|
// must contain an element for each decoded field. Decode returns an
|
||||||
// error if there are too few or too many elements.
|
// error if there are too few or too many elements.
|
||||||
//
|
//
|
||||||
// The decoding of struct fields honours two struct tags, "tail" and
|
// The decoding of struct fields honours certain struct tags, "tail",
|
||||||
// "nil". For an explanation of "tail", see the example.
|
// "nil" and "-".
|
||||||
// The "nil" tag applies to pointer-typed fields and changes the
|
//
|
||||||
// decoding rules for the field such that input values of size zero
|
// The "-" tag ignores fields.
|
||||||
// decode as a nil pointer. This tag can be useful when decoding
|
//
|
||||||
// recursive types.
|
// For an explanation of "tail", see the example.
|
||||||
|
//
|
||||||
|
// The "nil" tag applies to pointer-typed fields and changes the decoding
|
||||||
|
// rules for the field such that input values of size zero decode as a nil
|
||||||
|
// pointer. This tag can be useful when decoding recursive types.
|
||||||
//
|
//
|
||||||
// type StructWithEmptyOK struct {
|
// type StructWithEmptyOK struct {
|
||||||
// Foo *[20]byte `rlp:"nil"`
|
// Foo *[20]byte `rlp:"nil"`
|
||||||
|
@ -339,6 +339,12 @@ var (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type hasIgnoredField struct {
|
||||||
|
A uint
|
||||||
|
B uint `rlp:"-"`
|
||||||
|
C uint
|
||||||
|
}
|
||||||
|
|
||||||
var decodeTests = []decodeTest{
|
var decodeTests = []decodeTest{
|
||||||
// booleans
|
// booleans
|
||||||
{input: "01", ptr: new(bool), value: true},
|
{input: "01", ptr: new(bool), value: true},
|
||||||
@ -490,6 +496,13 @@ var decodeTests = []decodeTest{
|
|||||||
value: tailRaw{A: 1, Tail: []RawValue{}},
|
value: tailRaw{A: 1, Tail: []RawValue{}},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// struct tag "-"
|
||||||
|
{
|
||||||
|
input: "C20102",
|
||||||
|
ptr: new(hasIgnoredField),
|
||||||
|
value: hasIgnoredField{A: 1, C: 2},
|
||||||
|
},
|
||||||
|
|
||||||
// RawValue
|
// RawValue
|
||||||
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
|
{input: "01", ptr: new(RawValue), value: RawValue(unhex("01"))},
|
||||||
{input: "82FFFF", ptr: new(RawValue), value: RawValue(unhex("82FFFF"))},
|
{input: "82FFFF", ptr: new(RawValue), value: RawValue(unhex("82FFFF"))},
|
||||||
|
@ -218,6 +218,7 @@ var encTests = []encTest{
|
|||||||
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
|
{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
|
||||||
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
|
||||||
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
|
||||||
|
{val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"},
|
||||||
|
|
||||||
// nil
|
// nil
|
||||||
{val: (*uint)(nil), output: "80"},
|
{val: (*uint)(nil), output: "80"},
|
||||||
|
@ -37,11 +37,12 @@ type typeinfo struct {
|
|||||||
type tags struct {
|
type tags struct {
|
||||||
// rlp:"nil" controls whether empty input results in a nil pointer.
|
// rlp:"nil" controls whether empty input results in a nil pointer.
|
||||||
nilOK bool
|
nilOK bool
|
||||||
|
|
||||||
// rlp:"tail" controls whether this field swallows additional list
|
// rlp:"tail" controls whether this field swallows additional list
|
||||||
// elements. It can only be set for the last field, which must be
|
// elements. It can only be set for the last field, which must be
|
||||||
// of slice type.
|
// of slice type.
|
||||||
tail bool
|
tail bool
|
||||||
|
// rlp:"-" ignores fields.
|
||||||
|
ignored bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type typekey struct {
|
type typekey struct {
|
||||||
@ -101,6 +102,9 @@ func structFields(typ reflect.Type) (fields []field, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if tags.ignored {
|
||||||
|
continue
|
||||||
|
}
|
||||||
info, err := cachedTypeInfo1(f.Type, tags)
|
info, err := cachedTypeInfo1(f.Type, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -117,6 +121,8 @@ func parseStructTag(typ reflect.Type, fi int) (tags, error) {
|
|||||||
for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
|
for _, t := range strings.Split(f.Tag.Get("rlp"), ",") {
|
||||||
switch t = strings.TrimSpace(t); t {
|
switch t = strings.TrimSpace(t); t {
|
||||||
case "":
|
case "":
|
||||||
|
case "-":
|
||||||
|
ts.ignored = true
|
||||||
case "nil":
|
case "nil":
|
||||||
ts.nilOK = true
|
ts.nilOK = true
|
||||||
case "tail":
|
case "tail":
|
||||||
|
Loading…
Reference in New Issue
Block a user