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 .ethtest
*/**/*tx_database* */**/*tx_database*
*/**/*dapps* */**/*dapps*
Godeps/_workspace/pkg
Godeps/_workspace/bin
#* #*
.#* .#*
@ -21,7 +23,9 @@
.project .project
.settings .settings
cmd/ethereum/ethereum geth
mist
cmd/geth/geth
cmd/mist/mist cmd/mist/mist
deploy/osx/Mist.app deploy/osx/Mist.app
deploy/osx/Mist\ Installer.dmg 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"] [submodule "cmd/mist/assets/ext/ethereum.js"]
path = cmd/mist/assets/ext/ethereum.js path = cmd/mist/assets/ext/ethereum.js
url = https://github.com/ethereum/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> Nick Savers <nicksavers@gmail.com>
Maran Hidskes <maran.hidskes@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 code.google.com/p/go.tools/cmd/goimports
# - go get github.com/golang/lint/golint # - go get github.com/golang/lint/golint
# - go get golang.org/x/tools/cmd/vet # - 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 - go get github.com/mattn/goveralls
before_script: before_script:
# - gofmt -l -w . # - 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 RUN git clone https://github.com/ethereum/go-ethereum $GOPATH/src/github.com/ethereum/go-ethereum
WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum
RUN git checkout develop 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 ## Run & expose JSON RPC
ENTRYPOINT ["ethereum", "-rpc=true", "-rpcport=8545"] ENTRYPOINT ["geth", "-rpc=true", "-rpcport=8545"]
EXPOSE 8545 EXPOSE 8545

View file

