Merge branch 'develop' into bzz

This commit is contained in:
Daniel A. Nagy 2015-03-30 14:08:44 +02:00
commit 5273400437
24 changed files with 1767 additions and 514 deletions

6
.gitignore vendored
View file

@ -13,6 +13,8 @@
.ethtest
*/**/*tx_database*
*/**/*dapps*
Godeps/_workspace/pkg
Godeps/_workspace/bin
#*
.#*
@ -21,7 +23,9 @@
.project
.settings
cmd/ethereum/ethereum
geth
mist
cmd/geth/geth
cmd/mist/mist
deploy/osx/Mist.app
deploy/osx/Mist\ Installer.dmg

3
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "ethereal/assets/samplecoin"]
path = ethereal/assets/samplecoin
url = git@github.com:obscuren/SampleCoin.git
[submodule "cmd/mist/assets/ext/ethereum.js"]
path = cmd/mist/assets/ext/ethereum.js
url = https://github.com/ethereum/ethereum.js

View file

@ -10,3 +10,5 @@ Joseph Goulden <joegoulden@gmail.com>
Nick Savers <nicksavers@gmail.com>
Maran Hidskes <maran.hidskes@gmail.com>
Taylor Gerring <taylor.gerring@gmail.com> <taylor.gerring@ethereum.org>

View file

@ -9,7 +9,7 @@ install:
# - go get code.google.com/p/go.tools/cmd/goimports
# - go get github.com/golang/lint/golint
# - go get golang.org/x/tools/cmd/vet
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
before_script:
# - gofmt -l -w .

View file

@ -30,10 +30,10 @@ RUN mkdir -p $GOPATH/src/github.com/ethereum/
RUN git clone https://github.com/ethereum/go-ethereum $GOPATH/src/github.com/ethereum/go-ethereum
WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum
RUN git checkout develop
RUN GOPATH=$GOPATH:$GOPATH/src/github.com/ethereum/go-ethereum/Godeps/_workspace go install -v ./cmd/ethereum
RUN GOPATH=$GOPATH:$GOPATH/src/github.com/ethereum/go-ethereum/Godeps/_workspace go install -v ./cmd/geth
## Run & expose JSON RPC
ENTRYPOINT ["ethereum", "-rpc=true", "-rpcport=8545"]
ENTRYPOINT ["geth", "-rpc=true", "-rpcport=8545"]
EXPOSE 8545

View file

