Skip to content

Commit

Permalink
Merge pull request ethereum#2984 from karalabe/fix-head-sub
Browse files Browse the repository at this point in the history
core/types, ethclient: fix broken subscriptions
  • Loading branch information
bas-vk authored Sep 9, 2016
2 parents 6fb8ae2 + b6b5ec8 commit b7f6404
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 1 deletion.
21 changes: 21 additions & 0 deletions core/types/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ import (

type hexBytes []byte

func (b *hexBytes) MarshalJSON() ([]byte, error) {
if b != nil {
return []byte(fmt.Sprintf(`"0x%x"`, []byte(*b))), nil
}
return nil, nil
}

func (b *hexBytes) UnmarshalJSON(input []byte) error {
if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' {
return fmt.Errorf("cannot unmarshal non-string into hexBytes")
Expand All @@ -44,6 +51,13 @@ func (b *hexBytes) UnmarshalJSON(input []byte) error {

type hexBig big.Int

func (b *hexBig) MarshalJSON() ([]byte, error) {
if b != nil {
return []byte(fmt.Sprintf(`"0x%x"`, (*big.Int)(b))), nil
}
return nil, nil
}

func (b *hexBig) UnmarshalJSON(input []byte) error {
raw, err := checkHexNumber(input)
if err != nil {
Expand All @@ -59,6 +73,13 @@ func (b *hexBig) UnmarshalJSON(input []byte) error {

type hexUint64 uint64

func (b *hexUint64) MarshalJSON() ([]byte, error) {
if b != nil {
return []byte(fmt.Sprintf(`"0x%x"`, *(*uint64)(b))), nil
}
return nil, nil
}

func (b *hexUint64) UnmarshalJSON(input []byte) error {
raw, err := checkHexNumber(input)
if err != nil {
Expand Down
77 changes: 77 additions & 0 deletions core/types/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"encoding/json"
"reflect"
"testing"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -44,6 +45,31 @@ func TestUnmarshalHeader(t *testing.T) {
}
}

func TestMarshalHeader(t *testing.T) {
for name, test := range unmarshalHeaderTests {
if test.wantError != nil {
continue
}
var original *Header
json.Unmarshal([]byte(test.input), &original)

blob, err := json.Marshal(original)
if err != nil {
t.Errorf("test %q: failed to marshal header: %v", name, err)
continue
}
var proced *Header
if err := json.Unmarshal(blob, &proced); err != nil {
t.Errorf("Test %q: failed to unmarshal marhsalled header: %v", name, err)
continue
}
if !reflect.DeepEqual(original, proced) {
t.Errorf("test %q: header mismatch: have %+v, want %+v", name, proced, original)
continue
}
}
}

var unmarshalTransactionTests = map[string]struct {
input string
wantHash common.Hash
Expand Down Expand Up @@ -94,6 +120,32 @@ func TestUnmarshalTransaction(t *testing.T) {
}
}

func TestMarshalTransaction(t *testing.T) {
for name, test := range unmarshalTransactionTests {
if test.wantError != nil {
continue
}
var original *Transaction
json.Unmarshal([]byte(test.input), &original)

blob, err := json.Marshal(original)
if err != nil {
t.Errorf("test %q: failed to marshal transaction: %v", name, err)
continue
}
var proced *Transaction
if err := json.Unmarshal(blob, &proced); err != nil {
t.Errorf("Test %q: failed to unmarshal marhsalled transaction: %v", name, err)
continue
}
proced.Hash() // hack private fields to pass deep equal
if !reflect.DeepEqual(original, proced) {
t.Errorf("test %q: transaction mismatch: have %+v, want %+v", name, proced, original)
continue
}
}
}

var unmarshalReceiptTests = map[string]struct {
input string
wantError error
Expand All @@ -119,6 +171,31 @@ func TestUnmarshalReceipt(t *testing.T) {
}
}

func TestMarshalReceipt(t *testing.T) {
for name, test := range unmarshalReceiptTests {
if test.wantError != nil {
continue
}
var original *Receipt
json.Unmarshal([]byte(test.input), &original)

blob, err := json.Marshal(original)
if err != nil {
t.Errorf("test %q: failed to marshal receipt: %v", name, err)
continue
}
var proced *Receipt
if err := json.Unmarshal(blob, &proced); err != nil {
t.Errorf("Test %q: failed to unmarshal marhsalled receipt: %v", name, err)
continue
}
if !reflect.DeepEqual(original, proced) {
t.Errorf("test %q: receipt mismatch: have %+v, want %+v", name, proced, original)
continue
}
}
}

func checkError(t *testing.T, testname string, got, want error) bool {
if got == nil {
if want != nil {
Expand Down
15 changes: 15 additions & 0 deletions core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ 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: (*hexBig)(r.CumulativeGasUsed),
Bloom: &r.Bloom,
Logs: &r.Logs,
TxHash: &r.TxHash,
ContractAddress: &r.ContractAddress,
GasUsed: (*hexBig)(r.GasUsed),
})
}

// UnmarshalJSON decodes the web3 RPC receipt format.
func (r *Receipt) UnmarshalJSON(input []byte) error {
var dec jsonReceipt
Expand Down
18 changes: 18 additions & 0 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ 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, v := tx.Hash(), uint64(tx.data.V)

return json.Marshal(&jsonTransaction{
Hash: &hash,
AccountNonce: (*hexUint64)(&tx.data.AccountNonce),
Price: (*hexBig)(tx.data.Price),
GasLimit: (*hexBig)(tx.data.GasLimit),
Recipient: tx.data.Recipient,
Amount: (*hexBig)(tx.data.Amount),
Payload: (*hexBytes)(&tx.data.Payload),
V: (*hexUint64)(&v),
R: (*hexBig)(tx.data.R),
S: (*hexBig)(tx.data.S),
})
}

// UnmarshalJSON decodes the web3 RPC transaction format.
func (tx *Transaction) UnmarshalJSON(input []byte) error {
var dec jsonTransaction
Expand Down
2 changes: 1 addition & 1 deletion ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, err
// SubscribeNewHead subscribes to notifications about the current blockchain head
// on the given channel.
func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
return ec.c.EthSubscribe(ctx, ch, "newBlocks", map[string]struct{}{})
return ec.c.EthSubscribe(ctx, ch, "newHeads", map[string]struct{}{})
}

// State Access
Expand Down

0 comments on commit b7f6404

Please sign in to comment.