From 0ce971d9d396521697b56efeb60e28fe40bd0015 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:27:14 +0200 Subject: [PATCH 01/33] Add new formatting regex --- rpc/responses_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 43924151a4..20bc8e97dd 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -13,12 +13,13 @@ import ( ) const ( - reHash = `"0x[0-9a-f]{64}"` // 32 bytes - reHashOpt = `"(0x[0-9a-f]{64})"|null` // 32 bytes or null - reAddress = `"0x[0-9a-f]{40}"` // 20 bytes - reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null - reNum = `"0x([1-9a-f][0-9a-f]{1,15})|0"` // must not have left-padded zeros - reData = `"0x[0-9a-f]*"` // can be "empty" + reHash = `"0x[0-9a-f]{64}"` // 32 bytes + reHashOpt = `"(0x[0-9a-f]{64})"|null` // 32 bytes or null + reAddress = `"0x[0-9a-f]{40}"` // 20 bytes + reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null + reNum = `"0x([1-9a-f][0-9a-f]{0,15})|0"` // must not have left-padded zeros + reNumOpt = `"0x([1-9a-f][0-9a-f]{0,15})|0"|null` // must not have left-padded zeros or null + reData = `"0x[0-9a-f]*"` // can be "empty" ) func TestNewBlockRes(t *testing.T) { From 93f832a1a76430ebb18276aaf2a3f18d000edae2 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:27:37 +0200 Subject: [PATCH 02/33] Make block context optional nulls --- rpc/responses_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 20bc8e97dd..702fc5c226 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -72,9 +72,9 @@ func TestNewTransactionRes(t *testing.T) { tests := map[string]string{ "hash": reHash, "nonce": reNum, - "blockHash": reHash, - "blockNum": reNum, - "transactionIndex": reNum, + "blockHash": reHashOpt, + "blockNum": reNumOpt, + "transactionIndex": reNumOpt, "from": reAddress, "to": reAddressOpt, "value": reNum, From 6e8ff578f18473d7c4fe013a88d2bece1ecf65d1 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:28:06 +0200 Subject: [PATCH 03/33] Block nonce as data --- rpc/responses.go | 4 ++-- rpc/responses_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rpc/responses.go b/rpc/responses.go index 45a2fa18b2..0f67299fc3 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -11,7 +11,7 @@ type BlockRes struct { BlockNumber *hexnum `json:"number"` BlockHash *hexdata `json:"hash"` ParentHash *hexdata `json:"parentHash"` - Nonce *hexnum `json:"nonce"` + Nonce *hexdata `json:"nonce"` Sha3Uncles *hexdata `json:"sha3Uncles"` LogsBloom *hexdata `json:"logsBloom"` TransactionRoot *hexdata `json:"transactionRoot"` @@ -41,7 +41,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { res.BlockNumber = newHexNum(block.Number()) res.BlockHash = newHexData(block.Hash()) res.ParentHash = newHexData(block.ParentHash()) - res.Nonce = newHexNum(block.Header().Nonce) + res.Nonce = newHexData(block.Header().Nonce) res.Sha3Uncles = newHexData(block.Header().UncleHash) res.LogsBloom = newHexData(block.Bloom()) res.TransactionRoot = newHexData(block.Header().TxHash) diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 702fc5c226..949e1794ba 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -34,7 +34,7 @@ func TestNewBlockRes(t *testing.T) { "number": reNum, "hash": reHash, "parentHash": reHash, - "nonce": reNum, + "nonce": reData, "sha3Uncles": reHash, "logsBloom": reData, "transactionRoot": reHash, From ac03ff6f055ef2bd9404a30a0c257fdd2722eafe Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:44:09 +0200 Subject: [PATCH 04/33] Fix block size output #613 --- common/size.go | 4 ++++ rpc/responses.go | 2 +- rpc/responses_test.go | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/size.go b/common/size.go index b5c0b0b3f6..0d9dbf5583 100644 --- a/common/size.go +++ b/common/size.go @@ -17,6 +17,10 @@ func (self StorageSize) String() string { } } +func (self StorageSize) Int64() int64 { + return int64(self) +} + // The different number of units var ( Douglas = BigPow(10, 42) diff --git a/rpc/responses.go b/rpc/responses.go index 0f67299fc3..41776a0be0 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -49,7 +49,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { res.Miner = newHexData(block.Header().Coinbase) res.Difficulty = newHexNum(block.Difficulty()) res.TotalDifficulty = newHexNum(block.Td) - res.Size = newHexNum(block.Size()) + res.Size = newHexNum(block.Size().Int64()) res.ExtraData = newHexData(block.Header().Extra) res.GasLimit = newHexNum(block.GasLimit()) // res.MinGasPrice = diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 949e1794ba..704a381863 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -18,6 +18,7 @@ const ( reAddress = `"0x[0-9a-f]{40}"` // 20 bytes reAddressOpt = `"0x[0-9a-f]{40}"|null` // 20 bytes or null reNum = `"0x([1-9a-f][0-9a-f]{0,15})|0"` // must not have left-padded zeros + reNumNonZero = `"0x([1-9a-f][0-9a-f]{0,15})"` // non-zero required must not have left-padded zeros reNumOpt = `"0x([1-9a-f][0-9a-f]{0,15})|0"|null` // must not have left-padded zeros or null reData = `"0x[0-9a-f]*"` // can be "empty" ) @@ -42,7 +43,7 @@ func TestNewBlockRes(t *testing.T) { "miner": reAddress, "difficulty": `"0x1"`, "totalDifficulty": reNum, - "size": reNum, + "size": reNumNonZero, "extraData": reData, "gasLimit": reNum, // "minGasPrice": "0x", From bea3879d6f5862886948b9045b6c6111b41f8480 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:45:56 +0200 Subject: [PATCH 05/33] If nil, type doesn't matter --- rpc/messages.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpc/messages.go b/rpc/messages.go index 3c011cd93b..549268cce3 100644 --- a/rpc/messages.go +++ b/rpc/messages.go @@ -45,6 +45,9 @@ func (d *hexdata) UnmarshalJSON(b []byte) (err error) { func newHexData(input interface{}) *hexdata { d := new(hexdata) + if input == nil { + d.data = nil + } switch input := input.(type) { case []byte: d.data = input From 55b9689950dbb3f47e2d4720d04d2539243429bd Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 15:53:48 +0200 Subject: [PATCH 06/33] rename messages to types --- rpc/{messages.go => types.go} | 0 rpc/{messages_test.go => types_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename rpc/{messages.go => types.go} (100%) rename rpc/{messages_test.go => types_test.go} (100%) diff --git a/rpc/messages.go b/rpc/types.go similarity index 100% rename from rpc/messages.go rename to rpc/types.go diff --git a/rpc/messages_test.go b/rpc/types_test.go similarity index 100% rename from rpc/messages_test.go rename to rpc/types_test.go From b6f0b400375dfe3ae1ada954f14fa15155163f1e Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 16:49:07 +0200 Subject: [PATCH 07/33] Respect fullTx option #614 --- rpc/responses.go | 95 +++++++++++++++++++++++++++++++++++++++++++ rpc/responses_test.go | 63 ++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) diff --git a/rpc/responses.go b/rpc/responses.go index 41776a0be0..172a0902fd 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -1,6 +1,8 @@ package rpc import ( + "encoding/json" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" ) @@ -29,6 +31,99 @@ type BlockRes struct { Uncles []*hexdata `json:"uncles"` } +func (b *BlockRes) MarshalJSON() ([]byte, error) { + if b.fullTx { + var ext struct { + BlockNumber *hexnum `json:"number"` + BlockHash *hexdata `json:"hash"` + ParentHash *hexdata `json:"parentHash"` + Nonce *hexdata `json:"nonce"` + Sha3Uncles *hexdata `json:"sha3Uncles"` + LogsBloom *hexdata `json:"logsBloom"` + TransactionRoot *hexdata `json:"transactionRoot"` + StateRoot *hexdata `json:"stateRoot"` + Miner *hexdata `json:"miner"` + Difficulty *hexnum `json:"difficulty"` + TotalDifficulty *hexnum `json:"totalDifficulty"` + Size *hexnum `json:"size"` + ExtraData *hexdata `json:"extraData"` + GasLimit *hexnum `json:"gasLimit"` + MinGasPrice *hexnum `json:"minGasPrice"` + GasUsed *hexnum `json:"gasUsed"` + UnixTimestamp *hexnum `json:"timestamp"` + Transactions []*TransactionRes `json:"transactions"` + Uncles []*hexdata `json:"uncles"` + } + + ext.BlockNumber = b.BlockNumber + ext.BlockHash = b.BlockHash + ext.ParentHash = b.ParentHash + ext.Nonce = b.Nonce + ext.Sha3Uncles = b.Sha3Uncles + ext.LogsBloom = b.LogsBloom + ext.TransactionRoot = b.TransactionRoot + ext.StateRoot = b.StateRoot + ext.Miner = b.Miner + ext.Difficulty = b.Difficulty + ext.TotalDifficulty = b.TotalDifficulty + ext.Size = b.Size + ext.ExtraData = b.ExtraData + ext.GasLimit = b.GasLimit + ext.MinGasPrice = b.MinGasPrice + ext.GasUsed = b.GasUsed + ext.UnixTimestamp = b.UnixTimestamp + ext.Transactions = b.Transactions + ext.Uncles = b.Uncles + return json.Marshal(ext) + } else { + var ext struct { + BlockNumber *hexnum `json:"number"` + BlockHash *hexdata `json:"hash"` + ParentHash *hexdata `json:"parentHash"` + Nonce *hexdata `json:"nonce"` + Sha3Uncles *hexdata `json:"sha3Uncles"` + LogsBloom *hexdata `json:"logsBloom"` + TransactionRoot *hexdata `json:"transactionRoot"` + StateRoot *hexdata `json:"stateRoot"` + Miner *hexdata `json:"miner"` + Difficulty *hexnum `json:"difficulty"` + TotalDifficulty *hexnum `json:"totalDifficulty"` + Size *hexnum `json:"size"` + ExtraData *hexdata `json:"extraData"` + GasLimit *hexnum `json:"gasLimit"` + MinGasPrice *hexnum `json:"minGasPrice"` + GasUsed *hexnum `json:"gasUsed"` + UnixTimestamp *hexnum `json:"timestamp"` + Transactions []*hexdata `json:"transactions"` + Uncles []*hexdata `json:"uncles"` + } + + ext.BlockNumber = b.BlockNumber + ext.BlockHash = b.BlockHash + ext.ParentHash = b.ParentHash + ext.Nonce = b.Nonce + ext.Sha3Uncles = b.Sha3Uncles + ext.LogsBloom = b.LogsBloom + ext.TransactionRoot = b.TransactionRoot + ext.StateRoot = b.StateRoot + ext.Miner = b.Miner + ext.Difficulty = b.Difficulty + ext.TotalDifficulty = b.TotalDifficulty + ext.Size = b.Size + ext.ExtraData = b.ExtraData + ext.GasLimit = b.GasLimit + ext.MinGasPrice = b.MinGasPrice + ext.GasUsed = b.GasUsed + ext.UnixTimestamp = b.UnixTimestamp + ext.Transactions = make([]*hexdata, len(b.Transactions)) + for i, tx := range b.Transactions { + ext.Transactions[i] = tx.Hash + } + ext.Uncles = b.Uncles + return json.Marshal(ext) + } +} + func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { // TODO respect fullTx flag diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 704a381863..0f911c8869 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -21,6 +21,8 @@ const ( reNumNonZero = `"0x([1-9a-f][0-9a-f]{0,15})"` // non-zero required must not have left-padded zeros reNumOpt = `"0x([1-9a-f][0-9a-f]{0,15})|0"|null` // must not have left-padded zeros or null reData = `"0x[0-9a-f]*"` // can be "empty" + // reListHash = `[("\w":"0x[0-9a-f]{64}",?)*]` + // reListObj = `[("\w":(".+"|null),?)*]` ) func TestNewBlockRes(t *testing.T) { @@ -49,9 +51,70 @@ func TestNewBlockRes(t *testing.T) { // "minGasPrice": "0x", "gasUsed": reNum, "timestamp": reNum, + // "transactions": reListHash, + // "uncles": reListHash, } + to := common.HexToAddress("0x02") + amount := big.NewInt(1) + gasAmount := big.NewInt(1) + gasPrice := big.NewInt(1) + data := []byte{1, 2, 3} + tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) + v := NewBlockRes(block, false) + v.Transactions = make([]*TransactionRes, 1) + v.Transactions[0] = NewTransactionRes(tx) + j, _ := json.Marshal(v) + + for k, re := range tests { + match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j)) + if !match { + t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j)) + } + } +} + +func TestNewBlockResWithTrans(t *testing.T) { + parentHash := common.HexToHash("0x01") + coinbase := common.HexToAddress("0x01") + root := common.HexToHash("0x01") + difficulty := common.Big1 + nonce := uint64(1) + extra := "" + block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) + tests := map[string]string{ + "number": reNum, + "hash": reHash, + "parentHash": reHash, + "nonce": reData, + "sha3Uncles": reHash, + "logsBloom": reData, + "transactionRoot": reHash, + "stateRoot": reHash, + "miner": reAddress, + "difficulty": `"0x1"`, + "totalDifficulty": reNum, + "size": reNumNonZero, + "extraData": reData, + "gasLimit": reNum, + // "minGasPrice": "0x", + "gasUsed": reNum, + "timestamp": reNum, + // "transactions": `[{.*}]`, + // "uncles": reListHash, + } + + to := common.HexToAddress("0x02") + amount := big.NewInt(1) + gasAmount := big.NewInt(1) + gasPrice := big.NewInt(1) + data := []byte{1, 2, 3} + tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data) + + v := NewBlockRes(block, true) + v.Transactions = make([]*TransactionRes, 1) + v.Transactions[0] = NewTransactionRes(tx) j, _ := json.Marshal(v) for k, re := range tests { From 1045015a3c8df048d80c0f66598a8a8fa09b2f71 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 17:48:53 +0200 Subject: [PATCH 08/33] Update nonce field --- rpc/responses.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/responses.go b/rpc/responses.go index 172a0902fd..bf4f518aaf 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -136,7 +136,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { res.BlockNumber = newHexNum(block.Number()) res.BlockHash = newHexData(block.Hash()) res.ParentHash = newHexData(block.ParentHash()) - res.Nonce = newHexData(block.Header().Nonce) + res.Nonce = newHexData(block.Nonce()) res.Sha3Uncles = newHexData(block.Header().UncleHash) res.LogsBloom = newHexData(block.Bloom()) res.TransactionRoot = newHexData(block.Header().TxHash) From eac4d582d7bfe427d4bf5c738e38f1f9861cd30a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 17:49:22 +0200 Subject: [PATCH 09/33] Patches --- rpc/types.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rpc/types.go b/rpc/types.go index 549268cce3..2d0cf53be6 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -47,6 +47,7 @@ func newHexData(input interface{}) *hexdata { if input == nil { d.data = nil + return d } switch input := input.(type) { case []byte: @@ -57,8 +58,8 @@ func newHexData(input interface{}) *hexdata { d.data = input.Bytes() case common.Address: d.data = input.Bytes() - case *common.Address: - d.data = input.Bytes() + // case *common.Address: + // d.data = input.Bytes() case *big.Int: d.data = input.Bytes() case int64: From 5d8be9c30d1f2334ecac0ddb92d82a878b35c51c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Wed, 1 Apr 2015 23:08:00 +0200 Subject: [PATCH 10/33] Fixed decoding for uint64 into bytes --- rpc/types.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpc/types.go b/rpc/types.go index 2d0cf53be6..75c4ba85f9 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -17,6 +17,7 @@ package rpc import ( + "encoding/binary" "encoding/json" "fmt" "math/big" @@ -65,7 +66,9 @@ func newHexData(input interface{}) *hexdata { case int64: d.data = big.NewInt(input).Bytes() case uint64: - d.data = big.NewInt(int64(input)).Bytes() + buff := make([]byte, 8) + binary.BigEndian.PutUint64(buff, input) + d.data = buff case int: d.data = big.NewInt(int64(input)).Bytes() case uint: From bb3ae3026edec431c59299271f1af682e8dbb938 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 2 Apr 2015 01:53:33 +0200 Subject: [PATCH 11/33] print nonenumerable properties of object in geth console --- jsre/pp_js.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/jsre/pp_js.go b/jsre/pp_js.go index 3352f23ce0..78509fc0bc 100644 --- a/jsre/pp_js.go +++ b/jsre/pp_js.go @@ -23,18 +23,26 @@ function pp(object, indent) { } } str += " ]"; + } else if (object instanceof Error) { + str += "\033[31m" + "Error"; } else if(typeof(object) === "object") { str += "{\n"; - indent += " "; - var last = Object.keys(object).pop() - for(var k in object) { - str += indent + k + ": " + pp(object[k], indent); + indent += " "; + var last = Object.getOwnPropertyNames(object).pop() + Object.getOwnPropertyNames(object).forEach(function (k) { + str += indent + k + ": "; + try { + str += pp(object[k], indent); + } catch (e) { + str += pp(e, indent); + } if(k !== last) { str += ","; } - str += "\n"; - } + + str += "\n"; + }); str += indent.substr(2, indent.length) + "}"; } else if(typeof(object) === "string") { str += "\033[32m'" + object + "'"; @@ -43,7 +51,7 @@ function pp(object, indent) { } else if(typeof(object) === "number") { str += "\033[31m" + object; } else if(typeof(object) === "function") { - str += "\033[35m[Function]"; + str += "\033[35m[Function]"; } else { str += object; } From 3d568e21b8fa0eaa24731c2822b531e6af662ae1 Mon Sep 17 00:00:00 2001 From: "Daniel A. Nagy" Date: Thu, 2 Apr 2015 10:54:24 +0200 Subject: [PATCH 12/33] Network ID changed to 100 to be able to experiment with a private blockchain. --- eth/protocol.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/protocol.go b/eth/protocol.go index a0ab177cdc..b39ac5b154 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -14,7 +14,7 @@ import ( const ( ProtocolVersion = 60 - NetworkId = 0 + NetworkId = 100 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 maxHashes = 256 From f960fc066e2daa27658e61e2b5da381c31bfff15 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 2 Apr 2015 02:13:34 +0200 Subject: [PATCH 13/33] fixed printing BigNumbers --- jsre/pp_js.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jsre/pp_js.go b/jsre/pp_js.go index 78509fc0bc..0b22afe6d3 100644 --- a/jsre/pp_js.go +++ b/jsre/pp_js.go @@ -25,6 +25,8 @@ function pp(object, indent) { str += " ]"; } else if (object instanceof Error) { str += "\033[31m" + "Error"; + } else if (isBigNumber(object)) { + str += "\033[32m'" + object.toString(10) + "'"; } else if(typeof(object) === "object") { str += "{\n"; indent += " "; @@ -61,6 +63,11 @@ function pp(object, indent) { return str; } +var isBigNumber = function (object) { + return typeof BigNumber !== 'undefined' && object instanceof BigNumber; +}; + + function prettyPrint(/* */) { var args = arguments; var ret = ""; From c71ca1a089cc963848c5eee7391a53168adf188c Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 11:32:50 +0200 Subject: [PATCH 14/33] Better nil handling --- rpc/types.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/rpc/types.go b/rpc/types.go index 75c4ba85f9..53a2a08061 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -24,10 +24,12 @@ import ( "strings" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) type hexdata struct { - data []byte + data []byte + isNil bool } func (d *hexdata) String() string { @@ -35,6 +37,9 @@ func (d *hexdata) String() string { } func (d *hexdata) MarshalJSON() ([]byte, error) { + if d.isNil { + return json.Marshal(nil) + } return json.Marshal(d.String()) } @@ -56,11 +61,19 @@ func newHexData(input interface{}) *hexdata { case common.Hash: d.data = input.Bytes() case *common.Hash: - d.data = input.Bytes() + if input == nil { + d.isNil = true + } else { + d.data = input.Bytes() + } case common.Address: d.data = input.Bytes() - // case *common.Address: - // d.data = input.Bytes() + case *common.Address: + if input == nil { + d.isNil = true + } else { + d.data = input.Bytes() + } case *big.Int: d.data = input.Bytes() case int64: @@ -83,7 +96,8 @@ func newHexData(input interface{}) *hexdata { } type hexnum struct { - data []byte + data []byte + isNil bool } func (d *hexnum) String() string { @@ -99,6 +113,9 @@ func (d *hexnum) String() string { } func (d *hexnum) MarshalJSON() ([]byte, error) { + if d.isNil { + return json.Marshal(nil) + } return json.Marshal(d.String()) } From 85ebbc9aa5e4c8902b94847dbeb78f26255eb0aa Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 11:57:26 +0200 Subject: [PATCH 15/33] Default BlockNumber to -1 when missing --- rpc/args.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rpc/args.go b/rpc/args.go index dd013147d9..220daf9608 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -233,6 +233,8 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -320,6 +322,8 @@ func (args *CallArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -350,6 +354,8 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeight(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -387,6 +393,8 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeight(obj[2], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -417,6 +425,8 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeight(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -447,6 +457,8 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeight(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil @@ -477,6 +489,8 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) { if err := blockHeight(obj[1], &args.BlockNumber); err != nil { return err } + } else { + args.BlockNumber = -1 } return nil From f89baa73e5cfc0e93f32e36f5c3838cd808e6f46 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 12:30:22 +0200 Subject: [PATCH 16/33] transactionRoot -> transactionsRoot --- rpc/responses.go | 6 ++--- rpc/responses_test.go | 56 +++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/rpc/responses.go b/rpc/responses.go index bf4f518aaf..f1dc344db2 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -16,7 +16,7 @@ type BlockRes struct { Nonce *hexdata `json:"nonce"` Sha3Uncles *hexdata `json:"sha3Uncles"` LogsBloom *hexdata `json:"logsBloom"` - TransactionRoot *hexdata `json:"transactionRoot"` + TransactionRoot *hexdata `json:"transactionsRoot"` StateRoot *hexdata `json:"stateRoot"` Miner *hexdata `json:"miner"` Difficulty *hexnum `json:"difficulty"` @@ -40,7 +40,7 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { Nonce *hexdata `json:"nonce"` Sha3Uncles *hexdata `json:"sha3Uncles"` LogsBloom *hexdata `json:"logsBloom"` - TransactionRoot *hexdata `json:"transactionRoot"` + TransactionRoot *hexdata `json:"transactionsRoot"` StateRoot *hexdata `json:"stateRoot"` Miner *hexdata `json:"miner"` Difficulty *hexnum `json:"difficulty"` @@ -83,7 +83,7 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) { Nonce *hexdata `json:"nonce"` Sha3Uncles *hexdata `json:"sha3Uncles"` LogsBloom *hexdata `json:"logsBloom"` - TransactionRoot *hexdata `json:"transactionRoot"` + TransactionRoot *hexdata `json:"transactionsRoot"` StateRoot *hexdata `json:"stateRoot"` Miner *hexdata `json:"miner"` Difficulty *hexnum `json:"difficulty"` diff --git a/rpc/responses_test.go b/rpc/responses_test.go index 0f911c8869..2ec6d9d15f 100644 --- a/rpc/responses_test.go +++ b/rpc/responses_test.go @@ -34,20 +34,20 @@ func TestNewBlockRes(t *testing.T) { extra := "" block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) tests := map[string]string{ - "number": reNum, - "hash": reHash, - "parentHash": reHash, - "nonce": reData, - "sha3Uncles": reHash, - "logsBloom": reData, - "transactionRoot": reHash, - "stateRoot": reHash, - "miner": reAddress, - "difficulty": `"0x1"`, - "totalDifficulty": reNum, - "size": reNumNonZero, - "extraData": reData, - "gasLimit": reNum, + "number": reNum, + "hash": reHash, + "parentHash": reHash, + "nonce": reData, + "sha3Uncles": reHash, + "logsBloom": reData, + "transactionsRoot": reHash, + "stateRoot": reHash, + "miner": reAddress, + "difficulty": `"0x1"`, + "totalDifficulty": reNum, + "size": reNumNonZero, + "extraData": reData, + "gasLimit": reNum, // "minGasPrice": "0x", "gasUsed": reNum, "timestamp": reNum, @@ -84,20 +84,20 @@ func TestNewBlockResWithTrans(t *testing.T) { extra := "" block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, extra) tests := map[string]string{ - "number": reNum, - "hash": reHash, - "parentHash": reHash, - "nonce": reData, - "sha3Uncles": reHash, - "logsBloom": reData, - "transactionRoot": reHash, - "stateRoot": reHash, - "miner": reAddress, - "difficulty": `"0x1"`, - "totalDifficulty": reNum, - "size": reNumNonZero, - "extraData": reData, - "gasLimit": reNum, + "number": reNum, + "hash": reHash, + "parentHash": reHash, + "nonce": reData, + "sha3Uncles": reHash, + "logsBloom": reData, + "transactionsRoot": reHash, + "stateRoot": reHash, + "miner": reAddress, + "difficulty": `"0x1"`, + "totalDifficulty": reNum, + "size": reNumNonZero, + "extraData": reData, + "gasLimit": reNum, // "minGasPrice": "0x", "gasUsed": reNum, "timestamp": reNum, From cc45b4d8b536a53b59696389e3609c2f633d07a7 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 12:30:42 +0200 Subject: [PATCH 17/33] Trim left only, not right --- rpc/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/types.go b/rpc/types.go index 53a2a08061..83542c83db 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -104,7 +104,7 @@ func (d *hexnum) String() string { // Get hex string from bytes out := common.Bytes2Hex(d.data) // Trim leading 0s - out = strings.Trim(out, "0") + out = strings.TrimLeft(out, "0") // Output "0x0" when value is 0 if len(out) == 0 { out = "0" From b10e33c04011c9b9f52841ed09de0b8d4cb5bc6a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 12:31:10 +0200 Subject: [PATCH 18/33] More types supported --- rpc/types.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/rpc/types.go b/rpc/types.go index 83542c83db..205b58b0a2 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -74,6 +74,14 @@ func newHexData(input interface{}) *hexdata { } else { d.data = input.Bytes() } + case types.Bloom: + d.data = input.Bytes() + case *types.Bloom: + if input == nil { + d.isNil = true + } else { + d.data = input.Bytes() + } case *big.Int: d.data = input.Bytes() case int64: @@ -86,6 +94,18 @@ func newHexData(input interface{}) *hexdata { d.data = big.NewInt(int64(input)).Bytes() case uint: d.data = big.NewInt(int64(input)).Bytes() + case int8: + d.data = big.NewInt(int64(input)).Bytes() + case uint8: + d.data = big.NewInt(int64(input)).Bytes() + case int16: + d.data = big.NewInt(int64(input)).Bytes() + case uint16: + d.data = big.NewInt(int64(input)).Bytes() + case int32: + d.data = big.NewInt(int64(input)).Bytes() + case uint32: + d.data = big.NewInt(int64(input)).Bytes() case string: // hexstring d.data = common.Big(input).Bytes() default: From edfd2757d9d958dca936fe38efe350cf60b2c3ce Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 12:52:25 +0200 Subject: [PATCH 19/33] Better decoding of uint* --- rpc/types.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rpc/types.go b/rpc/types.go index 205b58b0a2..0789a99017 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -101,11 +101,15 @@ func newHexData(input interface{}) *hexdata { case int16: d.data = big.NewInt(int64(input)).Bytes() case uint16: - d.data = big.NewInt(int64(input)).Bytes() + buff := make([]byte, 8) + binary.BigEndian.PutUint16(buff, input) + d.data = buff case int32: d.data = big.NewInt(int64(input)).Bytes() case uint32: - d.data = big.NewInt(int64(input)).Bytes() + buff := make([]byte, 8) + binary.BigEndian.PutUint32(buff, input) + d.data = buff case string: // hexstring d.data = common.Big(input).Bytes() default: From 585aec127cb231d91998b33564b2294659f56ac1 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 12:56:36 +0200 Subject: [PATCH 20/33] Don't ignore user-specified "include tx" param --- rpc/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 660bb32513..940b80758a 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -179,7 +179,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByHash(args.BlockHash) - br := NewBlockRes(block, true) + br := NewBlockRes(block, args.IncludeTxs) *reply = br case "eth_getBlockByNumber": @@ -189,7 +189,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } block := api.xeth().EthBlockByNumber(args.BlockNumber) - br := NewBlockRes(block, true) + br := NewBlockRes(block, args.IncludeTxs) *reply = br case "eth_getTransactionByHash": From 0f3bf7ef4de95b8012eb9bba717323b9e89c5908 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 12:57:04 +0200 Subject: [PATCH 21/33] Fixes for balance --- rpc/api.go | 7 ++++--- xeth/xeth.go | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 80dd27afba..d9206eb798 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -36,7 +36,7 @@ func (api *EthereumApi) xethAtStateNum(num int64) *xeth.XEth { func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error { // Spec at https://github.com/ethereum/wiki/wiki/JSON-RPC - rpclogger.Debugf("%s %s", req.Method, req.Params) + rpclogger.Infof("%s %s", req.Method, req.Params) switch req.Method { case "web3_sha3": @@ -80,8 +80,9 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } - v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance() - *reply = common.ToHex(v.Bytes()) + *reply = api.xethAtStateNum(args.BlockNumber).BalanceAt(args.Address) + //v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance() + //*reply = common.ToHex(v.Bytes()) case "eth_getStorage", "eth_storageAt": args := new(GetStorageArgs) if err := json.Unmarshal(req.Params, &args); err != nil { diff --git a/xeth/xeth.go b/xeth/xeth.go index 0a813ec99c..d9a34695a3 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -312,7 +312,7 @@ func (self *XEth) StorageAt(addr, storageAddr string) string { } func (self *XEth) BalanceAt(addr string) string { - return self.State().state.GetBalance(common.HexToAddress(addr)).String() + return common.ToHex(self.State().state.GetBalance(common.HexToAddress(addr)).Bytes()) } func (self *XEth) TxCountAt(address string) int { From 3f4c1aaf01032787367a97b6e4574c2784179546 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 12:58:17 +0200 Subject: [PATCH 22/33] info => debug --- cmd/mist/assets/examples/coin.html | 2 +- miner/worker.go | 2 ++ rpc/api.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html index a15345ab31..0528a5ad00 100644 --- a/cmd/mist/assets/examples/coin.html +++ b/cmd/mist/assets/examples/coin.html @@ -3,7 +3,7 @@ JevCoin - + diff --git a/miner/worker.go b/miner/worker.go index 2ba3faed85..3357c6f7b7 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -171,6 +171,8 @@ func (self *worker) wait() { } self.mux.Post(core.NewMinedBlockEvent{block}) + minerlogger.Infof("ð”¨#%v", block.Number()) + jsonlogger.LogJson(&logger.EthMinerNewBlock{ BlockHash: block.Hash().Hex(), BlockNumber: block.Number(), diff --git a/rpc/api.go b/rpc/api.go index d9206eb798..4a17d3b15a 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -36,7 +36,7 @@ func (api *EthereumApi) xethAtStateNum(num int64) *xeth.XEth { func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error { // Spec at https://github.com/ethereum/wiki/wiki/JSON-RPC - rpclogger.Infof("%s %s", req.Method, req.Params) + rpclogger.Debugf("%s %s", req.Method, req.Params) switch req.Method { case "web3_sha3": From 60da9a12890710fd01013e4928cf094716bf8ea4 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 13:03:33 +0200 Subject: [PATCH 23/33] Put the old hammer back in <3 --- miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index 3357c6f7b7..4385b51c80 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -171,7 +171,7 @@ func (self *worker) wait() { } self.mux.Post(core.NewMinedBlockEvent{block}) - minerlogger.Infof("ð”¨#%v", block.Number()) + minerlogger.Infof("🔨 Mined block #%v", block.Number()) jsonlogger.LogJson(&logger.EthMinerNewBlock{ BlockHash: block.Hash().Hex(), From 2efb89d5440a9e43bec75b5f59032a0ff0cdc3cc Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:04:58 +0200 Subject: [PATCH 24/33] Guard for nil *big.Int --- rpc/types.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rpc/types.go b/rpc/types.go index 0789a99017..806c9c8a43 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -83,7 +83,11 @@ func newHexData(input interface{}) *hexdata { d.data = input.Bytes() } case *big.Int: - d.data = input.Bytes() + if input == nil { + d.isNil = true + } else { + d.data = input.Bytes() + } case int64: d.data = big.NewInt(input).Bytes() case uint64: From 14c14fd61f72bfa8c1494fa799a4f2e2eb14f4c1 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:05:13 +0200 Subject: [PATCH 25/33] Output empty block as nil --- rpc/responses.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/responses.go b/rpc/responses.go index f1dc344db2..3d1687cb68 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -128,7 +128,7 @@ func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { // TODO respect fullTx flag if block == nil { - return &BlockRes{} + return nil } res := new(BlockRes) From 79828531b1e6a1d5073f45e0e672c54a019de7c0 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 13:13:11 +0200 Subject: [PATCH 26/33] updated ethereum.js --- cmd/mist/assets/ext/ethereum.js | 2 +- jsre/ethereum_js.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/mist/assets/ext/ethereum.js b/cmd/mist/assets/ext/ethereum.js index 2536888f81..31e046dbec 160000 --- a/cmd/mist/assets/ext/ethereum.js +++ b/cmd/mist/assets/ext/ethereum.js @@ -1 +1 @@ -Subproject commit 2536888f817a1a15b05dab4727d30f73d6763f07 +Subproject commit 31e046dbecea51d3b99b21f3e7e60ddfb6c39304 diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go index fe15178fa3..0c38cd0e46 100644 --- a/jsre/ethereum_js.go +++ b/jsre/ethereum_js.go @@ -1,3 +1,4 @@ package jsre -const Ethereum_JS = `require=function t(e,n,r){function o(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;av;v++)g.push(h(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(s),n.push(h(e.slice(0,s))),e=e.slice(s)):(n.push(h(e.slice(0,s))),e=e.slice(s))}),n},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:h,outputParser:d,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),i(r.toTwosComplement(t).round().toString(16),e)},u=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},c=function(t){return a(new n(t).times(new n(2).pow(128)))},l=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},f=function(t){return t=t||"0",l(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},p=function(t){return t=t||"0",new n(t,16)},m=function(t){return f(t).dividedBy(new n(2).pow(128))},h=function(t){return p(t).dividedBy(new n(2).pow(128))},d=function(t){return"0x"+t},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},v=function(t){return r.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:u,formatInputBool:s,formatInputReal:c,formatOutputInt:f,formatOutputUInt:p,formatOutputReal:m,formatOutputUReal:h,formatOutputHash:d,formatOutputBool:g,formatOutputString:v,formatOutputAddress:y}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},a=function(t){for(var e="",n=0;n1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},i.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},i.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(n.getInstance().send(t))},e.exports=i},{"../utils/utils":6,"./errors":11,"./requestmanager":22}],19:[function(t,e){var n=t("../utils/utils"),r=t("./property"),o=[],i=[new r({name:"listening",getter:"net_listening"}),new r({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:o,properties:i}},{"../utils/utils":6,"./property":20}],20:[function(t,e){var n=t("./requestmanager"),r=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};r.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},r.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},r.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},r.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},r.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=r},{"./requestmanager":22}],21:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],22:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/utils"),o=t("../utils/config"),i=t("./errors"),a=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};a.getInstance=function(){var t=new a;return t},a.prototype.send=function(t){if(!this.provider)return console.error(i.InvalidProvider),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw i.InvalidResponse(r);return r.result},a.prototype.sendAsync=function(t,e){if(!this.provider)return e(i.InvalidProvider);var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(i.InvalidResponse(r))})},a.prototype.setProvider=function(t){this.provider=t},a.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},a.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},a.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},a.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(i.InvalidProvider);var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,o){if(!t){if(!r.isArray(o))throw i.InvalidResponse(o);o.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(i.InvalidResponse(t)),e}).filter(function(t){return r.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=a},{"../utils/config":5,"../utils/utils":6,"./errors":11,"./jsonrpc":17}],23:[function(t,e){var n=t("./method"),r=t("./formatters"),o=new n({name:"post",call:"shh_post",params:1,inputFormatter:r.inputPostFormatter}),i=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),a=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new n({name:"newGroup",call:"shh_newGroup",params:0}),s=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),c=[o,i,a,u,s];e.exports={methods:c}},{"./formatters":15,"./method":18}],24:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],25:[function(t,e){var n=t("./method"),r=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1});return[e,r,o,i]},o=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,r,o]};e.exports={eth:r,shh:o}},{"./method":18}],26:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":16,"./lib/web3/qtsync":21}]},{},["ethereum.js"]);` +const Ethereum_JS = ` +require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;av;v++)g.push(h(e.slice(0,u))),e=e.slice(u);n.push(g)}else o.prefixedType("bytes")(t[c].type)?(l=l.slice(u),n.push(h(e.slice(0,u))),e=e.slice(u)):(n.push(h(e.slice(0,u))),e=e.slice(u))}),n},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),i=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=i),e[r][o]=i}),e};e.exports={inputParser:h,outputParser:d,formatInput:l,formatOutput:m}},{"../utils/config":5,"../utils/utils":6,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("bignumber.js"),r=t("../utils/utils"),o=t("../utils/config"),i=function(t){var e=2*o.ETH_PADDING;return n.config(o.ETH_BIGNUMBER_ROUNDING_MODE),r.padLeft(r.toTwosComplement(t).round().toString(16),e)},a=function(t){return r.fromAscii(t,o.ETH_PADDING).substr(2)},s=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},u=function(t){return i(new n(t).times(new n(2).pow(128)))},c=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},l=function(t){return t=t||"0",c(t)?new n(t,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(t,16)},f=function(t){return t=t||"0",new n(t,16)},p=function(t){return l(t).dividedBy(new n(2).pow(128))},m=function(t){return f(t).dividedBy(new n(2).pow(128))},h=function(t){return"0x"+t},d=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return r.toAscii(t)},v=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:i,formatInputString:a,formatInputBool:s,formatInputReal:u,formatOutputInt:l,formatOutputUInt:f,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:h,formatOutputBool:d,formatOutputString:g,formatOutputAddress:v}},{"../utils/config":5,"../utils/utils":6,"bignumber.js":"bignumber.js"}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},i=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("bytes"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},a=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("bytes"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:i,outputTypes:a}},{"./formatters":2}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[function(t,e){var n=t("bignumber.js"),r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:r,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,ETH_DEFAULTBLOCK:"latest"}},{"bignumber.js":"bignumber.js"}],6:[function(t,e){var n=t("bignumber.js"),r={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},i=function(t,e){for(var n=!1,r=0;rn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",n=0;n1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},i.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},i.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(n.getInstance().send(t))},e.exports=i},{"../utils/utils":6,"./errors":11,"./requestmanager":22}],19:[function(t,e){var n=t("../utils/utils"),r=t("./property"),o=[],i=[new r({name:"listening",getter:"net_listening"}),new r({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:o,properties:i}},{"../utils/utils":6,"./property":20}],20:[function(t,e){var n=t("./requestmanager"),r=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};r.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},r.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},r.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},r.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},r.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=r},{"./requestmanager":22}],21:[function(t,e){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],22:[function(t,e){var n=t("./jsonrpc"),r=t("../utils/utils"),o=t("../utils/config"),i=t("./errors"),a=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};a.getInstance=function(){var t=new a;return t},a.prototype.send=function(t){if(!this.provider)return console.error(i.InvalidProvider),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw i.InvalidResponse(r);return r.result},a.prototype.sendAsync=function(t,e){if(!this.provider)return e(i.InvalidProvider);var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(i.InvalidResponse(r))})},a.prototype.setProvider=function(t){this.provider=t},a.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},a.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},a.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},a.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(i.InvalidProvider);var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,o){if(!t){if(!r.isArray(o))throw i.InvalidResponse(o);o.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(i.InvalidResponse(t)),e}).filter(function(t){return r.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=a},{"../utils/config":5,"../utils/utils":6,"./errors":11,"./jsonrpc":17}],23:[function(t,e){var n=t("./method"),r=t("./formatters"),o=new n({name:"post",call:"shh_post",params:1,inputFormatter:r.inputPostFormatter}),i=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),a=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),s=new n({name:"newGroup",call:"shh_newGroup",params:0}),u=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),c=[o,i,a,s,u];e.exports={methods:c}},{"./formatters":15,"./method":18}],24:[function(t,e){var n=t("../web3"),r=t("../utils/config"),o=function(t){return n.sha3(n.fromAscii(t)).slice(0,2+2*r.ETH_SIGNATURE_LENGTH)},i=function(t){return n.sha3(n.fromAscii(t))};e.exports={functionSignatureFromAscii:o,eventSignatureFromAscii:i}},{"../utils/config":5,"../web3":8}],25:[function(t,e){var n=t("./method"),r=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1});return[e,r,o,i]},o=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,r,o]};e.exports={eth:r,shh:o}},{"./method":18}],26:[function(){},{}],"bignumber.js":[function(t,e){"use strict";e.exports=BigNumber},{}],"ethereum.js":[function(t,e){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":8,"./lib/web3/contract":9,"./lib/web3/httpprovider":16,"./lib/web3/qtsync":21}]},{},["ethereum.js"]);` From e402e1dc2e72df2a433b984caeaba771085b2b66 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:17:55 +0200 Subject: [PATCH 27/33] New args types with stricter checking --- rpc/api.go | 12 +++---- rpc/args.go | 94 +++++++++++++++++++++++++++++++++--------------- rpc/args_test.go | 12 ++++++- 3 files changed, 82 insertions(+), 36 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 940b80758a..478ca87521 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -108,15 +108,15 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err count := api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address) *reply = common.ToHex(big.NewInt(int64(count)).Bytes()) case "eth_getBlockTransactionCountByHash": - args := new(GetBlockByHashArgs) + args := new(HashArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } - block := NewBlockRes(api.xeth().EthBlockByHash(args.BlockHash), false) + block := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false) *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes()) case "eth_getBlockTransactionCountByNumber": - args := new(GetBlockByNumberArgs) + args := new(BlockNumArg) if err := json.Unmarshal(req.Params, &args); err != nil { return err } @@ -124,16 +124,16 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err block := NewBlockRes(api.xeth().EthBlockByNumber(args.BlockNumber), false) *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes()) case "eth_getUncleCountByBlockHash": - args := new(GetBlockByHashArgs) + args := new(HashArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } - block := api.xeth().EthBlockByHash(args.BlockHash) + block := api.xeth().EthBlockByHash(args.Hash) br := NewBlockRes(block, false) *reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes()) case "eth_getUncleCountByBlockNumber": - args := new(GetBlockByNumberArgs) + args := new(BlockNumArg) if err := json.Unmarshal(req.Params, &args); err != nil { return err } diff --git a/rpc/args.go b/rpc/args.go index 220daf9608..b43c465c05 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -108,8 +108,8 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) { return NewDecodeParamError(err.Error()) } - if len(obj) < 1 { - return NewInsufficientParamsError(len(obj), 1) + if len(obj) < 2 { + return NewInsufficientParamsError(len(obj), 2) } argstr, ok := obj[0].(string) @@ -118,9 +118,7 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) { } args.BlockHash = argstr - if len(obj) > 1 { - args.IncludeTxs = obj[1].(bool) - } + args.IncludeTxs = obj[1].(bool) return nil } @@ -136,8 +134,8 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) { return NewDecodeParamError(err.Error()) } - if len(obj) < 1 { - return NewInsufficientParamsError(len(obj), 1) + if len(obj) < 2 { + return NewInsufficientParamsError(len(obj), 2) } if v, ok := obj[0].(float64); ok { @@ -148,9 +146,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) { return NewInvalidTypeError("blockNumber", "not a number or string") } - if len(obj) > 1 { - args.IncludeTxs = obj[1].(bool) - } + args.IncludeTxs = obj[1].(bool) return nil } @@ -496,12 +492,11 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) { return nil } -type BlockNumIndexArgs struct { +type BlockNumArg struct { BlockNumber int64 - Index int64 } -func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) { +func (args *BlockNumArg) UnmarshalJSON(b []byte) (err error) { var obj []interface{} if err := json.Unmarshal(b, &obj); err != nil { return NewDecodeParamError(err.Error()) @@ -515,23 +510,42 @@ func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) { return err } - if len(obj) > 1 { - arg1, ok := obj[1].(string) - if !ok { - return NewInvalidTypeError("index", "not a string") - } - args.Index = common.Big(arg1).Int64() + return nil +} + +type BlockNumIndexArgs struct { + BlockNumber int64 + Index int64 +} + +func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) { + var obj []interface{} + if err := json.Unmarshal(b, &obj); err != nil { + return NewDecodeParamError(err.Error()) } + if len(obj) < 2 { + return NewInsufficientParamsError(len(obj), 2) + } + + if err := blockHeight(obj[0], &args.BlockNumber); err != nil { + return err + } + + arg1, ok := obj[1].(string) + if !ok { + return NewInvalidTypeError("index", "not a string") + } + args.Index = common.Big(arg1).Int64() + return nil } -type HashIndexArgs struct { - Hash string - Index int64 +type HashArgs struct { + Hash string } -func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) { +func (args *HashArgs) UnmarshalJSON(b []byte) (err error) { var obj []interface{} if err := json.Unmarshal(b, &obj); err != nil { return NewDecodeParamError(err.Error()) @@ -547,14 +561,36 @@ func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) { } args.Hash = arg0 - if len(obj) > 1 { - arg1, ok := obj[1].(string) - if !ok { - return NewInvalidTypeError("index", "not a string") - } - args.Index = common.Big(arg1).Int64() + return nil +} + +type HashIndexArgs struct { + Hash string + Index int64 +} + +func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) { + var obj []interface{} + if err := json.Unmarshal(b, &obj); err != nil { + return NewDecodeParamError(err.Error()) } + if len(obj) < 2 { + return NewInsufficientParamsError(len(obj), 2) + } + + arg0, ok := obj[0].(string) + if !ok { + return NewInvalidTypeError("hash", "not a string") + } + args.Hash = arg0 + + arg1, ok := obj[1].(string) + if !ok { + return NewInvalidTypeError("index", "not a string") + } + args.Index = common.Big(arg1).Int64() + return nil } diff --git a/rpc/args_test.go b/rpc/args_test.go index 3635882c00..f00899b790 100644 --- a/rpc/args_test.go +++ b/rpc/args_test.go @@ -225,7 +225,7 @@ func TestGetBlockByHashArgsHashInt(t *testing.T) { input := `[8]` args := new(GetBlockByHashArgs) - str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args)) + str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args)) if len(str) > 0 { t.Error(str) } @@ -281,6 +281,16 @@ func TestGetBlockByNumberEmpty(t *testing.T) { } } +func TestGetBlockByNumberShort(t *testing.T) { + input := `["0xbbb"]` + + args := new(GetBlockByNumberArgs) + str := ExpectInsufficientParamsError(json.Unmarshal([]byte(input), &args)) + if len(str) > 0 { + t.Error(str) + } +} + func TestGetBlockByNumberBool(t *testing.T) { input := `[true, true]` From b86450aaae361ef183928b2de53e3724d3e174a8 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:27:58 +0200 Subject: [PATCH 28/33] Guard from nil pointers --- rpc/api.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rpc/api.go b/rpc/api.go index 478ca87521..20299bef1e 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -238,6 +238,10 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err } br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false) + if br == nil { + *reply = nil + return nil + } if args.Index >= int64(len(br.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") @@ -256,6 +260,11 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err block := api.xeth().EthBlockByNumber(args.BlockNumber) v := NewBlockRes(block, true) + if v == nil { + *reply = nil + return nil + } + if args.Index >= int64(len(v.Uncles)) || args.Index < 0 { return NewValidationError("Index", "does not exist") } From 81de8ed0912f767b2e3104aaad5c7f31920aaf2a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:38:12 +0200 Subject: [PATCH 29/33] Format code as hexdata --- rpc/api.go | 3 ++- xeth/xeth.go | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/rpc/api.go b/rpc/api.go index 20299bef1e..b554dc16b4 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -146,7 +146,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err if err := json.Unmarshal(req.Params, &args); err != nil { return err } - *reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address) + v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address) + *reply = newHexData(v) case "eth_sendTransaction", "eth_transact": args := new(NewTxArgs) if err := json.Unmarshal(req.Params, &args); err != nil { diff --git a/xeth/xeth.go b/xeth/xeth.go index 5936c0fb2e..1b6b1ccd0e 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -325,6 +325,10 @@ func (self *XEth) CodeAt(address string) string { return common.ToHex(self.State().SafeGet(address).Code()) } +func (self *XEth) CodeAtBytes(address string) []byte { + return self.State().SafeGet(address).Code() +} + func (self *XEth) IsContract(address string) bool { return len(self.State().SafeGet(address).Code()) > 0 } From 55b1c1546b72b24b087cecf18f3e52bad5c758c8 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 13:55:35 +0200 Subject: [PATCH 30/33] Moved to function --- xeth/xeth.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xeth/xeth.go b/xeth/xeth.go index d9a34695a3..cb2319865a 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -29,6 +29,9 @@ var ( defaultGas = big.NewInt(90000) //500000 ) +func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) } +func DefaultGasPrice() *big.Int { return new(big.Int).Set(defaultGasPrice) } + type XEth struct { backend *eth.Ethereum frontend Frontend @@ -130,9 +133,6 @@ func cTopics(t [][]string) [][]common.Hash { return topics } -func (self *XEth) DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) } -func (self *XEth) DefaultGasPrice() *big.Int { return new(big.Int).Set(defaultGasPrice) } - func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent } func (self *XEth) AtStateNum(num int64) *XEth { From 015453f5b3f5b78ac8f432aed2247c839a6e5049 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 13:55:53 +0200 Subject: [PATCH 31/33] Default Value to 0 for NewTxArgs --- rpc/args.go | 2 +- rpc/args_test.go | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rpc/args.go b/rpc/args.go index b43c465c05..df57e69c4c 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -198,7 +198,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { var num int64 if ext.Value == nil { - return NewValidationError("value", "is required") + num = 0 } else { if err := numString(ext.Value, &num); err != nil { return err diff --git a/rpc/args_test.go b/rpc/args_test.go index f00899b790..8c1e8c4780 100644 --- a/rpc/args_test.go +++ b/rpc/args_test.go @@ -500,12 +500,18 @@ func TestNewTxArgsValueMissing(t *testing.T) { "gasPrice": "0x9184e72a000", "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" }]` + expected := new(NewTxArgs) + expected.Value = big.NewInt(0) args := new(NewTxArgs) - str := ExpectValidationError(json.Unmarshal([]byte(input), &args)) - if len(str) > 0 { - t.Error(str) + if err := json.Unmarshal([]byte(input), &args); err != nil { + t.Error(err) } + + if bytes.Compare(expected.Value.Bytes(), args.Value.Bytes()) != 0 { + t.Errorf("Value shoud be %v but is %v", expected.Value, args.Value) + } + } func TestNewTxArgsEmpty(t *testing.T) { From 1e28b424e7f0f0d16f467ac7bac08b9dc0384106 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 2 Apr 2015 14:00:49 +0200 Subject: [PATCH 32/33] Default gas --- rpc/api.go | 2 +- rpc/jeth.go | 2 ++ xeth/xeth.go | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/rpc/api.go b/rpc/api.go index 4a17d3b15a..44146c8c76 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -67,7 +67,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err case "eth_mining": *reply = api.xeth().IsMining() case "eth_gasPrice": - v := api.xeth().DefaultGas() + v := xeth.DefaultGas() *reply = common.ToHex(v.Bytes()) case "eth_accounts": *reply = api.xeth().Accounts() diff --git a/rpc/jeth.go b/rpc/jeth.go index 9d33f45e1d..e83212bb5c 100644 --- a/rpc/jeth.go +++ b/rpc/jeth.go @@ -2,6 +2,7 @@ package rpc import ( "encoding/json" + "fmt" // "fmt" "github.com/ethereum/go-ethereum/jsre" "github.com/robertkrimen/otto" @@ -42,6 +43,7 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) { var respif interface{} err = self.ethApi.GetRequestReply(&req, &respif) if err != nil { + fmt.Printf("error: %s\n", err) return self.err(-32603, err.Error(), req.Id) } self.re.Set("ret_jsonrpc", jsonrpcver) diff --git a/xeth/xeth.go b/xeth/xeth.go index cb2319865a..13a1838320 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -566,11 +566,11 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st } if msg.gas.Cmp(big.NewInt(0)) == 0 { - msg.gas = self.DefaultGas() + msg.gas = DefaultGas() } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { - msg.gasPrice = self.DefaultGasPrice() + msg.gasPrice = DefaultGasPrice() } block := self.CurrentBlock() @@ -616,11 +616,11 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt // TODO: align default values to have the same type, e.g. not depend on // common.Value conversions later on if gas.Cmp(big.NewInt(0)) == 0 { - gas = self.DefaultGas() + gas = DefaultGas() } if price.Cmp(big.NewInt(0)) == 0 { - price = self.DefaultGasPrice() + price = DefaultGasPrice() } data = common.FromHex(codeStr) From b4eef59b6f9631d22fdf62a2b1a40fe05209fccd Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 2 Apr 2015 14:05:14 +0200 Subject: [PATCH 33/33] No longer require gas & gas price in transactions Defaults to 0, which is then set to default values in XEth --- rpc/args.go | 4 ++-- rpc/args_test.go | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/rpc/args.go b/rpc/args.go index df57e69c4c..70618a01a4 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -207,7 +207,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { args.Value = big.NewInt(num) if ext.Gas == nil { - return NewValidationError("gas", "is required") + num = 0 } else { if err := numString(ext.Gas, &num); err != nil { return err @@ -216,7 +216,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { args.Gas = big.NewInt(num) if ext.GasPrice == nil { - return NewValidationError("gasprice", "is required") + num = 0 } else { if err := numString(ext.GasPrice, &num); err != nil { return err diff --git a/rpc/args_test.go b/rpc/args_test.go index 8c1e8c4780..902f8013e4 100644 --- a/rpc/args_test.go +++ b/rpc/args_test.go @@ -468,11 +468,16 @@ func TestNewTxArgsGasMissing(t *testing.T) { "value": "0x9184e72a000", "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" }]` + expected := new(NewTxArgs) + expected.Gas = big.NewInt(0) args := new(NewTxArgs) - str := ExpectValidationError(json.Unmarshal([]byte(input), &args)) - if len(str) > 0 { - t.Error(str) + if err := json.Unmarshal([]byte(input), &args); err != nil { + t.Error(err) + } + + if bytes.Compare(expected.Gas.Bytes(), args.Gas.Bytes()) != 0 { + t.Errorf("Gas shoud be %v but is %v", expected.Gas, args.Gas) } } @@ -484,12 +489,18 @@ func TestNewTxArgsBlockGaspriceMissing(t *testing.T) { "value": "0x9184e72a000", "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" }]` + expected := new(NewTxArgs) + expected.GasPrice = big.NewInt(0) args := new(NewTxArgs) - str := ExpectValidationError(json.Unmarshal([]byte(input), &args)) - if len(str) > 0 { - t.Error(str) + if err := json.Unmarshal([]byte(input), &args); err != nil { + t.Error(err) } + + if bytes.Compare(expected.GasPrice.Bytes(), args.GasPrice.Bytes()) != 0 { + t.Errorf("GasPrice shoud be %v but is %v", expected.GasPrice, args.GasPrice) + } + } func TestNewTxArgsValueMissing(t *testing.T) {