@ -4,8 +4,8 @@ Ethereum Go Client © 2014 Jeffrey Wilcke.
| Linux | OSX | Windows | Tests
----------|---------|-----|---------|------
develop | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=develop)](https://travis-ci.org/ethereum/go-ethereum)
master | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum)
develop | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=develop)](https://travis-ci.org/ethereum/go-ethereum) [![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.svg?branch=develop)](https://coveralls.io/r/ethereum/go-ethereum?branch=develop)
master | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum) [![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.svg?branch=master)](https://coveralls.io/r/ethereum/go-ethereum?branch=master)
[![Bugs](https://badge.waffle.io/ethereum/go-ethereum.png?label=bug&title=Bugs)](https://waffle.io/ethereum/go-ethereum)
[![Stories in Ready](https://badge.waffle.io/ethereum/go-ethereum.png?label=ready&title=Ready)](https://waffle.io/ethereum/go-ethereum)
@ -22,7 +22,7 @@ Mist (GUI):
Geth (CLI):
`go get github.com/ethereum/go-ethereum/cmd/ethereum`
`go get github.com/ethereum/go-ethereum/cmd/geth`
As of POC-8, go-ethereum uses [Godep](https://github.com/tools/godep) to manage dependencies. Assuming you have [your environment all set up](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum), switch to the go-ethereum repository root folder, and build/install the executable you need:

View file

@ -11,14 +11,18 @@ import (
)
type Execution struct {
env vm.Environment
address *common.Address
input []byte
env vm.Environment
address *common.Address
input []byte
evm vm.VirtualMachine
Gas, price, value *big.Int
}
func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution {
return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
exe := &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
exe.evm = vm.NewVm(env)
return exe
}
func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) {
@ -28,11 +32,17 @@ func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]by
return self.exec(&codeAddr, code, caller)
}
func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) {
ret, err = self.exec(nil, self.input, caller)
account = self.env.State().GetStateObject(*self.address)
return
}
func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) {
start := time.Now()
env := self.env
evm := vm.NewVm(env)
evm := self.evm
if env.Depth() == vm.MaxCallDepth {
caller.ReturnGas(self.Gas, self.price)
@ -70,10 +80,3 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
return
}
func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) {
ret, err = self.exec(nil, self.input, caller)
account = self.env.State().GetStateObject(*self.address)
return
}

View file

@ -12,17 +12,6 @@ type AccountChange struct {
Address, StateAddress []byte
}
type FilterOptions struct {
Earliest int64
Latest int64
Address []common.Address
Topics [][]common.Hash
Skip int
Max int
}
// Filtering interface
type Filter struct {
eth Backend
@ -44,18 +33,6 @@ func NewFilter(eth Backend) *Filter {
return &Filter{eth: eth}
}
// SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
// is simply because named arguments in this case is extremely nice and readable.
func (self *Filter) SetOptions(options *FilterOptions) {
self.earliest = options.Earliest
self.latest = options.Latest
self.skip = options.Skip
self.max = options.Max
self.address = options.Address
self.topics = options.Topics
}
// Set the earliest and latest block for filtering.
// -1 = latest block (i.e., the current block)
// hash = particular hash from-to

View file

@ -3,8 +3,8 @@ package vm
import (
"math/big"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
type Address interface {
@ -61,15 +61,32 @@ func ripemd160Func(in []byte) []byte {
return common.LeftPadBytes(crypto.Ripemd160(in), 32)
}
const ecRecoverInputLength = 128
func ecrecoverFunc(in []byte) []byte {
// In case of an invalid sig. Defaults to return nil
defer func() { recover() }()
// "in" is (hash, v, r, s), each 32 bytes
// but for ecrecover we want (r, s, v)
if len(in) < ecRecoverInputLength {
return nil
}
hash := in[:32]
v := common.BigD(in[32:64]).Bytes()[0] - 27
sig := append(in[64:], v)
// Treat V as a 256bit integer
v := new(big.Int).Sub(common.Bytes2Big(in[32:64]), big.NewInt(27))
// Ethereum requires V to be either 0 or 1 => (27 || 28)
if !(v.Cmp(Zero) == 0 || v.Cmp(One) == 0) {
return nil
}
return common.LeftPadBytes(crypto.Sha3(crypto.Ecrecover(append(hash, sig...))[1:])[12:], 32)
// v needs to be moved to the end
rsv := append(in[64:128], byte(v.Uint64()))
pubKey := crypto.Ecrecover(in[:32], rsv)
// make sure the public key is a valid one
if pubKey == nil || len(pubKey) != 65 {
return nil
}
// the first byte of pubkey is bitcoin heritage
return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32)
}
func memCpy(in []byte) []byte {

View file

@ -1,9 +1,25 @@
package vm
import "gopkg.in/fatih/set.v0"
import (
"math/big"
func analyseJumpDests(code []byte) (dests *set.Set) {
dests = set.New()
"gopkg.in/fatih/set.v0"
)
type destinations struct {
set *set.Set
}
func (d *destinations) Has(dest *big.Int) bool {
return d.set.Has(string(dest.Bytes()))
}
func (d *destinations) Add(dest *big.Int) {
d.set.Add(string(dest.Bytes()))
}
func analyseJumpDests(code []byte) (dests *destinations) {
dests = &destinations{set.New()}
for pc := uint64(0); pc < uint64(len(code)); pc++ {
var op OpCode = OpCode(code[pc])
@ -13,7 +29,7 @@ func analyseJumpDests(code []byte) (dests *set.Set) {
pc += a
case JUMPDEST:
dests.Add(pc)
dests.Add(big.NewInt(int64(pc)))
}
}
return

View file

@ -33,6 +33,7 @@ var (
S256 = common.S256
Zero = common.Big0
One = common.Big1
max = big.NewInt(math.MaxInt64)
)
@ -80,3 +81,13 @@ func getData(data []byte, start, size *big.Int) []byte {
e := common.BigMin(new(big.Int).Add(s, size), dlen)
return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
}
func UseGas(gas, amount *big.Int) bool {
if gas.Cmp(amount) < 0 {
return false
}
// Sub the amount of gas from the remaining
gas.Sub(gas, amount)
return true
}

View file

@ -1,7 +1,6 @@
package vm
import (
"math"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -41,29 +40,18 @@ func NewContext(caller ContextRef, object ContextRef, value, gas, price *big.Int
return c
}
func (c *Context) GetOp(n uint64) OpCode {
func (c *Context) GetOp(n *big.Int) OpCode {
return OpCode(c.GetByte(n))
}
func (c *Context) GetByte(n uint64) byte {
if n < uint64(len(c.Code)) {
return c.Code[n]
func (c *Context) GetByte(n *big.Int) byte {
if n.Cmp(big.NewInt(int64(len(c.Code)))) < 0 {
return c.Code[n.Int64()]
}
return 0
}
func (c *Context) GetBytes(x, y int) []byte {
return c.GetRangeValue(uint64(x), uint64(y))
}
func (c *Context) GetRangeValue(x, size uint64) []byte {
x = uint64(math.Min(float64(x), float64(len(c.Code))))
y := uint64(math.Min(float64(x+size), float64(len(c.Code))))
return common.RightPadBytes(c.Code[x:y], int(size))
}
func (c *Context) Return(ret []byte) []byte {
// Return the remaining gas to the caller
c.caller.ReturnGas(c.Gas, c.Price)
@ -74,16 +62,12 @@ func (c *Context) Return(ret []byte) []byte {
/*
* Gas functions
*/
func (c *Context) UseGas(gas *big.Int) bool {
if c.Gas.Cmp(gas) < 0 {
return false
func (c *Context) UseGas(gas *big.Int) (ok bool) {
ok = UseGas(c.Gas, gas)
if ok {
c.UsedGas.Add(c.UsedGas, gas)
}
// Sub the amount of gas from the remaining
c.Gas.Sub(c.Gas, gas)
c.UsedGas.Add(c.UsedGas, gas)
return true
return
}
// Implement the caller interface

View file

@ -24,6 +24,9 @@ type Vm struct {
Fn string
Recoverable bool
// Will be called before the vm returns
After func(*Context, error)
}
func New(env Environment) *Vm {
@ -47,6 +50,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
defer func() {
if self.After != nil {
self.After(context, err)
}
if err != nil {
self.Printf(" %v", err).Endl()
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
@ -65,23 +72,20 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
var (
op OpCode
destinations = analyseJumpDests(context.Code)
mem = NewMemory()
stack = newStack()
pc uint64 = 0
step = 0
statedb = self.env.State()
destinations = analyseJumpDests(context.Code)
mem = NewMemory()
stack = newStack()
pc = new(big.Int)
statedb = self.env.State()
jump = func(from uint64, to *big.Int) error {
p := to.Uint64()
nop := context.GetOp(p)
if !destinations.Has(p) {
return fmt.Errorf("invalid jump destination (%v) %v", nop, p)
jump = func(from *big.Int, to *big.Int) error {
nop := context.GetOp(to)
if !destinations.Has(to) {
return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
}
self.Printf(" ~> %v", to)
pc = to.Uint64()
pc = to
self.Endl()
@ -98,7 +102,6 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// The base for all big integer arithmetic
base := new(big.Int)
step++
// Get the memory location of pc
op = context.GetOp(pc)
@ -421,22 +424,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => %v", value)
case CALLDATALOAD:
var (
offset = stack.pop()
data = make([]byte, 32)
lenData = big.NewInt(int64(len(callData)))
)
if lenData.Cmp(offset) >= 0 {
length := new(big.Int).Add(offset, common.Big32)
length = common.BigMin(length, lenData)
copy(data, callData[offset.Int64():length.Int64()])
}
data := getData(callData, stack.pop(), common.Big32)
self.Printf(" => 0x%x", data)
stack.push(common.BigD(data))
stack.push(common.Bytes2Big(data))
case CALLDATASIZE:
l := int64(len(callData))
stack.push(big.NewInt(l))
@ -535,13 +527,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// 0x50 range
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
a := uint64(op - PUSH1 + 1)
byts := context.GetRangeValue(pc+1, a)
a := big.NewInt(int64(op - PUSH1 + 1))
byts := getData(code, new(big.Int).Add(pc, big.NewInt(1)), a)
// push value to stack
stack.push(common.BigD(byts))
pc += a
step += int(op) - int(PUSH1) + 1
stack.push(common.Bytes2Big(byts))
pc.Add(pc, a)
self.Printf(" => 0x%x", byts)
case POP:
@ -621,7 +611,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case JUMPDEST:
case PC:
stack.push(big.NewInt(int64(pc)))
//stack.push(big.NewInt(int64(pc)))
stack.push(pc)
case MSIZE:
stack.push(big.NewInt(int64(mem.Len())))
case GAS:
@ -647,7 +638,6 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" (*) 0x0 %v", suberr)
} else {
// gas < len(ret) * CreateDataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, GasCreateByte)
@ -728,7 +718,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
return nil, fmt.Errorf("Invalid opcode %x", op)
}
pc++
pc.Add(pc, One)
self.Endl()
}

View file

@ -54,21 +54,17 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *Execution {
return NewExecution(self, addr, data, gas, price, value)
}
func (self *VMEnv) Call(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
exe := self.vm(&addr, data, gas, price, value)
exe := NewExecution(self, &addr, data, gas, price, value)
return exe.Call(addr, me)
}
func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
maddr := me.Address()
exe := self.vm(&maddr, data, gas, price, value)
exe := NewExecution(self, &maddr, data, gas, price, value)
return exe.Call(addr, me)
}
func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
exe := self.vm(nil, data, gas, price, value)
exe := NewExecution(self, nil, data, gas, price, value)
return exe.Create(me)
}

View file

@ -68,13 +68,8 @@ func Ripemd160(data []byte) []byte {
return ripemd.Sum(nil)
}
func Ecrecover(data []byte) []byte {
var in = struct {
hash []byte
sig []byte
}{data[:32], data[32:]}
r, _ := secp256k1.RecoverPubkey(in.hash, in.sig)
func Ecrecover(hash, sig []byte) []byte {
r, _ := secp256k1.RecoverPubkey(hash, sig)
return r
}
@ -151,9 +146,12 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
}
func SigToPub(hash, sig []byte) *ecdsa.PublicKey {
s := Ecrecover(append(hash, sig...))
x, y := elliptic.Unmarshal(S256(), s)
s := Ecrecover(hash, sig)
if s == nil || len(s) != 65 {
return nil
}
x, y := elliptic.Unmarshal(S256(), s)
return &ecdsa.PublicKey{S256(), x, y}
}

View file

@ -6,7 +6,6 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/xeth"
)
@ -14,7 +13,6 @@ import (
type EthereumApi struct {
eth *xeth.XEth
xethMu sync.RWMutex
db common.Database
}
func NewEthereumApi(xeth *xeth.XEth) *EthereumApi {
@ -82,10 +80,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
if err := args.requirements(); err != nil {
return err
}
v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
*reply = common.ToHex(v.Bytes())
case "eth_getStorage", "eth_storageAt":
@ -94,36 +88,25 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
if err := args.requirements(); err != nil {
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage()
case "eth_getStorageAt":
args := new(GetStorageAtArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
if err := args.requirements(); err != nil {
return err
}
state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address)
value := state.StorageString(args.Key)
*reply = common.Bytes2Hex(value.Bytes())
*reply = common.ToHex(value.Bytes())
case "eth_getTransactionCount":
args := new(GetTxCountArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
err := args.requirements()
if err != nil {
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
count := api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
*reply = common.ToHex(big.NewInt(int64(count)).Bytes())
case "eth_getBlockTransactionCountByHash":
args := new(GetBlockByHashArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
@ -163,9 +146,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
if err := args.requirements(); err != nil {
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address)
case "eth_sendTransaction", "eth_transact":
args := new(NewTxArgs)
@ -173,10 +153,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
if err := args.requirements(); err != nil {
return err
}
v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
if err != nil {
return err
@ -267,8 +243,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewValidationError("Index", "does not exist")
}
uhash := br.Uncles[args.Index].Hex()
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash))
uhash := br.Uncles[args.Index]
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
*reply = uncle
case "eth_getUncleByBlockNumberAndIndex":
@ -285,8 +261,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewValidationError("Index", "does not exist")
}
uhash := v.Uncles[args.Index].Hex()
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash))
uhash := v.Uncles[args.Index]
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
*reply = uncle
case "eth_getCompilers":
@ -300,18 +276,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
opts := toFilterOptions(args)
id := api.xeth().RegisterFilter(opts)
id := api.xeth().RegisterFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
*reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_newBlockFilter":
args := new(FilterStringArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
if err := args.requirements(); err != nil {
return err
}
id := api.xeth().NewFilterString(args.Word)
*reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_uninstallFilter":
@ -337,8 +308,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
opts := toFilterOptions(args)
*reply = NewLogsRes(api.xeth().AllLogs(opts))
*reply = NewLogsRes(api.xeth().AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics))
case "eth_getWork":
api.xeth().SetMining(true)
*reply = api.xeth().RemoteMining().GetWork()
@ -347,7 +317,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
*reply = api.xeth().RemoteMining().SubmitWork(args.Nonce, args.Digest, args.Header)
*reply = api.xeth().RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header))
case "db_putString":
args := new(DbArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
@ -433,7 +403,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err
}
opts := new(xeth.Options)
opts.From = args.From
// opts.From = args.From
opts.To = args.To
opts.Topics = args.Topics
id := api.xeth().NewWhisperFilter(opts)
@ -483,46 +453,3 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil
}
func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
var opts core.FilterOptions
// Convert optional address slice/string to byte slice
if str, ok := options.Address.(string); ok {
opts.Address = []common.Address{common.HexToAddress(str)}
} else if slice, ok := options.Address.([]interface{}); ok {
bslice := make([]common.Address, len(slice))
for i, addr := range slice {
if saddr, ok := addr.(string); ok {
bslice[i] = common.HexToAddress(saddr)
}
}
opts.Address = bslice
}
opts.Earliest = options.Earliest
opts.Latest = options.Latest
topics := make([][]common.Hash, len(options.Topics))
for i, topicDat := range options.Topics {
if slice, ok := topicDat.([]interface{}); ok {
topics[i] = make([]common.Hash, len(slice))
for j, topic := range slice {
topics[i][j] = common.HexToHash(topic.(string))
}
} else if str, ok := topicDat.(string); ok {
topics[i] = []common.Hash{common.HexToHash(str)}
}
}
opts.Topics = topics
return &opts
}
/*
Work() chan<- *types.Block
SetWorkCh(chan<- Work)
Stop()
Start()
Rate() uint64
*/

View file

@ -1,16 +1,27 @@
package rpc
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
func blockHeight(raw interface{}, number *int64) (err error) {
const (
defaultLogLimit = 100
defaultLogOffset = 0
)
func blockHeightFromJson(msg json.RawMessage, number *int64) error {
var raw interface{}
if err := json.Unmarshal(msg, &raw); err != nil {
return NewDecodeParamError(err.Error())
}
return blockHeight(raw, number)
}
func blockHeight(raw interface{}, number *int64) error {
// Parse as integer
num, ok := raw.(float64)
if ok {
@ -21,7 +32,7 @@ func blockHeight(raw interface{}, number *int64) (err error) {
// Parse as string/hexstring
str, ok := raw.(string)
if !ok {
return NewDecodeParamError("BlockNumber is not a string")
return NewInvalidTypeError("", "not a number or string")
}
switch str {
@ -36,26 +47,55 @@ func blockHeight(raw interface{}, number *int64) (err error) {
return nil
}
func toNumber(v interface{}) (int64, error) {
var str string
if v != nil {
var ok bool
str, ok = v.(string)
if !ok {
return 0, errors.New("is not a string or undefined")
}
} else {
str = "latest"
func numString(raw interface{}, number *int64) error {
// Parse as integer
num, ok := raw.(float64)
if ok {
*number = int64(num)
return nil
}
switch str {
case "latest":
return -1, nil
default:
return int64(common.Big(v.(string)).Int64()), nil
// Parse as string/hexstring
str, ok := raw.(string)
if !ok {
return NewInvalidTypeError("", "not a number or string")
}
*number = common.String2Big(str).Int64()
return nil
}
// func toNumber(v interface{}) (int64, error) {
// var str string
// if v != nil {
// var ok bool
// str, ok = v.(string)
// if !ok {
// return 0, errors.New("is not a string or undefined")
// }
// } else {
// str = "latest"
// }
// switch str {
// case "latest":
// return -1, nil
// default:
// return int64(common.Big(v.(string)).Int64()), nil
// }
// }
// func hashString(raw interface{}, hash *string) error {
// argstr, ok := raw.(string)
// if !ok {
// return NewInvalidTypeError("", "not a string")
// }
// v := common.IsHex(argstr)
// hash = &argstr
// return nil
// }
type GetBlockByHashArgs struct {
BlockHash string
IncludeTxs bool
@ -63,8 +103,8 @@ type GetBlockByHashArgs struct {
func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -74,7 +114,7 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
argstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("BlockHash not a string")
return NewInvalidTypeError("blockHash", "not a string")
}
args.BlockHash = argstr
@ -92,8 +132,7 @@ type GetBlockByNumberArgs struct {
func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -103,8 +142,10 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
if v, ok := obj[0].(float64); ok {
args.BlockNumber = int64(v)
} else if v, ok := obj[0].(string); ok {
args.BlockNumber = common.Big(v).Int64()
} else {
args.BlockNumber = common.Big(obj[0].(string)).Int64()
return NewInvalidTypeError("blockNumber", "not a number or string")
}
if len(obj) > 1 {
@ -127,7 +168,14 @@ type NewTxArgs struct {
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
var obj []json.RawMessage
var ext struct{ From, To, Value, Gas, GasPrice, Data string }
var ext struct {
From string
To string
Value interface{}
Gas interface{}
GasPrice interface{}
Data string
}
// Decode byte slice to array of RawMessages
if err := json.Unmarshal(b, &obj); err != nil {
@ -144,22 +192,45 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return NewDecodeParamError(err.Error())
}
// var ok bool
if len(ext.From) == 0 {
return NewValidationError("from", "is required")
}
args.From = ext.From
args.To = ext.To
args.Value = common.String2Big(ext.Value)
args.Gas = common.String2Big(ext.Gas)
args.GasPrice = common.String2Big(ext.GasPrice)
args.Data = ext.Data
var num int64
if ext.Value == nil {
return NewValidationError("value", "is required")
} else {
if err := numString(ext.Value, &num); err != nil {
return err
}
}
args.Value = big.NewInt(num)
if ext.Gas == nil {
return NewValidationError("gas", "is required")
} else {
if err := numString(ext.Gas, &num); err != nil {
return err
}
}
args.Gas = big.NewInt(num)
if ext.GasPrice == nil {
return NewValidationError("gasprice", "is required")
} else {
if err := numString(ext.GasPrice, &num); err != nil {
return err
}
}
args.GasPrice = big.NewInt(num)
// Check for optional BlockNumber param
if len(obj) > 1 {
var raw interface{}
if err = json.Unmarshal(obj[1], &raw); err != nil {
return NewDecodeParamError(err.Error())
}
if err := blockHeight(raw, &args.BlockNumber); err != nil {
if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
return err
}
}
@ -167,13 +238,6 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *NewTxArgs) requirements() error {
if len(args.From) == 0 {
return NewValidationError("From", "Is required")
}
return nil
}
type GetStorageArgs struct {
Address string
BlockNumber int64
@ -191,7 +255,7 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Address is not a string")
return NewInvalidTypeError("address", "not a string")
}
args.Address = addstr
@ -204,13 +268,6 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *GetStorageArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetStorageAtArgs struct {
Address string
Key string
@ -229,13 +286,13 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Address is not a string")
return NewInvalidTypeError("address", "not a string")
}
args.Address = addstr
keystr, ok := obj[1].(string)
if !ok {
return NewDecodeParamError("Key is not a string")
return NewInvalidTypeError("key", "not a string")
}
args.Key = keystr
@ -248,17 +305,6 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *GetStorageAtArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
if len(args.Key) == 0 {
return NewValidationError("Key", "cannot be blank")
}
return nil
}
type GetTxCountArgs struct {
Address string
BlockNumber int64
@ -276,7 +322,7 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Address is not a string")
return NewInvalidTypeError("address", "not a string")
}
args.Address = addstr
@ -289,13 +335,6 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *GetTxCountArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetBalanceArgs struct {
Address string
BlockNumber int64
@ -313,7 +352,7 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Address is not a string")
return NewInvalidTypeError("address", "not a string")
}
args.Address = addstr
@ -326,13 +365,6 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *GetBalanceArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetDataArgs struct {
Address string
BlockNumber int64
@ -350,7 +382,7 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Address is not a string")
return NewInvalidTypeError("address", "not a string")
}
args.Address = addstr
@ -363,13 +395,6 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
func (args *GetDataArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type BlockNumIndexArgs struct {
BlockNumber int64
Index int64
@ -377,8 +402,7 @@ type BlockNumIndexArgs struct {
func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -386,16 +410,14 @@ func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
arg0, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("BlockNumber is not string")
if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
return err
}
args.BlockNumber = common.Big(arg0).Int64()
if len(obj) > 1 {
arg1, ok := obj[1].(string)
if !ok {
return NewDecodeParamError("Index not a string")
return NewInvalidTypeError("index", "not a string")
}
args.Index = common.Big(arg1).Int64()
}
@ -410,8 +432,7 @@ type HashIndexArgs struct {
func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -421,14 +442,14 @@ func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
arg0, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Hash not a string")
return NewInvalidTypeError("hash", "not a string")
}
args.Hash = arg0
if len(obj) > 1 {
arg1, ok := obj[1].(string)
if !ok {
return NewDecodeParamError("Index not a string")
return NewInvalidTypeError("index", "not a string")
}
args.Index = common.Big(arg1).Int64()
}
@ -442,36 +463,39 @@ type Sha3Args struct {
func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
if len(obj) < 1 {
return NewInsufficientParamsError(len(obj), 1)
}
args.Data = obj[0].(string)
argstr, ok := obj[0].(string)
if !ok {
return NewInvalidTypeError("data", "is not a string")
}
args.Data = argstr
return nil
}
type BlockFilterArgs struct {
Earliest int64
Latest int64
Address interface{}
Topics []interface{}
Address []string
Topics [][]string
Skip int
Max int
}
func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct {
FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"`
Limit string `json:"limit"`
Offset string `json:"offset"`
Address string `json:"address"`
Topics []interface{} `json:"topics"`
FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"`
Limit interface{} `json:"limit"`
Offset interface{} `json:"offset"`
Address interface{} `json:"address"`
Topics interface{} `json:"topics"`
}
if err = json.Unmarshal(b, &obj); err != nil {
@ -482,19 +506,113 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
args.Earliest, err = toNumber(obj[0].ToBlock)
if err != nil {
return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
// args.Earliest, err = toNumber(obj[0].ToBlock)
// if err != nil {
// return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
// }
// args.Latest, err = toNumber(obj[0].FromBlock)
// if err != nil {
// return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
var num int64
// if blank then latest
if obj[0].FromBlock == nil {
num = -1
} else {
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
return err
}
}
args.Latest, err = toNumber(obj[0].FromBlock)
if err != nil {
return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
// if -2 or other "silly" number, use latest
if num < 0 {
args.Earliest = -1 //latest block
} else {
args.Earliest = num
}
args.Max = int(common.Big(obj[0].Limit).Int64())
args.Skip = int(common.Big(obj[0].Offset).Int64())
args.Address = obj[0].Address
args.Topics = obj[0].Topics
// if blank than latest
if obj[0].ToBlock == nil {
num = -1
} else {
if err := blockHeight(obj[0].ToBlock, &num); err != nil {
return err
}
}
args.Latest = num
if obj[0].Limit == nil {
num = defaultLogLimit
} else {
if err := numString(obj[0].Limit, &num); err != nil {
return err
}
}
args.Max = int(num)
if obj[0].Offset == nil {
num = defaultLogOffset
} else {
if err := numString(obj[0].Offset, &num); err != nil {
return err
}
}
args.Skip = int(num)
if obj[0].Address != nil {
marg, ok := obj[0].Address.([]interface{})
if ok {
v := make([]string, len(marg))
for i, arg := range marg {
argstr, ok := arg.(string)
if !ok {
return NewInvalidTypeError(fmt.Sprintf("address[%d]", i), "is not a string")
}
v[i] = argstr
}
args.Address = v
} else {
argstr, ok := obj[0].Address.(string)
if ok {
v := make([]string, 1)
v[0] = argstr
args.Address = v
} else {
return NewInvalidTypeError("address", "is not a string or array")
}
}
}
if obj[0].Topics != nil {
other, ok := obj[0].Topics.([]interface{})
if ok {
topicdbl := make([][]string, len(other))
for i, iv := range other {
if argstr, ok := iv.(string); ok {
// Found a string, push into first element of array
topicsgl := make([]string, 1)
topicsgl[0] = argstr
topicdbl[i] = topicsgl
} else if argarray, ok := iv.([]interface{}); ok {
// Found an array of other
topicdbl[i] = make([]string, len(argarray))
for j, jv := range argarray {
if v, ok := jv.(string); ok {
topicdbl[i][j] = v
} else {
return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", i, j), "is not a string")
}
}
} else {
return NewInvalidTypeError(fmt.Sprintf("topic[%d]", i), "not a string or array")
}
}
args.Topics = topicdbl
return nil
} else {
return NewInvalidTypeError("topic", "is not a string or array")
}
}
return nil
}
@ -519,19 +637,19 @@ func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
var ok bool
if objstr, ok = obj[0].(string); !ok {
return NewDecodeParamError("Database is not a string")
return NewInvalidTypeError("database", "not a string")
}
args.Database = objstr
if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Key is not a string")
return NewInvalidTypeError("key", "not a string")
}
args.Key = objstr
if len(obj) > 2 {
objstr, ok = obj[2].(string)
if !ok {
return NewDecodeParamError("Value is not a string")
return NewInvalidTypeError("value", "not a string")
}
args.Value = []byte(objstr)
@ -570,19 +688,19 @@ func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
var ok bool
if objstr, ok = obj[0].(string); !ok {
return NewDecodeParamError("Database is not a string")
return NewInvalidTypeError("database", "not a string")
}
args.Database = objstr
if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Key is not a string")
return NewInvalidTypeError("key", "not a string")
}
args.Key = objstr
if len(obj) > 2 {
objstr, ok = obj[2].(string)
if !ok {
return NewDecodeParamError("Value is not a string")
return NewInvalidTypeError("value", "not a string")
}
args.Value = common.FromHex(objstr)
@ -616,8 +734,8 @@ func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
To string
From string
Topics []string
Priority string
Ttl string
Priority interface{}
Ttl interface{}
}
if err = json.Unmarshal(b, &obj); err != nil {
@ -631,8 +749,17 @@ func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
args.To = obj[0].To
args.From = obj[0].From
args.Topics = obj[0].Topics
args.Priority = uint32(common.Big(obj[0].Priority).Int64())
args.Ttl = uint32(common.Big(obj[0].Ttl).Int64())
var num int64
if err := numString(obj[0].Priority, &num); err != nil {
return err
}
args.Priority = uint32(num)
if err := numString(obj[0].Ttl, &num); err != nil {
return err
}
args.Ttl = uint32(num)
return nil
}
@ -643,14 +770,18 @@ type CompileArgs struct {
func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
if len(obj) > 0 {
args.Source = obj[0].(string)
if len(obj) < 1 {
return NewInsufficientParamsError(len(obj), 1)
}
argstr, ok := obj[0].(string)
if !ok {
return NewInvalidTypeError("arg0", "is not a string")
}
args.Source = argstr
return nil
}
@ -661,8 +792,7 @@ type FilterStringArgs struct {
func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -673,20 +803,15 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
var argstr string
argstr, ok := obj[0].(string)
if !ok {
return NewDecodeParamError("Filter is not a string")
return NewInvalidTypeError("filter", "not a string")
}
args.Word = argstr
return nil
}
func (args *FilterStringArgs) requirements() error {
switch args.Word {
switch argstr {
case "latest", "pending":
break
default:
return NewValidationError("Word", "Must be `latest` or `pending`")
}
args.Word = argstr
return nil
}
@ -695,9 +820,8 @@ type FilterIdArgs struct {
}
func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
var obj []string
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -705,7 +829,11 @@ func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
args.Id = int(common.Big(obj[0]).Int64())
var num int64
if err := numString(obj[0], &num); err != nil {
return err
}
args.Id = int(num)
return nil
}
@ -715,9 +843,8 @@ type WhisperIdentityArgs struct {
}
func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
var obj []string
r := bytes.NewReader(b)
if err := json.NewDecoder(r).Decode(&obj); err != nil {
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
@ -725,7 +852,14 @@ func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
args.Identity = obj[0]
argstr, ok := obj[0].(string)
if !ok {
return NewInvalidTypeError("arg0", "not a string")
}
// if !common.IsHex(argstr) {
// return NewValidationError("arg0", "not a hexstring")
// }
args.Identity = argstr
return nil
}
@ -738,9 +872,8 @@ type WhisperFilterArgs struct {
func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct {
To string
From string
Topics []string
To interface{}
Topics []interface{}
}
if err = json.Unmarshal(b, &obj); err != nil {
@ -751,17 +884,30 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
args.To = obj[0].To
args.From = obj[0].From
args.Topics = obj[0].Topics
var argstr string
argstr, ok := obj[0].To.(string)
if !ok {
return NewInvalidTypeError("to", "is not a string")
}
args.To = argstr
t := make([]string, len(obj[0].Topics))
for i, j := range obj[0].Topics {
argstr, ok := j.(string)
if !ok {
return NewInvalidTypeError("topics["+string(i)+"]", "is not a string")
}
t[i] = argstr
}
args.Topics = t
return nil
}
type SubmitWorkArgs struct {
Nonce uint64
Header common.Hash
Digest common.Hash
Header string
Digest string
}
func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
@ -777,21 +923,21 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
var objstr string
var ok bool
if objstr, ok = obj[0].(string); !ok {
return NewDecodeParamError("Nonce is not a string")
return NewInvalidTypeError("nonce", "not a string")
}
args.Nonce = common.String2Big(objstr).Uint64()
if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Header is not a string")
return NewInvalidTypeError("header", "not a string")
}
args.Header = common.HexToHash(objstr)
args.Header = objstr
if objstr, ok = obj[2].(string); !ok {
return NewDecodeParamError("Digest is not a string")
return NewInvalidTypeError("digest", "not a string")
}
args.Digest = common.HexToHash(objstr)
args.Digest = objstr
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -76,7 +76,7 @@ func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} {
case *NotImplementedError:
jsonerr := &RpcErrorObject{-32601, reserr.Error()}
response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
case *DecodeParamError, *InsufficientParamsError, *ValidationError, *InvalidTypeError:
jsonerr := &RpcErrorObject{-32602, reserr.Error()}
response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
default:

View file

@ -21,6 +21,22 @@ import (
"fmt"
)
type InvalidTypeError struct {
method string
msg string
}
func (e *InvalidTypeError) Error() string {
return fmt.Sprintf("invalid type on field %s: %s", e.method, e.msg)
}
func NewInvalidTypeError(method, msg string) *InvalidTypeError {
return &InvalidTypeError{
method: method,
msg: msg,
}
}
type InsufficientParamsError struct {
have int
want int

View file

@ -4,6 +4,15 @@ import (
"testing"
)
func TestInvalidTypeError(t *testing.T) {
err := NewInvalidTypeError("testField", "not string")
expected := "invalid type on field testField: not string"
if err.Error() != expected {
t.Error(err.Error())
}
}
func TestInsufficientParamsError(t *testing.T) {
err := NewInsufficientParamsError(0, 1)
expected := "insufficient params, want 1 have 0"

View file

@ -70,7 +70,7 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) {
ext.Difficulty = common.ToHex(b.Difficulty.Bytes())
ext.TotalDifficulty = common.ToHex(b.TotalDifficulty.Bytes())
ext.Size = common.ToHex(b.Size.Bytes())
// ext.ExtraData = common.ToHex(b.ExtraData)
ext.ExtraData = common.ToHex(b.ExtraData)
ext.GasLimit = common.ToHex(b.GasLimit.Bytes())
// ext.MinGasPrice = common.ToHex(big.NewInt(b.MinGasPrice).Bytes())
ext.GasUsed = common.ToHex(b.GasUsed.Bytes())
@ -111,7 +111,7 @@ func NewBlockRes(block *types.Block) *BlockRes {
res.Difficulty = block.Difficulty()
res.TotalDifficulty = block.Td
res.Size = big.NewInt(int64(block.Size()))
// res.ExtraData =
res.ExtraData = []byte(block.Header().Extra)
res.GasLimit = block.GasLimit()
// res.MinGasPrice =
res.GasUsed = block.GasUsed()
@ -243,8 +243,8 @@ func (l *LogRes) MarshalJSON() ([]byte, error) {
}
ext.Address = l.Address.Hex()
ext.Data = common.Bytes2Hex(l.Data)
ext.Number = common.Bytes2Hex(big.NewInt(int64(l.Number)).Bytes())
ext.Data = common.ToHex(l.Data)
ext.Number = common.ToHex(big.NewInt(int64(l.Number)).Bytes())
ext.Topics = make([]string, len(l.Topics))
for i, v := range l.Topics {
ext.Topics[i] = v.Hex()

View file

@ -40,7 +40,7 @@ var (
extensions = []string{".go", ".js", ".qml"}
// paths with any of these prefixes will be skipped
skipPrefixes = []string{"tests/files/", "cmd/mist/assets/ext/", "cmd/mist/assets/muted/"}
skipPrefixes = []string{"Godeps/", "tests/files/", "cmd/mist/assets/ext/", "cmd/mist/assets/muted/"}
// paths with this prefix are licensed as GPL. all other files are LGPL.
gplPrefixes = []string{"cmd/"}
@ -190,7 +190,7 @@ func fileInfo(file string) (*info, error) {
break
}
}
cmd := exec.Command("git", "log", "--follow", "--find-copies", "--pretty=format:%aI | %aN <%aE>", "--", file)
cmd := exec.Command("git", "log", "--follow", "--find-copies", "--pretty=format:%ai | %aN <%aE>", "--", file)
err := doLines(cmd, func(line string) {
sep := strings.IndexByte(line, '|')
year, name := line[:4], line[sep+2:]

View file

@ -110,6 +110,24 @@ func (self *XEth) stop() {
close(self.quit)
}
func cAddress(a []string) []common.Address {
bslice := make([]common.Address, len(a))
for i, addr := range a {
bslice[i] = common.HexToAddress(addr)
}
return bslice
}
func cTopics(t [][]string) [][]common.Hash {
topics := make([][]common.Hash, len(t))
for i, iv := range t {
for j, jv := range iv {
topics[i][j] = common.HexToHash(jv)
}
}
return topics
}
func (self *XEth) DefaultGas() *big.Int { return defaultGas }
func (self *XEth) DefaultGasPrice() *big.Int { return defaultGasPrice }
@ -228,15 +246,15 @@ func (self *XEth) IsMining() bool {
}
func (self *XEth) EthVersion() string {
return string(self.backend.EthVersion())
return fmt.Sprintf("%d", self.backend.EthVersion())
}
func (self *XEth) NetworkVersion() string {
return string(self.backend.NetVersion())
return fmt.Sprintf("%d", self.backend.NetVersion())
}
func (self *XEth) WhisperVersion() string {
return string(self.backend.ShhVersion())
return fmt.Sprintf("%d", self.backend.ShhVersion())
}
func (self *XEth) ClientVersion() string {
@ -301,10 +319,15 @@ func (self *XEth) SecretToAddress(key string) string {
return common.ToHex(pair.Address())
}
func (self *XEth) RegisterFilter(args *core.FilterOptions) int {
func (self *XEth) RegisterFilter(earliest, latest int64, skip, max int, address []string, topics [][]string) int {
var id int
filter := core.NewFilter(self.backend)
filter.SetOptions(args)
filter.SetEarliestBlock(earliest)
filter.SetLatestBlock(latest)
filter.SetSkip(skip)
filter.SetMax(max)
filter.SetAddress(cAddress(address))
filter.SetTopics(cTopics(topics))
filter.LogsCallback = func(logs state.Logs) {
self.logMut.Lock()
defer self.logMut.Unlock()
@ -380,9 +403,14 @@ func (self *XEth) Logs(id int) state.Logs {
return nil
}
func (self *XEth) AllLogs(args *core.FilterOptions) state.Logs {
func (self *XEth) AllLogs(earliest, latest int64, skip, max int, address []string, topics [][]string) state.Logs {
filter := core.NewFilter(self.backend)
filter.SetOptions(args)
filter.SetEarliestBlock(earliest)
filter.SetLatestBlock(latest)
filter.SetSkip(skip)
filter.SetMax(max)
filter.SetAddress(cAddress(address))
filter.SetTopics(cTopics(topics))
return filter.Find()
}