@ -4,8 +4,8 @@ Ethereum Go Client © 2014 Jeffrey Wilcke.
| Linux | OSX | Windows | Tests | 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) 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) 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) [![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) [![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): 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: 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

@ -14,11 +14,15 @@ type Execution struct {
env vm.Environment env vm.Environment
address *common.Address address *common.Address
input []byte input []byte
evm vm.VirtualMachine
Gas, price, value *big.Int Gas, price, value *big.Int
} }
func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution { 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) { 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) 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) { func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) {
start := time.Now() start := time.Now()
env := self.env env := self.env
evm := vm.NewVm(env) evm := self.evm
if env.Depth() == vm.MaxCallDepth { if env.Depth() == vm.MaxCallDepth {
caller.ReturnGas(self.Gas, self.price) caller.ReturnGas(self.Gas, self.price)
@ -70,10 +80,3 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
return 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 Address, StateAddress []byte
} }
type FilterOptions struct {
Earliest int64
Latest int64
Address []common.Address
Topics [][]common.Hash
Skip int
Max int
}
// Filtering interface // Filtering interface
type Filter struct { type Filter struct {
eth Backend eth Backend
@ -44,18 +33,6 @@ func NewFilter(eth Backend) *Filter {
return &Filter{eth: eth} 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. // Set the earliest and latest block for filtering.
// -1 = latest block (i.e., the current block) // -1 = latest block (i.e., the current block)
// hash = particular hash from-to // hash = particular hash from-to

View file

@ -3,8 +3,8 @@ package vm
import ( import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
) )
type Address interface { type Address interface {
@ -61,15 +61,32 @@ func ripemd160Func(in []byte) []byte {
return common.LeftPadBytes(crypto.Ripemd160(in), 32) return common.LeftPadBytes(crypto.Ripemd160(in), 32)
} }
const ecRecoverInputLength = 128
func ecrecoverFunc(in []byte) []byte { func ecrecoverFunc(in []byte) []byte {
// In case of an invalid sig. Defaults to return nil // "in" is (hash, v, r, s), each 32 bytes
defer func() { recover() }() // but for ecrecover we want (r, s, v)
if len(in) < ecRecoverInputLength {
return nil
}
hash := in[:32] // Treat V as a 256bit integer
v := common.BigD(in[32:64]).Bytes()[0] - 27 v := new(big.Int).Sub(common.Bytes2Big(in[32:64]), big.NewInt(27))
sig := append(in[64:], v) // 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 { func memCpy(in []byte) []byte {

View file

@ -1,9 +1,25 @@
package vm package vm
import "gopkg.in/fatih/set.v0" import (
"math/big"
func analyseJumpDests(code []byte) (dests *set.Set) { "gopkg.in/fatih/set.v0"
dests = set.New() )
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++ { for pc := uint64(0); pc < uint64(len(code)); pc++ {
var op OpCode = OpCode(code[pc]) var op OpCode = OpCode(code[pc])
@ -13,7 +29,7 @@ func analyseJumpDests(code []byte) (dests *set.Set) {
pc += a pc += a
case JUMPDEST: case JUMPDEST:
dests.Add(pc) dests.Add(big.NewInt(int64(pc)))
} }
} }
return return

View file

@ -33,6 +33,7 @@ var (
S256 = common.S256 S256 = common.S256
Zero = common.Big0 Zero = common.Big0
One = common.Big1
max = big.NewInt(math.MaxInt64) 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) e := common.BigMin(new(big.Int).Add(s, size), dlen)
return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) 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 package vm
import ( import (
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -41,29 +40,18 @@ func NewContext(caller ContextRef, object ContextRef, value, gas, price *big.Int
return c return c
} }
func (c *Context) GetOp(n uint64) OpCode { func (c *Context) GetOp(n *big.Int) OpCode {
return OpCode(c.GetByte(n)) return OpCode(c.GetByte(n))
} }
func (c *Context) GetByte(n uint64) byte { func (c *Context) GetByte(n *big.Int) byte {
if n < uint64(len(c.Code)) { if n.Cmp(big.NewInt(int64(len(c.Code)))) < 0 {
return c.Code[n] return c.Code[n.Int64()]
} }
return 0 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 { func (c *Context) Return(ret []byte) []byte {
// Return the remaining gas to the caller // Return the remaining gas to the caller
c.caller.ReturnGas(c.Gas, c.Price) c.caller.ReturnGas(c.Gas, c.Price)
@ -74,16 +62,12 @@ func (c *Context) Return(ret []byte) []byte {
/* /*
* Gas functions * Gas functions
*/ */
func (c *Context) UseGas(gas *big.Int) bool { func (c *Context) UseGas(gas *big.Int) (ok bool) {
if c.Gas.Cmp(gas) < 0 { ok = UseGas(c.Gas, gas)
return false if ok {
}
// Sub the amount of gas from the remaining
c.Gas.Sub(c.Gas, gas)
c.UsedGas.Add(c.UsedGas, gas) c.UsedGas.Add(c.UsedGas, gas)
}
return true return
} }
// Implement the caller interface // Implement the caller interface

View file

@ -24,6 +24,9 @@ type Vm struct {
Fn string Fn string
Recoverable bool Recoverable bool
// Will be called before the vm returns
After func(*Context, error)
} }
func New(env Environment) *Vm { 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. // User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
defer func() { defer func() {
if self.After != nil {
self.After(context, err)
}
if err != nil { if err != nil {
self.Printf(" %v", err).Endl() self.Printf(" %v", err).Endl()
// In case of a VM exception (known exceptions) all gas consumed (panics NOT included). // In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
@ -68,20 +75,17 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
destinations = analyseJumpDests(context.Code) destinations = analyseJumpDests(context.Code)
mem = NewMemory() mem = NewMemory()
stack = newStack() stack = newStack()
pc uint64 = 0 pc = new(big.Int)
step = 0
statedb = self.env.State() statedb = self.env.State()
jump = func(from uint64, to *big.Int) error { jump = func(from *big.Int, to *big.Int) error {
p := to.Uint64() nop := context.GetOp(to)
if !destinations.Has(to) {
nop := context.GetOp(p) return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
if !destinations.Has(p) {
return fmt.Errorf("invalid jump destination (%v) %v", nop, p)
} }
self.Printf(" ~> %v", to) self.Printf(" ~> %v", to)
pc = to.Uint64() pc = to
self.Endl() 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 // The base for all big integer arithmetic
base := new(big.Int) base := new(big.Int)
step++
// Get the memory location of pc // Get the memory location of pc
op = context.GetOp(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) self.Printf(" => %v", value)
case CALLDATALOAD: case CALLDATALOAD:
var ( data := getData(callData, stack.pop(), common.Big32)
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()])
}
self.Printf(" => 0x%x", data) self.Printf(" => 0x%x", data)
stack.push(common.BigD(data)) stack.push(common.Bytes2Big(data))
case CALLDATASIZE: case CALLDATASIZE:
l := int64(len(callData)) l := int64(len(callData))
stack.push(big.NewInt(l)) stack.push(big.NewInt(l))
@ -535,13 +527,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// 0x50 range // 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: 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) a := big.NewInt(int64(op - PUSH1 + 1))
byts := context.GetRangeValue(pc+1, a) byts := getData(code, new(big.Int).Add(pc, big.NewInt(1)), a)
// push value to stack // push value to stack
stack.push(common.BigD(byts)) stack.push(common.Bytes2Big(byts))
pc += a pc.Add(pc, a)
step += int(op) - int(PUSH1) + 1
self.Printf(" => 0x%x", byts) self.Printf(" => 0x%x", byts)
case POP: case POP:
@ -621,7 +611,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case JUMPDEST: case JUMPDEST:
case PC: case PC:
stack.push(big.NewInt(int64(pc))) //stack.push(big.NewInt(int64(pc)))
stack.push(pc)
case MSIZE: case MSIZE:
stack.push(big.NewInt(int64(mem.Len()))) stack.push(big.NewInt(int64(mem.Len())))
case GAS: case GAS:
@ -647,7 +638,6 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" (*) 0x0 %v", suberr) self.Printf(" (*) 0x0 %v", suberr)
} else { } else {
// gas < len(ret) * CreateDataGas == NO_CODE // gas < len(ret) * CreateDataGas == NO_CODE
dataGas := big.NewInt(int64(len(ret))) dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, GasCreateByte) 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) return nil, fmt.Errorf("Invalid opcode %x", op)
} }
pc++ pc.Add(pc, One)
self.Endl() 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) 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) { 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) return exe.Call(addr, me)
} }
func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
maddr := me.Address() maddr := me.Address()
exe := self.vm(&maddr, data, gas, price, value) exe := NewExecution(self, &maddr, data, gas, price, value)
return exe.Call(addr, me) return exe.Call(addr, me)
} }
func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { 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) return exe.Create(me)
} }

View file

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

View file

@ -6,7 +6,6 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
@ -14,7 +13,6 @@ import (
type EthereumApi struct { type EthereumApi struct {
eth *xeth.XEth eth *xeth.XEth
xethMu sync.RWMutex xethMu sync.RWMutex
db common.Database
} }
func NewEthereumApi(xeth *xeth.XEth) *EthereumApi { func NewEthereumApi(xeth *xeth.XEth) *EthereumApi {
@ -82,10 +80,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
if err := args.requirements(); err != nil {
return err
}
v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance() v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
*reply = common.ToHex(v.Bytes()) *reply = common.ToHex(v.Bytes())
case "eth_getStorage", "eth_storageAt": case "eth_getStorage", "eth_storageAt":
@ -94,36 +88,25 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
if err := args.requirements(); err != nil {
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage() *reply = api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage()
case "eth_getStorageAt": case "eth_getStorageAt":
args := new(GetStorageAtArgs) args := new(GetStorageAtArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
return err return err
} }
if err := args.requirements(); err != nil {
return err
}
state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address) state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address)
value := state.StorageString(args.Key) value := state.StorageString(args.Key)
*reply = common.Bytes2Hex(value.Bytes()) *reply = common.ToHex(value.Bytes())
case "eth_getTransactionCount": case "eth_getTransactionCount":
args := new(GetTxCountArgs) args := new(GetTxCountArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
return err return err
} }
err := args.requirements() count := api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
if err != nil { *reply = common.ToHex(big.NewInt(int64(count)).Bytes())
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
case "eth_getBlockTransactionCountByHash": case "eth_getBlockTransactionCountByHash":
args := new(GetBlockByHashArgs) args := new(GetBlockByHashArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { 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 { if err := json.Unmarshal(req.Params, &args); err != nil {
return err return err
} }
if err := args.requirements(); err != nil {
return err
}
*reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address) *reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address)
case "eth_sendTransaction", "eth_transact": case "eth_sendTransaction", "eth_transact":
args := new(NewTxArgs) args := new(NewTxArgs)
@ -173,10 +153,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return 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) v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
if err != nil { if err != nil {
return err return err
@ -267,8 +243,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewValidationError("Index", "does not exist") return NewValidationError("Index", "does not exist")
} }
uhash := br.Uncles[args.Index].Hex() uhash := br.Uncles[args.Index]
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash)) uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
*reply = uncle *reply = uncle
case "eth_getUncleByBlockNumberAndIndex": case "eth_getUncleByBlockNumberAndIndex":
@ -285,8 +261,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewValidationError("Index", "does not exist") return NewValidationError("Index", "does not exist")
} }
uhash := v.Uncles[args.Index].Hex() uhash := v.Uncles[args.Index]
uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash)) uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
*reply = uncle *reply = uncle
case "eth_getCompilers": case "eth_getCompilers":
@ -300,18 +276,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
opts := toFilterOptions(args) id := api.xeth().RegisterFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
id := api.xeth().RegisterFilter(opts)
*reply = common.ToHex(big.NewInt(int64(id)).Bytes()) *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_newBlockFilter": case "eth_newBlockFilter":
args := new(FilterStringArgs) args := new(FilterStringArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
return err return err
} }
if err := args.requirements(); err != nil {
return err
}
id := api.xeth().NewFilterString(args.Word) id := api.xeth().NewFilterString(args.Word)
*reply = common.ToHex(big.NewInt(int64(id)).Bytes()) *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_uninstallFilter": 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 { if err := json.Unmarshal(req.Params, &args); err != nil {
return err return err
} }
opts := toFilterOptions(args) *reply = NewLogsRes(api.xeth().AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics))
*reply = NewLogsRes(api.xeth().AllLogs(opts))
case "eth_getWork": case "eth_getWork":
api.xeth().SetMining(true) api.xeth().SetMining(true)
*reply = api.xeth().RemoteMining().GetWork() *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 { if err := json.Unmarshal(req.Params, &args); err != nil {
return err 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": case "db_putString":
args := new(DbArgs) args := new(DbArgs)
if err := json.Unmarshal(req.Params, &args); err != nil { if err := json.Unmarshal(req.Params, &args); err != nil {
@ -433,7 +403,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return err return err
} }
opts := new(xeth.Options) opts := new(xeth.Options)
opts.From = args.From // opts.From = args.From
opts.To = args.To opts.To = args.To
opts.Topics = args.Topics opts.Topics = args.Topics
id := api.xeth().NewWhisperFilter(opts) 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) rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil 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 package rpc
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "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 // Parse as integer
num, ok := raw.(float64) num, ok := raw.(float64)
if ok { if ok {
@ -21,7 +32,7 @@ func blockHeight(raw interface{}, number *int64) (err error) {
// Parse as string/hexstring // Parse as string/hexstring
str, ok := raw.(string) str, ok := raw.(string)
if !ok { if !ok {
return NewDecodeParamError("BlockNumber is not a string") return NewInvalidTypeError("", "not a number or string")
} }
switch str { switch str {
@ -36,26 +47,55 @@ func blockHeight(raw interface{}, number *int64) (err error) {
return nil return nil
} }
func toNumber(v interface{}) (int64, error) { func numString(raw interface{}, number *int64) error {
var str string // Parse as integer
if v != nil { num, ok := raw.(float64)
var ok bool if ok {
str, ok = v.(string) *number = int64(num)
if !ok { return nil
return 0, errors.New("is not a string or undefined")
}
} else {
str = "latest"
} }
switch str { // Parse as string/hexstring
case "latest": str, ok := raw.(string)
return -1, nil if !ok {
default: return NewInvalidTypeError("", "not a number or string")
return int64(common.Big(v.(string)).Int64()), nil
} }
*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 { type GetBlockByHashArgs struct {
BlockHash string BlockHash string
IncludeTxs bool IncludeTxs bool
@ -63,8 +103,8 @@ type GetBlockByHashArgs struct {
func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) { func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} 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()) return NewDecodeParamError(err.Error())
} }
@ -74,7 +114,7 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
argstr, ok := obj[0].(string) argstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("BlockHash not a string") return NewInvalidTypeError("blockHash", "not a string")
} }
args.BlockHash = argstr args.BlockHash = argstr
@ -92,8 +132,7 @@ type GetBlockByNumberArgs struct {
func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) { func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -103,8 +142,10 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
if v, ok := obj[0].(float64); ok { if v, ok := obj[0].(float64); ok {
args.BlockNumber = int64(v) args.BlockNumber = int64(v)
} else if v, ok := obj[0].(string); ok {
args.BlockNumber = common.Big(v).Int64()
} else { } else {
args.BlockNumber = common.Big(obj[0].(string)).Int64() return NewInvalidTypeError("blockNumber", "not a number or string")
} }
if len(obj) > 1 { if len(obj) > 1 {
@ -127,7 +168,14 @@ type NewTxArgs struct {
func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) { func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
var obj []json.RawMessage 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 // Decode byte slice to array of RawMessages
if err := json.Unmarshal(b, &obj); err != nil { if err := json.Unmarshal(b, &obj); err != nil {
@ -144,22 +192,45 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
// var ok bool if len(ext.From) == 0 {
return NewValidationError("from", "is required")
}
args.From = ext.From args.From = ext.From
args.To = ext.To 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 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 // Check for optional BlockNumber param
if len(obj) > 1 { if len(obj) > 1 {
var raw interface{} if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
if err = json.Unmarshal(obj[1], &raw); err != nil {
return NewDecodeParamError(err.Error())
}
if err := blockHeight(raw, &args.BlockNumber); err != nil {
return err return err
} }
} }
@ -167,13 +238,6 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *NewTxArgs) requirements() error {
if len(args.From) == 0 {
return NewValidationError("From", "Is required")
}
return nil
}
type GetStorageArgs struct { type GetStorageArgs struct {
Address string Address string
BlockNumber int64 BlockNumber int64
@ -191,7 +255,7 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string) addstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Address is not a string") return NewInvalidTypeError("address", "not a string")
} }
args.Address = addstr args.Address = addstr
@ -204,13 +268,6 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *GetStorageArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetStorageAtArgs struct { type GetStorageAtArgs struct {
Address string Address string
Key string Key string
@ -229,13 +286,13 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string) addstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Address is not a string") return NewInvalidTypeError("address", "not a string")
} }
args.Address = addstr args.Address = addstr
keystr, ok := obj[1].(string) keystr, ok := obj[1].(string)
if !ok { if !ok {
return NewDecodeParamError("Key is not a string") return NewInvalidTypeError("key", "not a string")
} }
args.Key = keystr args.Key = keystr
@ -248,17 +305,6 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
return nil 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 { type GetTxCountArgs struct {
Address string Address string
BlockNumber int64 BlockNumber int64
@ -276,7 +322,7 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string) addstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Address is not a string") return NewInvalidTypeError("address", "not a string")
} }
args.Address = addstr args.Address = addstr
@ -289,13 +335,6 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *GetTxCountArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetBalanceArgs struct { type GetBalanceArgs struct {
Address string Address string
BlockNumber int64 BlockNumber int64
@ -313,7 +352,7 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string) addstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Address is not a string") return NewInvalidTypeError("address", "not a string")
} }
args.Address = addstr args.Address = addstr
@ -326,13 +365,6 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *GetBalanceArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type GetDataArgs struct { type GetDataArgs struct {
Address string Address string
BlockNumber int64 BlockNumber int64
@ -350,7 +382,7 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
addstr, ok := obj[0].(string) addstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Address is not a string") return NewInvalidTypeError("address", "not a string")
} }
args.Address = addstr args.Address = addstr
@ -363,13 +395,6 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *GetDataArgs) requirements() error {
if len(args.Address) == 0 {
return NewValidationError("Address", "cannot be blank")
}
return nil
}
type BlockNumIndexArgs struct { type BlockNumIndexArgs struct {
BlockNumber int64 BlockNumber int64
Index int64 Index int64
@ -377,8 +402,7 @@ type BlockNumIndexArgs struct {
func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) { func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -386,16 +410,14 @@ func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1) return NewInsufficientParamsError(len(obj), 1)
} }
arg0, ok := obj[0].(string) if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
if !ok { return err
return NewDecodeParamError("BlockNumber is not string")
} }
args.BlockNumber = common.Big(arg0).Int64()
if len(obj) > 1 { if len(obj) > 1 {
arg1, ok := obj[1].(string) arg1, ok := obj[1].(string)
if !ok { if !ok {
return NewDecodeParamError("Index not a string") return NewInvalidTypeError("index", "not a string")
} }
args.Index = common.Big(arg1).Int64() args.Index = common.Big(arg1).Int64()
} }
@ -410,8 +432,7 @@ type HashIndexArgs struct {
func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) { func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -421,14 +442,14 @@ func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
arg0, ok := obj[0].(string) arg0, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Hash not a string") return NewInvalidTypeError("hash", "not a string")
} }
args.Hash = arg0 args.Hash = arg0
if len(obj) > 1 { if len(obj) > 1 {
arg1, ok := obj[1].(string) arg1, ok := obj[1].(string)
if !ok { if !ok {
return NewDecodeParamError("Index not a string") return NewInvalidTypeError("index", "not a string")
} }
args.Index = common.Big(arg1).Int64() args.Index = common.Big(arg1).Int64()
} }
@ -442,24 +463,27 @@ type Sha3Args struct {
func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) { func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
if len(obj) < 1 { if len(obj) < 1 {
return NewInsufficientParamsError(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 return nil
} }
type BlockFilterArgs struct { type BlockFilterArgs struct {
Earliest int64 Earliest int64
Latest int64 Latest int64
Address interface{} Address []string
Topics []interface{} Topics [][]string
Skip int Skip int
Max int Max int
} }
@ -468,10 +492,10 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct { var obj []struct {
FromBlock interface{} `json:"fromBlock"` FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"` ToBlock interface{} `json:"toBlock"`
Limit string `json:"limit"` Limit interface{} `json:"limit"`
Offset string `json:"offset"` Offset interface{} `json:"offset"`
Address string `json:"address"` Address interface{} `json:"address"`
Topics []interface{} `json:"topics"` Topics interface{} `json:"topics"`
} }
if err = json.Unmarshal(b, &obj); err != nil { 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) return NewInsufficientParamsError(len(obj), 1)
} }
args.Earliest, err = toNumber(obj[0].ToBlock) // args.Earliest, err = toNumber(obj[0].ToBlock)
if err != nil { // if err != nil {
return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err)) // 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 { // if -2 or other "silly" number, use latest
return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err)) if num < 0 {
args.Earliest = -1 //latest block
} else {
args.Earliest = num
} }
args.Max = int(common.Big(obj[0].Limit).Int64()) // if blank than latest
args.Skip = int(common.Big(obj[0].Offset).Int64()) if obj[0].ToBlock == nil {
args.Address = obj[0].Address num = -1
args.Topics = obj[0].Topics } 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 return nil
} }
@ -519,19 +637,19 @@ func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
var ok bool var ok bool
if objstr, ok = obj[0].(string); !ok { if objstr, ok = obj[0].(string); !ok {
return NewDecodeParamError("Database is not a string") return NewInvalidTypeError("database", "not a string")
} }
args.Database = objstr args.Database = objstr
if objstr, ok = obj[1].(string); !ok { if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Key is not a string") return NewInvalidTypeError("key", "not a string")
} }
args.Key = objstr args.Key = objstr
if len(obj) > 2 { if len(obj) > 2 {
objstr, ok = obj[2].(string) objstr, ok = obj[2].(string)
if !ok { if !ok {
return NewDecodeParamError("Value is not a string") return NewInvalidTypeError("value", "not a string")
} }
args.Value = []byte(objstr) args.Value = []byte(objstr)
@ -570,19 +688,19 @@ func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
var ok bool var ok bool
if objstr, ok = obj[0].(string); !ok { if objstr, ok = obj[0].(string); !ok {
return NewDecodeParamError("Database is not a string") return NewInvalidTypeError("database", "not a string")
} }
args.Database = objstr args.Database = objstr
if objstr, ok = obj[1].(string); !ok { if objstr, ok = obj[1].(string); !ok {
return NewDecodeParamError("Key is not a string") return NewInvalidTypeError("key", "not a string")
} }
args.Key = objstr args.Key = objstr
if len(obj) > 2 { if len(obj) > 2 {
objstr, ok = obj[2].(string) objstr, ok = obj[2].(string)
if !ok { if !ok {
return NewDecodeParamError("Value is not a string") return NewInvalidTypeError("value", "not a string")
} }
args.Value = common.FromHex(objstr) args.Value = common.FromHex(objstr)
@ -616,8 +734,8 @@ func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
To string To string
From string From string
Topics []string Topics []string
Priority string Priority interface{}
Ttl string Ttl interface{}
} }
if err = json.Unmarshal(b, &obj); err != nil { 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.To = obj[0].To
args.From = obj[0].From args.From = obj[0].From
args.Topics = obj[0].Topics 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 return nil
} }
@ -643,14 +770,18 @@ type CompileArgs struct {
func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) { func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
if len(obj) > 0 { if len(obj) < 1 {
args.Source = obj[0].(string) return NewInsufficientParamsError(len(obj), 1)
} }
argstr, ok := obj[0].(string)
if !ok {
return NewInvalidTypeError("arg0", "is not a string")
}
args.Source = argstr
return nil return nil
} }
@ -661,8 +792,7 @@ type FilterStringArgs struct {
func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) { func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{} var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -673,20 +803,15 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
var argstr string var argstr string
argstr, ok := obj[0].(string) argstr, ok := obj[0].(string)
if !ok { if !ok {
return NewDecodeParamError("Filter is not a string") return NewInvalidTypeError("filter", "not a string")
} }
args.Word = argstr switch argstr {
return nil
}
func (args *FilterStringArgs) requirements() error {
switch args.Word {
case "latest", "pending": case "latest", "pending":
break break
default: default:
return NewValidationError("Word", "Must be `latest` or `pending`") return NewValidationError("Word", "Must be `latest` or `pending`")
} }
args.Word = argstr
return nil return nil
} }
@ -695,9 +820,8 @@ type FilterIdArgs struct {
} }
func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) { func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
var obj []string var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -705,7 +829,11 @@ func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1) 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 return nil
} }
@ -715,9 +843,8 @@ type WhisperIdentityArgs struct {
} }
func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) { func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
var obj []string var obj []interface{}
r := bytes.NewReader(b) if err := json.Unmarshal(b, &obj); err != nil {
if err := json.NewDecoder(r).Decode(&obj); err != nil {
return NewDecodeParamError(err.Error()) return NewDecodeParamError(err.Error())
} }
@ -725,7 +852,14 @@ func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1) 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 return nil
} }
@ -738,9 +872,8 @@ type WhisperFilterArgs struct {
func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct { var obj []struct {
To string To interface{}
From string Topics []interface{}
Topics []string
} }
if err = json.Unmarshal(b, &obj); err != nil { 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) return NewInsufficientParamsError(len(obj), 1)
} }
args.To = obj[0].To var argstr string
args.From = obj[0].From argstr, ok := obj[0].To.(string)
args.Topics = obj[0].Topics 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 return nil
} }
type SubmitWorkArgs struct { type SubmitWorkArgs struct {
Nonce uint64 Nonce uint64
Header common.Hash Header string
Digest common.Hash Digest string
} }
func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) { func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
@ -777,21 +923,21 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
var objstr string var objstr string
var ok bool var ok bool
if objstr, ok = obj[0].(string); !ok { 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() args.Nonce = common.String2Big(objstr).Uint64()
if objstr, ok = obj[1].(string); !ok { 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 { 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 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: case *NotImplementedError:
jsonerr := &RpcErrorObject{-32601, reserr.Error()} jsonerr := &RpcErrorObject{-32601, reserr.Error()}
response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr} response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
case *DecodeParamError, *InsufficientParamsError, *ValidationError: case *DecodeParamError, *InsufficientParamsError, *ValidationError, *InvalidTypeError:
jsonerr := &RpcErrorObject{-32602, reserr.Error()} jsonerr := &RpcErrorObject{-32602, reserr.Error()}
response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr} response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
default: default:

View file

@ -21,6 +21,22 @@ import (
"fmt" "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 { type InsufficientParamsError struct {
have int have int
want int want int

View file

@ -4,6 +4,15 @@ import (
"testing" "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) { func TestInsufficientParamsError(t *testing.T) {
err := NewInsufficientParamsError(0, 1) err := NewInsufficientParamsError(0, 1)
expected := "insufficient params, want 1 have 0" 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.Difficulty = common.ToHex(b.Difficulty.Bytes())
ext.TotalDifficulty = common.ToHex(b.TotalDifficulty.Bytes()) ext.TotalDifficulty = common.ToHex(b.TotalDifficulty.Bytes())
ext.Size = common.ToHex(b.Size.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.GasLimit = common.ToHex(b.GasLimit.Bytes())
// ext.MinGasPrice = common.ToHex(big.NewInt(b.MinGasPrice).Bytes()) // ext.MinGasPrice = common.ToHex(big.NewInt(b.MinGasPrice).Bytes())
ext.GasUsed = common.ToHex(b.GasUsed.Bytes()) ext.GasUsed = common.ToHex(b.GasUsed.Bytes())
@ -111,7 +111,7 @@ func NewBlockRes(block *types.Block) *BlockRes {
res.Difficulty = block.Difficulty() res.Difficulty = block.Difficulty()
res.TotalDifficulty = block.Td res.TotalDifficulty = block.Td
res.Size = big.NewInt(int64(block.Size())) res.Size = big.NewInt(int64(block.Size()))
// res.ExtraData = res.ExtraData = []byte(block.Header().Extra)
res.GasLimit = block.GasLimit() res.GasLimit = block.GasLimit()
// res.MinGasPrice = // res.MinGasPrice =
res.GasUsed = block.GasUsed() res.GasUsed = block.GasUsed()
@ -243,8 +243,8 @@ func (l *LogRes) MarshalJSON() ([]byte, error) {
} }
ext.Address = l.Address.Hex() ext.Address = l.Address.Hex()
ext.Data = common.Bytes2Hex(l.Data) ext.Data = common.ToHex(l.Data)
ext.Number = common.Bytes2Hex(big.NewInt(int64(l.Number)).Bytes()) ext.Number = common.ToHex(big.NewInt(int64(l.Number)).Bytes())
ext.Topics = make([]string, len(l.Topics)) ext.Topics = make([]string, len(l.Topics))
for i, v := range l.Topics { for i, v := range l.Topics {
ext.Topics[i] = v.Hex() ext.Topics[i] = v.Hex()

View file

@ -40,7 +40,7 @@ var (
extensions = []string{".go", ".js", ".qml"} extensions = []string{".go", ".js", ".qml"}
// paths with any of these prefixes will be skipped // 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. // paths with this prefix are licensed as GPL. all other files are LGPL.
gplPrefixes = []string{"cmd/"} gplPrefixes = []string{"cmd/"}
@ -190,7 +190,7 @@ func fileInfo(file string) (*info, error) {
break 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) { err := doLines(cmd, func(line string) {
sep := strings.IndexByte(line, '|') sep := strings.IndexByte(line, '|')
year, name := line[:4], line[sep+2:] year, name := line[:4], line[sep+2:]

View file

@ -110,6 +110,24 @@ func (self *XEth) stop() {
close(self.quit) 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) DefaultGas() *big.Int { return defaultGas }
func (self *XEth) DefaultGasPrice() *big.Int { return defaultGasPrice } func (self *XEth) DefaultGasPrice() *big.Int { return defaultGasPrice }
@ -228,15 +246,15 @@ func (self *XEth) IsMining() bool {
} }
func (self *XEth) EthVersion() string { func (self *XEth) EthVersion() string {
return string(self.backend.EthVersion()) return fmt.Sprintf("%d", self.backend.EthVersion())
} }
func (self *XEth) NetworkVersion() string { func (self *XEth) NetworkVersion() string {
return string(self.backend.NetVersion()) return fmt.Sprintf("%d", self.backend.NetVersion())
} }
func (self *XEth) WhisperVersion() string { func (self *XEth) WhisperVersion() string {
return string(self.backend.ShhVersion()) return fmt.Sprintf("%d", self.backend.ShhVersion())
} }
func (self *XEth) ClientVersion() string { func (self *XEth) ClientVersion() string {
@ -301,10 +319,15 @@ func (self *XEth) SecretToAddress(key string) string {
return common.ToHex(pair.Address()) 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 var id int
filter := core.NewFilter(self.backend) 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) { filter.LogsCallback = func(logs state.Logs) {
self.logMut.Lock() self.logMut.Lock()
defer self.logMut.Unlock() defer self.logMut.Unlock()
@ -380,9 +403,14 @@ func (self *XEth) Logs(id int) state.Logs {
return nil 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 := 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() return filter.Find()
} }