internal/ethapi: add missing output fields
- returned headers didn't include mixHash - returned transactions didn't include signature fields - empty transaction input was returned as "", but should be "0x" - returned receipts didn't include the bloom filter - "root" in receipts was missing 0x prefix
This commit is contained in:
		| @@ -588,24 +588,26 @@ func FormatLogs(structLogs []vm.StructLog) []StructLogRes { | |||||||
| // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain | // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain | ||||||
| // transaction hashes. | // transaction hashes. | ||||||
| func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { | func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { | ||||||
|  | 	head := b.Header() // copies the header once | ||||||
| 	fields := map[string]interface{}{ | 	fields := map[string]interface{}{ | ||||||
| 		"number":           rpc.NewHexNumber(b.Number()), | 		"number":           rpc.NewHexNumber(head.Number), | ||||||
| 		"hash":             b.Hash(), | 		"hash":             b.Hash(), | ||||||
| 		"parentHash":       b.ParentHash(), | 		"parentHash":       head.ParentHash, | ||||||
| 		"nonce":            b.Header().Nonce, | 		"nonce":            head.Nonce, | ||||||
| 		"sha3Uncles":       b.UncleHash(), | 		"mixHash":          head.MixDigest, | ||||||
| 		"logsBloom":        b.Bloom(), | 		"sha3Uncles":       head.UncleHash, | ||||||
| 		"stateRoot":        b.Root(), | 		"logsBloom":        head.Bloom, | ||||||
| 		"miner":            b.Coinbase(), | 		"stateRoot":        head.Root, | ||||||
| 		"difficulty":       rpc.NewHexNumber(b.Difficulty()), | 		"miner":            head.Coinbase, | ||||||
|  | 		"difficulty":       rpc.NewHexNumber(head.Difficulty), | ||||||
| 		"totalDifficulty":  rpc.NewHexNumber(s.b.GetTd(b.Hash())), | 		"totalDifficulty":  rpc.NewHexNumber(s.b.GetTd(b.Hash())), | ||||||
| 		"extraData":        fmt.Sprintf("0x%x", b.Extra()), | 		"extraData":        rpc.HexBytes(head.Extra), | ||||||
| 		"size":             rpc.NewHexNumber(b.Size().Int64()), | 		"size":             rpc.NewHexNumber(b.Size().Int64()), | ||||||
| 		"gasLimit":         rpc.NewHexNumber(b.GasLimit()), | 		"gasLimit":         rpc.NewHexNumber(head.GasLimit), | ||||||
| 		"gasUsed":          rpc.NewHexNumber(b.GasUsed()), | 		"gasUsed":          rpc.NewHexNumber(head.GasUsed), | ||||||
| 		"timestamp":        rpc.NewHexNumber(b.Time()), | 		"timestamp":        rpc.NewHexNumber(head.Time), | ||||||
| 		"transactionsRoot": b.TxHash(), | 		"transactionsRoot": head.TxHash, | ||||||
| 		"receiptRoot":      b.ReceiptHash(), | 		"receiptRoot":      head.ReceiptHash, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if inclTx { | 	if inclTx { | ||||||
| @@ -648,26 +650,32 @@ type RPCTransaction struct { | |||||||
| 	Gas              *rpc.HexNumber  `json:"gas"` | 	Gas              *rpc.HexNumber  `json:"gas"` | ||||||
| 	GasPrice         *rpc.HexNumber  `json:"gasPrice"` | 	GasPrice         *rpc.HexNumber  `json:"gasPrice"` | ||||||
| 	Hash             common.Hash     `json:"hash"` | 	Hash             common.Hash     `json:"hash"` | ||||||
| 	Input            string          `json:"input"` | 	Input            rpc.HexBytes    `json:"input"` | ||||||
| 	Nonce            *rpc.HexNumber  `json:"nonce"` | 	Nonce            *rpc.HexNumber  `json:"nonce"` | ||||||
| 	To               *common.Address `json:"to"` | 	To               *common.Address `json:"to"` | ||||||
| 	TransactionIndex *rpc.HexNumber  `json:"transactionIndex"` | 	TransactionIndex *rpc.HexNumber  `json:"transactionIndex"` | ||||||
| 	Value            *rpc.HexNumber  `json:"value"` | 	Value            *rpc.HexNumber  `json:"value"` | ||||||
|  | 	V                *rpc.HexNumber  `json:"v"` | ||||||
|  | 	R                *rpc.HexNumber  `json:"r"` | ||||||
|  | 	S                *rpc.HexNumber  `json:"s"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation | // newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation | ||||||
| func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { | func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { | ||||||
| 	from, _ := tx.FromFrontier() | 	from, _ := tx.FromFrontier() | ||||||
|  | 	v, r, s := tx.SignatureValues() | ||||||
| 	return &RPCTransaction{ | 	return &RPCTransaction{ | ||||||
| 		From:     from, | 		From:     from, | ||||||
| 		Gas:      rpc.NewHexNumber(tx.Gas()), | 		Gas:      rpc.NewHexNumber(tx.Gas()), | ||||||
| 		GasPrice: rpc.NewHexNumber(tx.GasPrice()), | 		GasPrice: rpc.NewHexNumber(tx.GasPrice()), | ||||||
| 		Hash:     tx.Hash(), | 		Hash:     tx.Hash(), | ||||||
| 		Input:    fmt.Sprintf("0x%x", tx.Data()), | 		Input:    rpc.HexBytes(tx.Data()), | ||||||
| 		Nonce:    rpc.NewHexNumber(tx.Nonce()), | 		Nonce:    rpc.NewHexNumber(tx.Nonce()), | ||||||
| 		To:       tx.To(), | 		To:       tx.To(), | ||||||
| 		Value:    rpc.NewHexNumber(tx.Value()), | 		Value:    rpc.NewHexNumber(tx.Value()), | ||||||
|  | 		V:        rpc.NewHexNumber(v), | ||||||
|  | 		R:        rpc.NewHexNumber(r), | ||||||
|  | 		S:        rpc.NewHexNumber(s), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -679,7 +687,7 @@ func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransacti | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  | 		v, r, s := tx.SignatureValues() | ||||||
| 		return &RPCTransaction{ | 		return &RPCTransaction{ | ||||||
| 			BlockHash:        b.Hash(), | 			BlockHash:        b.Hash(), | ||||||
| 			BlockNumber:      rpc.NewHexNumber(b.Number()), | 			BlockNumber:      rpc.NewHexNumber(b.Number()), | ||||||
| @@ -687,11 +695,14 @@ func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransacti | |||||||
| 			Gas:              rpc.NewHexNumber(tx.Gas()), | 			Gas:              rpc.NewHexNumber(tx.Gas()), | ||||||
| 			GasPrice:         rpc.NewHexNumber(tx.GasPrice()), | 			GasPrice:         rpc.NewHexNumber(tx.GasPrice()), | ||||||
| 			Hash:             tx.Hash(), | 			Hash:             tx.Hash(), | ||||||
| 			Input:            fmt.Sprintf("0x%x", tx.Data()), | 			Input:            rpc.HexBytes(tx.Data()), | ||||||
| 			Nonce:            rpc.NewHexNumber(tx.Nonce()), | 			Nonce:            rpc.NewHexNumber(tx.Nonce()), | ||||||
| 			To:               tx.To(), | 			To:               tx.To(), | ||||||
| 			TransactionIndex: rpc.NewHexNumber(txIndex), | 			TransactionIndex: rpc.NewHexNumber(txIndex), | ||||||
| 			Value:            rpc.NewHexNumber(tx.Value()), | 			Value:            rpc.NewHexNumber(tx.Value()), | ||||||
|  | 			V:                rpc.NewHexNumber(v), | ||||||
|  | 			R:                rpc.NewHexNumber(r), | ||||||
|  | 			S:                rpc.NewHexNumber(s), | ||||||
| 		}, nil | 		}, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -861,7 +872,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	fields := map[string]interface{}{ | 	fields := map[string]interface{}{ | ||||||
| 		"root":              common.Bytes2Hex(receipt.PostState), | 		"root":              rpc.HexBytes(receipt.PostState), | ||||||
| 		"blockHash":         txBlock, | 		"blockHash":         txBlock, | ||||||
| 		"blockNumber":       rpc.NewHexNumber(blockIndex), | 		"blockNumber":       rpc.NewHexNumber(blockIndex), | ||||||
| 		"transactionHash":   txHash, | 		"transactionHash":   txHash, | ||||||
| @@ -872,17 +883,15 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | |||||||
| 		"cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed), | 		"cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed), | ||||||
| 		"contractAddress":   nil, | 		"contractAddress":   nil, | ||||||
| 		"logs":              receipt.Logs, | 		"logs":              receipt.Logs, | ||||||
|  | 		"logsBloom":         receipt.Bloom, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if receipt.Logs == nil { | 	if receipt.Logs == nil { | ||||||
| 		fields["logs"] = []vm.Logs{} | 		fields["logs"] = []vm.Logs{} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation | 	// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation | ||||||
| 	if bytes.Compare(receipt.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 { | 	if receipt.ContractAddress != (common.Address{}) { | ||||||
| 		fields["contractAddress"] = receipt.ContractAddress | 		fields["contractAddress"] = receipt.ContractAddress | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return fields, nil | 	return fields, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								rpc/types.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								rpc/types.go
									
									
									
									
									
								
							| @@ -17,6 +17,8 @@ | |||||||
| package rpc | package rpc | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/hex" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"math" | 	"math" | ||||||
| 	"math/big" | 	"math/big" | ||||||
| @@ -272,3 +274,31 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { | |||||||
| func (bn BlockNumber) Int64() int64 { | func (bn BlockNumber) Int64() int64 { | ||||||
| 	return (int64)(bn) | 	return (int64)(bn) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // HexBytes JSON-encodes as hex with 0x prefix. | ||||||
|  | type HexBytes []byte | ||||||
|  |  | ||||||
|  | func (b HexBytes) MarshalJSON() ([]byte, error) { | ||||||
|  | 	result := make([]byte, len(b)*2+4) | ||||||
|  | 	copy(result, `"0x`) | ||||||
|  | 	hex.Encode(result[3:], b) | ||||||
|  | 	result[len(result)-1] = '"' | ||||||
|  | 	return result, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (b *HexBytes) UnmarshalJSON(input []byte) error { | ||||||
|  | 	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' { | ||||||
|  | 		input = input[1 : len(input)-1] | ||||||
|  | 	} | ||||||
|  | 	if !bytes.HasPrefix(input, []byte("0x")) { | ||||||
|  | 		return fmt.Errorf("missing 0x prefix for hex byte array") | ||||||
|  | 	} | ||||||
|  | 	input = input[2:] | ||||||
|  | 	if len(input) == 0 { | ||||||
|  | 		*b = nil | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	*b = make([]byte, len(input)/2) | ||||||
|  | 	_, err := hex.Decode(*b, input) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|   | |||||||
| @@ -71,3 +71,25 @@ func TestHexNumberMarshalJSON(t *testing.T) { | |||||||
| 		t.Fatalf("Invalid json.Marshal, expected '%s', got '%s'", exp, got) | 		t.Fatalf("Invalid json.Marshal, expected '%s', got '%s'", exp, got) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var hexBytesTests = []struct{ in, out []byte }{ | ||||||
|  | 	{in: []byte(`"0x"`), out: []byte{}}, | ||||||
|  | 	{in: []byte(`"0x00"`), out: []byte{0}}, | ||||||
|  | 	{in: []byte(`"0x01ff"`), out: []byte{0x01, 0xFF}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestHexBytes(t *testing.T) { | ||||||
|  | 	for i, test := range hexBytesTests { | ||||||
|  | 		var dec HexBytes | ||||||
|  | 		if err := json.Unmarshal(test.in, &dec); err != nil { | ||||||
|  | 			t.Fatalf("test %d: can't decode: %v", i, err) | ||||||
|  | 		} | ||||||
|  | 		enc, _ := json.Marshal(HexBytes(test.out)) | ||||||
|  | 		if !bytes.Equal(dec, test.out) { | ||||||
|  | 			t.Errorf("test %d: wrong decoded value 0x%x", i, dec) | ||||||
|  | 		} | ||||||
|  | 		if !bytes.Equal(enc, test.in) { | ||||||
|  | 			t.Errorf("test %d: wrong encoded value %#q", i, enc) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user