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 | ||||
| // transaction hashes. | ||||
| 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{}{ | ||||
| 		"number":           rpc.NewHexNumber(b.Number()), | ||||
| 		"number":           rpc.NewHexNumber(head.Number), | ||||
| 		"hash":             b.Hash(), | ||||
| 		"parentHash":       b.ParentHash(), | ||||
| 		"nonce":            b.Header().Nonce, | ||||
| 		"sha3Uncles":       b.UncleHash(), | ||||
| 		"logsBloom":        b.Bloom(), | ||||
| 		"stateRoot":        b.Root(), | ||||
| 		"miner":            b.Coinbase(), | ||||
| 		"difficulty":       rpc.NewHexNumber(b.Difficulty()), | ||||
| 		"parentHash":       head.ParentHash, | ||||
| 		"nonce":            head.Nonce, | ||||
| 		"mixHash":          head.MixDigest, | ||||
| 		"sha3Uncles":       head.UncleHash, | ||||
| 		"logsBloom":        head.Bloom, | ||||
| 		"stateRoot":        head.Root, | ||||
| 		"miner":            head.Coinbase, | ||||
| 		"difficulty":       rpc.NewHexNumber(head.Difficulty), | ||||
| 		"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()), | ||||
| 		"gasLimit":         rpc.NewHexNumber(b.GasLimit()), | ||||
| 		"gasUsed":          rpc.NewHexNumber(b.GasUsed()), | ||||
| 		"timestamp":        rpc.NewHexNumber(b.Time()), | ||||
| 		"transactionsRoot": b.TxHash(), | ||||
| 		"receiptRoot":      b.ReceiptHash(), | ||||
| 		"gasLimit":         rpc.NewHexNumber(head.GasLimit), | ||||
| 		"gasUsed":          rpc.NewHexNumber(head.GasUsed), | ||||
| 		"timestamp":        rpc.NewHexNumber(head.Time), | ||||
| 		"transactionsRoot": head.TxHash, | ||||
| 		"receiptRoot":      head.ReceiptHash, | ||||
| 	} | ||||
|  | ||||
| 	if inclTx { | ||||
| @@ -648,26 +650,32 @@ type RPCTransaction struct { | ||||
| 	Gas              *rpc.HexNumber  `json:"gas"` | ||||
| 	GasPrice         *rpc.HexNumber  `json:"gasPrice"` | ||||
| 	Hash             common.Hash     `json:"hash"` | ||||
| 	Input            string          `json:"input"` | ||||
| 	Input            rpc.HexBytes    `json:"input"` | ||||
| 	Nonce            *rpc.HexNumber  `json:"nonce"` | ||||
| 	To               *common.Address `json:"to"` | ||||
| 	TransactionIndex *rpc.HexNumber  `json:"transactionIndex"` | ||||
| 	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 | ||||
| func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { | ||||
| 	from, _ := tx.FromFrontier() | ||||
|  | ||||
| 	v, r, s := tx.SignatureValues() | ||||
| 	return &RPCTransaction{ | ||||
| 		From:     from, | ||||
| 		Gas:      rpc.NewHexNumber(tx.Gas()), | ||||
| 		GasPrice: rpc.NewHexNumber(tx.GasPrice()), | ||||
| 		Hash:     tx.Hash(), | ||||
| 		Input:    fmt.Sprintf("0x%x", tx.Data()), | ||||
| 		Input:    rpc.HexBytes(tx.Data()), | ||||
| 		Nonce:    rpc.NewHexNumber(tx.Nonce()), | ||||
| 		To:       tx.To(), | ||||
| 		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 { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		v, r, s := tx.SignatureValues() | ||||
| 		return &RPCTransaction{ | ||||
| 			BlockHash:        b.Hash(), | ||||
| 			BlockNumber:      rpc.NewHexNumber(b.Number()), | ||||
| @@ -687,11 +695,14 @@ func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransacti | ||||
| 			Gas:              rpc.NewHexNumber(tx.Gas()), | ||||
| 			GasPrice:         rpc.NewHexNumber(tx.GasPrice()), | ||||
| 			Hash:             tx.Hash(), | ||||
| 			Input:            fmt.Sprintf("0x%x", tx.Data()), | ||||
| 			Input:            rpc.HexBytes(tx.Data()), | ||||
| 			Nonce:            rpc.NewHexNumber(tx.Nonce()), | ||||
| 			To:               tx.To(), | ||||
| 			TransactionIndex: rpc.NewHexNumber(txIndex), | ||||
| 			Value:            rpc.NewHexNumber(tx.Value()), | ||||
| 			V:                rpc.NewHexNumber(v), | ||||
| 			R:                rpc.NewHexNumber(r), | ||||
| 			S:                rpc.NewHexNumber(s), | ||||
| 		}, nil | ||||
| 	} | ||||
|  | ||||
| @@ -861,7 +872,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | ||||
| 	} | ||||
|  | ||||
| 	fields := map[string]interface{}{ | ||||
| 		"root":              common.Bytes2Hex(receipt.PostState), | ||||
| 		"root":              rpc.HexBytes(receipt.PostState), | ||||
| 		"blockHash":         txBlock, | ||||
| 		"blockNumber":       rpc.NewHexNumber(blockIndex), | ||||
| 		"transactionHash":   txHash, | ||||
| @@ -872,17 +883,15 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma | ||||
| 		"cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed), | ||||
| 		"contractAddress":   nil, | ||||
| 		"logs":              receipt.Logs, | ||||
| 		"logsBloom":         receipt.Bloom, | ||||
| 	} | ||||
|  | ||||
| 	if receipt.Logs == nil { | ||||
| 		fields["logs"] = []vm.Logs{} | ||||
| 	} | ||||
|  | ||||
| 	// 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 | ||||
| 	} | ||||
|  | ||||
| 	return fields, nil | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										30
									
								
								rpc/types.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								rpc/types.go
									
									
									
									
									
								
							| @@ -17,6 +17,8 @@ | ||||
| package rpc | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"math/big" | ||||
| @@ -272,3 +274,31 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { | ||||
| func (bn BlockNumber) Int64() int64 { | ||||
| 	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) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 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