Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
38c7c589
Commit
38c7c589
authored
Mar 21, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'rpcfrontier' into develop
parents
9edb9a21
28e19712
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
630 additions
and
729 deletions
+630
-729
filter.go
core/filter.go
+1
-1
eth_filter.go
event/filter/eth_filter.go
+3
-1
api.go
rpc/api.go
+177
-561
api_test.go
rpc/api_test.go
+32
-32
args.go
rpc/args.go
+18
-8
args_test.go
rpc/args_test.go
+16
-16
http.go
rpc/http.go
+8
-8
messages_test.go
rpc/messages_test.go
+41
-0
responses.go
rpc/responses.go
+26
-0
util.go
rpc/util.go
+0
-86
xeth.go
xeth/xeth.go
+308
-16
No files found.
core/filter.go
View file @
38c7c589
...
...
@@ -46,7 +46,7 @@ func NewFilter(eth Backend) *Filter {
// 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
)
{
func
(
self
*
Filter
)
SetOptions
(
options
*
FilterOptions
)
{
self
.
earliest
=
options
.
Earliest
self
.
latest
=
options
.
Latest
self
.
skip
=
options
.
Skip
...
...
event/filter/eth_filter.go
View file @
38c7c589
...
...
@@ -48,7 +48,9 @@ func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
func
(
self
*
FilterManager
)
UninstallFilter
(
id
int
)
{
self
.
filterMu
.
Lock
()
defer
self
.
filterMu
.
Unlock
()
delete
(
self
.
filters
,
id
)
if
_
,
ok
:=
self
.
filters
[
id
];
ok
{
delete
(
self
.
filters
,
id
)
}
}
// GetFilter retrieves a filter installed using InstallFilter.
...
...
rpc/api.go
View file @
38c7c589
...
...
@@ -2,494 +2,49 @@ package rpc
import
(
"encoding/json"
"fmt"
"math/big"
"path"
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
)
var
(
defaultGasPrice
=
big
.
NewInt
(
150000000000
)
defaultGas
=
big
.
NewInt
(
500000
)
filterTickerTime
=
5
*
time
.
Minute
)
type
EthereumApi
struct
{
eth
*
xeth
.
XEth
xethMu
sync
.
RWMutex
mux
*
event
.
TypeMux
quit
chan
struct
{}
filterManager
*
filter
.
FilterManager
logMut
sync
.
RWMutex
logs
map
[
int
]
*
logFilter
messagesMut
sync
.
RWMutex
messages
map
[
int
]
*
whisperFilter
// Register keeps a list of accounts and transaction data
regmut
sync
.
Mutex
register
map
[
string
][]
*
NewTxArgs
db
common
.
Database
db
common
.
Database
}
func
NewEthereumApi
(
eth
*
xeth
.
XEth
,
dataDir
string
)
*
EthereumApi
{
// What about when dataDir is empty?
db
,
_
:=
ethdb
.
NewLDBDatabase
(
path
.
Join
(
dataDir
,
"dapps"
))
api
:=
&
EthereumApi
{
eth
:
eth
,
mux
:
eth
.
Backend
()
.
EventMux
(),
quit
:
make
(
chan
struct
{}),
filterManager
:
filter
.
NewFilterManager
(
eth
.
Backend
()
.
EventMux
()),
logs
:
make
(
map
[
int
]
*
logFilter
),
messages
:
make
(
map
[
int
]
*
whisperFilter
),
db
:
db
,
eth
:
eth
,
db
:
db
,
}
go
api
.
filterManager
.
Start
()
go
api
.
start
()
return
api
}
func
(
self
*
EthereumApi
)
xethWithStateNum
(
num
int64
)
*
xeth
.
XEth
{
chain
:=
self
.
xeth
()
.
Backend
()
.
ChainManager
()
var
block
*
types
.
Block
if
num
<
0
{
num
=
chain
.
CurrentBlock
()
.
Number
()
.
Int64
()
+
num
+
1
}
block
=
chain
.
GetBlockByNumber
(
uint64
(
num
))
var
st
*
state
.
StateDB
if
block
!=
nil
{
st
=
state
.
New
(
block
.
Root
(),
self
.
xeth
()
.
Backend
()
.
StateDb
())
}
else
{
st
=
chain
.
State
()
}
return
self
.
xeth
()
.
WithState
(
st
)
}
func
(
self
*
EthereumApi
)
getStateWithNum
(
num
int64
)
*
xeth
.
State
{
return
self
.
xethWithStateNum
(
num
)
.
State
()
}
func
(
self
*
EthereumApi
)
start
()
{
timer
:=
time
.
NewTicker
(
2
*
time
.
Second
)
done
:
for
{
select
{
case
<-
timer
.
C
:
self
.
logMut
.
Lock
()
self
.
messagesMut
.
Lock
()
for
id
,
filter
:=
range
self
.
logs
{
if
time
.
Since
(
filter
.
timeout
)
>
filterTickerTime
{
self
.
filterManager
.
UninstallFilter
(
id
)
delete
(
self
.
logs
,
id
)
}
}
for
id
,
filter
:=
range
self
.
messages
{
if
time
.
Since
(
filter
.
timeout
)
>
filterTickerTime
{
self
.
xeth
()
.
Whisper
()
.
Unwatch
(
id
)
delete
(
self
.
messages
,
id
)
}
}
self
.
messagesMut
.
Unlock
()
self
.
logMut
.
Unlock
()
case
<-
self
.
quit
:
break
done
}
}
}
func
(
self
*
EthereumApi
)
stop
()
{
close
(
self
.
quit
)
}
// func (self *EthereumApi) Register(args string, reply *interface{}) error {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// if _, ok := self.register[args]; ok {
// self.register[args] = nil // register with empty
// }
// return nil
// }
// func (self *EthereumApi) Unregister(args string, reply *interface{}) error {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// delete(self.register, args)
// return nil
// }
// func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// txs := self.register[args]
// self.register[args] = nil
// *reply = txs
// return nil
// }
func
(
self
*
EthereumApi
)
NewFilter
(
args
*
FilterOptions
,
reply
*
interface
{})
error
{
var
id
int
filter
:=
core
.
NewFilter
(
self
.
xeth
()
.
Backend
())
filter
.
SetOptions
(
toFilterOptions
(
args
))
filter
.
LogsCallback
=
func
(
logs
state
.
Logs
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
self
.
logs
[
id
]
.
add
(
logs
...
)
}
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
())
return
nil
}
func
(
self
*
EthereumApi
)
UninstallFilter
(
id
int
,
reply
*
interface
{})
error
{
if
_
,
ok
:=
self
.
logs
[
id
];
ok
{
delete
(
self
.
logs
,
id
)
}
self
.
filterManager
.
UninstallFilter
(
id
)
*
reply
=
true
return
nil
}
func
(
self
*
EthereumApi
)
NewFilterString
(
args
*
FilterStringArgs
,
reply
*
interface
{})
error
{
var
id
int
filter
:=
core
.
NewFilter
(
self
.
xeth
()
.
Backend
())
switch
args
.
Word
{
case
"pending"
:
filter
.
PendingCallback
=
func
(
tx
*
types
.
Transaction
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
self
.
logs
[
id
]
.
add
(
&
state
.
StateLog
{})
}
case
"latest"
:
filter
.
BlockCallback
=
func
(
block
*
types
.
Block
,
logs
state
.
Logs
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
for
_
,
log
:=
range
logs
{
self
.
logs
[
id
]
.
add
(
log
)
}
self
.
logs
[
id
]
.
add
(
&
state
.
StateLog
{})
}
default
:
return
NewValidationError
(
"Word"
,
"Must be `latest` or `pending`"
)
}
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
())
return
nil
}
func
(
self
*
EthereumApi
)
FilterChanged
(
id
int
,
reply
*
interface
{})
error
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
if
self
.
logs
[
id
]
!=
nil
{
*
reply
=
toLogs
(
self
.
logs
[
id
]
.
get
())
}
return
nil
}
func
(
self
*
EthereumApi
)
Logs
(
id
int
,
reply
*
interface
{})
error
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
filter
:=
self
.
filterManager
.
GetFilter
(
id
)
if
filter
!=
nil
{
*
reply
=
toLogs
(
filter
.
Find
())
}
return
nil
}
func
(
self
*
EthereumApi
)
AllLogs
(
args
*
FilterOptions
,
reply
*
interface
{})
error
{
filter
:=
core
.
NewFilter
(
self
.
xeth
()
.
Backend
())
filter
.
SetOptions
(
toFilterOptions
(
args
))
*
reply
=
toLogs
(
filter
.
Find
())
return
nil
}
func
(
p
*
EthereumApi
)
Transact
(
args
*
NewTxArgs
,
reply
*
interface
{})
(
err
error
)
{
// TODO if no_private_key then
//if _, exists := p.register[args.From]; exists {
// p.register[args.From] = append(p.register[args.From], args)
//} else {
/*
account := accounts.Get(common.FromHex(args.From))
if account != nil {
if account.Unlocked() {
if !unlockAccount(account) {
return
}
}
result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data))
if len(result) > 0 {
*reply = common.ToHex(result)
}
} else if _, exists := p.register[args.From]; exists {
p.register[ags.From] = append(p.register[args.From], args)
}
*/
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
// TODO: align default values to have the same type, e.g. not depend on
// common.Value conversions later on
if
args
.
Gas
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
args
.
Gas
=
defaultGas
}
if
args
.
GasPrice
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
args
.
GasPrice
=
defaultGasPrice
}
*
reply
,
err
=
p
.
xeth
()
.
Transact
(
args
.
From
,
args
.
To
,
args
.
Value
.
String
(),
args
.
Gas
.
String
(),
args
.
GasPrice
.
String
(),
args
.
Data
)
if
err
!=
nil
{
fmt
.
Println
(
"err:"
,
err
)
return
err
}
return
nil
}
func
(
p
*
EthereumApi
)
Call
(
args
*
NewTxArgs
,
reply
*
interface
{})
error
{
result
,
err
:=
p
.
xethWithStateNum
(
args
.
BlockNumber
)
.
Call
(
args
.
From
,
args
.
To
,
args
.
Value
.
String
(),
args
.
Gas
.
String
(),
args
.
GasPrice
.
String
(),
args
.
Data
)
if
err
!=
nil
{
return
err
}
*
reply
=
result
return
nil
}
func
(
p
*
EthereumApi
)
GetBalance
(
args
*
GetBalanceArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
state
:=
p
.
getStateWithNum
(
args
.
BlockNumber
)
.
SafeGet
(
args
.
Address
)
*
reply
=
common
.
ToHex
(
state
.
Balance
()
.
Bytes
())
return
nil
}
func
(
p
*
EthereumApi
)
GetStorage
(
args
*
GetStorageArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
*
reply
=
p
.
getStateWithNum
(
args
.
BlockNumber
)
.
SafeGet
(
args
.
Address
)
.
Storage
()
return
nil
}
func
(
p
*
EthereumApi
)
GetStorageAt
(
args
*
GetStorageAtArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
state
:=
p
.
getStateWithNum
(
args
.
BlockNumber
)
.
SafeGet
(
args
.
Address
)
value
:=
state
.
StorageString
(
args
.
Key
)
var
hx
string
if
strings
.
Index
(
args
.
Key
,
"0x"
)
==
0
{
hx
=
string
([]
byte
(
args
.
Key
)[
2
:
])
}
else
{
// Convert the incoming string (which is a bigint) into hex
i
,
_
:=
new
(
big
.
Int
)
.
SetString
(
args
.
Key
,
10
)
hx
=
common
.
Bytes2Hex
(
i
.
Bytes
())
}
rpclogger
.
Debugf
(
"GetStateAt(%s, %s)
\n
"
,
args
.
Address
,
hx
)
*
reply
=
map
[
string
]
string
{
args
.
Key
:
value
.
Str
()}
return
nil
}
func
(
p
*
EthereumApi
)
GetTxCountAt
(
args
*
GetTxCountArgs
,
reply
*
interface
{})
error
{
err
:=
args
.
requirements
()
if
err
!=
nil
{
return
err
}
*
reply
=
p
.
xethWithStateNum
(
args
.
BlockNumber
)
.
TxCountAt
(
args
.
Address
)
return
nil
}
func
(
p
*
EthereumApi
)
GetData
(
args
*
GetDataArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
*
reply
=
p
.
xethWithStateNum
(
args
.
BlockNumber
)
.
CodeAt
(
args
.
Address
)
return
nil
}
func
(
p
*
EthereumApi
)
GetCompilers
(
reply
*
interface
{})
error
{
c
:=
[]
string
{
""
}
*
reply
=
c
return
nil
}
func
(
p
*
EthereumApi
)
DbPut
(
args
*
DbArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
p
.
db
.
Put
([]
byte
(
args
.
Database
+
args
.
Key
),
[]
byte
(
args
.
Value
))
*
reply
=
true
return
nil
}
func
(
p
*
EthereumApi
)
DbGet
(
args
*
DbArgs
,
reply
*
interface
{})
error
{
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
res
,
_
:=
p
.
db
.
Get
([]
byte
(
args
.
Database
+
args
.
Key
))
*
reply
=
string
(
res
)
return
nil
}
func
(
p
*
EthereumApi
)
NewWhisperIdentity
(
reply
*
interface
{})
error
{
*
reply
=
p
.
xeth
()
.
Whisper
()
.
NewIdentity
()
return
nil
}
// func (p *EthereumApi) RemoveWhisperIdentity(args *WhisperIdentityArgs, reply *interface{}) error {
// *reply = p.xeth().Whisper().RemoveIdentity(args.Identity)
// return nil
// }
func
(
p
*
EthereumApi
)
NewWhisperFilter
(
args
*
WhisperFilterArgs
,
reply
*
interface
{})
error
{
var
id
int
opts
:=
new
(
xeth
.
Options
)
opts
.
From
=
args
.
From
opts
.
To
=
args
.
To
opts
.
Topics
=
args
.
Topics
opts
.
Fn
=
func
(
msg
xeth
.
WhisperMessage
)
{
p
.
messagesMut
.
Lock
()
defer
p
.
messagesMut
.
Unlock
()
p
.
messages
[
id
]
.
add
(
msg
)
// = append(p.messages[id], msg)
}
id
=
p
.
xeth
()
.
Whisper
()
.
Watch
(
opts
)
p
.
messages
[
id
]
=
&
whisperFilter
{
timeout
:
time
.
Now
()}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
())
return
nil
}
func
(
p
*
EthereumApi
)
UninstallWhisperFilter
(
id
int
,
reply
*
interface
{})
error
{
delete
(
p
.
messages
,
id
)
*
reply
=
true
return
nil
}
func
(
self
*
EthereumApi
)
MessagesChanged
(
id
int
,
reply
*
interface
{})
error
{
self
.
messagesMut
.
Lock
()
defer
self
.
messagesMut
.
Unlock
()
if
self
.
messages
[
id
]
!=
nil
{
*
reply
=
self
.
messages
[
id
]
.
get
()
}
return
nil
}
func
(
p
*
EthereumApi
)
WhisperPost
(
args
*
WhisperMessageArgs
,
reply
*
interface
{})
error
{
err
:=
p
.
xeth
()
.
Whisper
()
.
Post
(
args
.
Payload
,
args
.
To
,
args
.
From
,
args
.
Topics
,
args
.
Priority
,
args
.
Ttl
)
if
err
!=
nil
{
return
err
}
*
reply
=
true
return
nil
}
func
(
p
*
EthereumApi
)
HasWhisperIdentity
(
args
string
,
reply
*
interface
{})
error
{
*
reply
=
p
.
xeth
()
.
Whisper
()
.
HasIdentity
(
args
)
return
nil
}
func
(
p
*
EthereumApi
)
WhisperMessages
(
id
int
,
reply
*
interface
{})
error
{
*
reply
=
p
.
xeth
()
.
Whisper
()
.
Messages
(
id
)
return
nil
}
func
(
p
*
EthereumApi
)
GetTransactionByHash
(
hash
string
,
reply
*
interface
{})
error
{
tx
:=
p
.
xeth
()
.
EthTransactionByHash
(
hash
)
if
tx
!=
nil
{
*
reply
=
NewTransactionRes
(
tx
)
}
return
nil
}
func
(
p
*
EthereumApi
)
GetBlockByHash
(
blockhash
string
,
includetx
bool
)
(
*
BlockRes
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByHash
(
blockhash
)
br
:=
NewBlockRes
(
block
)
br
.
fullTx
=
includetx
return
br
,
nil
}
func
(
p
*
EthereumApi
)
GetBlockByNumber
(
blocknum
int64
,
includetx
bool
)
(
*
BlockRes
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
blocknum
)
br
:=
NewBlockRes
(
block
)
br
.
fullTx
=
includetx
return
br
,
nil
}
func
(
p
*
EthereumApi
)
GetBlockTransactionCountByHash
(
blockhash
string
)
(
int64
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByHash
(
blockhash
)
br
:=
NewBlockRes
(
block
)
return
int64
(
len
(
br
.
Transactions
)),
nil
}
func
(
p
*
EthereumApi
)
GetBlockTransactionCountByNumber
(
blocknum
int64
)
(
int64
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
blocknum
)
br
:=
NewBlockRes
(
block
)
return
int64
(
len
(
br
.
Transactions
)),
nil
}
func
(
self
*
EthereumApi
)
xeth
()
*
xeth
.
XEth
{
self
.
xethMu
.
RLock
()
defer
self
.
xethMu
.
RUnlock
()
func
(
p
*
EthereumApi
)
GetBlockUncleCountByHash
(
blockhash
string
)
(
int64
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByHash
(
blockhash
)
br
:=
NewBlockRes
(
block
)
return
int64
(
len
(
br
.
Uncles
)),
nil
return
self
.
eth
}
func
(
p
*
EthereumApi
)
GetBlockUncleCountByNumber
(
blocknum
int64
)
(
int64
,
error
)
{
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
blocknum
)
br
:=
NewBlockRes
(
block
)
return
int64
(
len
(
br
.
Uncles
)),
nil
func
(
self
*
EthereumApi
)
xethAtStateNum
(
num
int64
)
*
xeth
.
XEth
{
return
self
.
xeth
()
.
AtStateNum
(
num
)
}
func
(
p
*
EthereumApi
)
GetRequestReply
(
req
*
RpcRequest
,
reply
*
interface
{})
error
{
// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger
.
Debugf
(
"%s %s"
,
req
.
Method
,
req
.
Params
)
switch
req
.
Method
{
case
"web3_sha3"
:
args
:=
new
(
Sha3Args
)
...
...
@@ -504,7 +59,8 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
case
"net_listening"
:
*
reply
=
p
.
xeth
()
.
IsListening
()
case
"net_peerCount"
:
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
p
.
xeth
()
.
PeerCount
()))
.
Bytes
())
v
:=
p
.
xeth
()
.
PeerCount
()
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
v
))
.
Bytes
())
case
"eth_coinbase"
:
// TODO handling of empty coinbase due to lack of accounts
res
:=
p
.
xeth
()
.
Coinbase
()
...
...
@@ -516,97 +72,131 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
case
"eth_mining"
:
*
reply
=
p
.
xeth
()
.
IsMining
()
case
"eth_gasPrice"
:
*
reply
=
common
.
ToHex
(
defaultGasPrice
.
Bytes
())
v
:=
p
.
xeth
()
.
DefaultGas
()
*
reply
=
common
.
ToHex
(
v
.
Bytes
())
case
"eth_accounts"
:
*
reply
=
p
.
xeth
()
.
Accounts
()
case
"eth_blockNumber"
:
*
reply
=
common
.
ToHex
(
p
.
xeth
()
.
Backend
()
.
ChainManager
()
.
CurrentBlock
()
.
Number
()
.
Bytes
())
v
:=
p
.
xeth
()
.
Backend
()
.
ChainManager
()
.
CurrentBlock
()
.
Number
()
*
reply
=
common
.
ToHex
(
v
.
Bytes
())
case
"eth_getBalance"
:
args
:=
new
(
GetBalanceArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
GetBalance
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
v
:=
p
.
xethAtStateNum
(
args
.
BlockNumber
)
.
State
()
.
SafeGet
(
args
.
Address
)
.
Balance
()
*
reply
=
common
.
ToHex
(
v
.
Bytes
())
case
"eth_getStorage"
,
"eth_storageAt"
:
args
:=
new
(
GetStorageArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
GetStorage
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
*
reply
=
p
.
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
}
return
p
.
GetStorageAt
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
state
:=
p
.
xethAtStateNum
(
args
.
BlockNumber
)
.
State
()
.
SafeGet
(
args
.
Address
)
value
:=
state
.
StorageString
(
args
.
Key
)
*
reply
=
common
.
Bytes2Hex
(
value
.
Bytes
())
case
"eth_getTransactionCount"
:
args
:=
new
(
GetTxCountArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
GetTxCountAt
(
args
,
reply
)
err
:=
args
.
requirements
()
if
err
!=
nil
{
return
err
}
*
reply
=
p
.
xethAtStateNum
(
args
.
BlockNumber
)
.
TxCountAt
(
args
.
Address
)
case
"eth_getBlockTransactionCountByHash"
:
args
:=
new
(
GetBlockByHashArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockTransactionCountByHash
(
args
.
BlockHash
)
if
err
!=
nil
{
return
err
}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
v
)
.
Bytes
())
block
:=
NewBlockRes
(
p
.
xeth
()
.
EthBlockByHash
(
args
.
BlockHash
))
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
len
(
block
.
Transactions
)))
.
Bytes
())
case
"eth_getBlockTransactionCountByNumber"
:
args
:=
new
(
GetBlockByNumberArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockTransactionCountByNumber
(
args
.
BlockNumber
)
if
err
!=
nil
{
return
err
}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
v
)
.
Bytes
())
block
:=
NewBlockRes
(
p
.
xeth
()
.
EthBlockByNumber
(
args
.
BlockNumber
))
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
len
(
block
.
Transactions
)))
.
Bytes
())
case
"eth_getUncleCountByBlockHash"
:
args
:=
new
(
GetBlockByHashArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockUncleCountByHash
(
args
.
BlockHash
)
if
err
!=
nil
{
return
err
}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
v
)
.
Bytes
())
block
:=
p
.
xeth
()
.
EthBlockByHash
(
args
.
BlockHash
)
br
:=
NewBlockRes
(
block
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
len
(
br
.
Uncles
)))
.
Bytes
())
case
"eth_getUncleCountByBlockNumber"
:
args
:=
new
(
GetBlockByNumberArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockUncleCountByNumber
(
args
.
BlockNumber
)
if
err
!=
nil
{
return
err
}
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
v
)
.
Bytes
())
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
args
.
BlockNumber
)
br
:=
NewBlockRes
(
block
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
len
(
br
.
Uncles
)))
.
Bytes
())
case
"eth_getData"
,
"eth_getCode"
:
args
:=
new
(
GetDataArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
GetData
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
*
reply
=
p
.
xethAtStateNum
(
args
.
BlockNumber
)
.
CodeAt
(
args
.
Address
)
case
"eth_sendTransaction"
,
"eth_transact"
:
args
:=
new
(
NewTxArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
Transact
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
xeth
()
.
Transact
(
args
.
From
,
args
.
To
,
args
.
Value
.
String
(),
args
.
Gas
.
String
(),
args
.
GasPrice
.
String
(),
args
.
Data
)
if
err
!=
nil
{
return
err
}
*
reply
=
v
case
"eth_call"
:
args
:=
new
(
NewTxArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
Call
(
args
,
reply
)
v
,
err
:=
p
.
xethAtStateNum
(
args
.
BlockNumber
)
.
Call
(
args
.
From
,
args
.
To
,
args
.
Value
.
String
(),
args
.
Gas
.
String
(),
args
.
GasPrice
.
String
(),
args
.
Data
)
if
err
!=
nil
{
return
err
}
*
reply
=
v
case
"eth_flush"
:
return
NewNotImplementedError
(
req
.
Method
)
case
"eth_getBlockByHash"
:
...
...
@@ -615,52 +205,55 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return
err
}
v
,
err
:=
p
.
GetBlockByHash
(
args
.
BlockHash
,
args
.
Transactions
)
if
err
!=
nil
{
return
err
}
*
reply
=
v
block
:=
p
.
xeth
()
.
EthBlockByHash
(
args
.
BlockHash
)
br
:=
NewBlockRes
(
block
)
br
.
fullTx
=
args
.
IncludeTxs
*
reply
=
br
case
"eth_getBlockByNumber"
:
args
:=
new
(
GetBlockByNumberArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockByNumber
(
args
.
BlockNumber
,
args
.
Transactions
)
if
err
!=
nil
{
return
err
}
*
reply
=
v
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
args
.
BlockNumber
)
br
:=
NewBlockRes
(
block
)
br
.
fullTx
=
args
.
IncludeTxs
*
reply
=
br
case
"eth_getTransactionByHash"
:
// HashIndexArgs used, but only the "Hash" part we need.
args
:=
new
(
HashIndexArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
}
return
p
.
GetTransactionByHash
(
args
.
Hash
,
reply
)
tx
:=
p
.
xeth
()
.
EthTransactionByHash
(
args
.
Hash
)
if
tx
!=
nil
{
*
reply
=
NewTransactionRes
(
tx
)
}
case
"eth_getTransactionByBlockHashAndIndex"
:
args
:=
new
(
HashIndexArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockByHash
(
args
.
Hash
,
true
)
if
err
!=
nil
{
return
err
}
if
args
.
Index
>
int64
(
len
(
v
.
Transactions
))
||
args
.
Index
<
0
{
block
:=
p
.
xeth
()
.
EthBlockByHash
(
args
.
Hash
)
br
:=
NewBlockRes
(
block
)
br
.
fullTx
=
true
if
args
.
Index
>
int64
(
len
(
br
.
Transactions
))
||
args
.
Index
<
0
{
return
NewValidationError
(
"Index"
,
"does not exist"
)
}
*
reply
=
v
.
Transactions
[
args
.
Index
]
*
reply
=
br
.
Transactions
[
args
.
Index
]
case
"eth_getTransactionByBlockNumberAndIndex"
:
args
:=
new
(
BlockNumIndexArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
v
,
err
:=
p
.
GetBlockByNumber
(
args
.
BlockNumber
,
true
)
if
err
!=
nil
{
return
err
}
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
args
.
BlockNumber
)
v
:=
NewBlockRes
(
block
)
v
.
fullTx
=
true
if
args
.
Index
>
int64
(
len
(
v
.
Transactions
))
||
args
.
Index
<
0
{
return
NewValidationError
(
"Index"
,
"does not exist"
)
}
...
...
@@ -671,18 +264,15 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return
err
}
v
,
err
:=
p
.
GetBlockByHash
(
args
.
Hash
,
false
)
if
err
!=
nil
{
return
err
}
if
args
.
Index
>
int64
(
len
(
v
.
Uncles
))
||
args
.
Index
<
0
{
br
:=
NewBlockRes
(
p
.
xeth
()
.
EthBlockByHash
(
args
.
Hash
))
if
args
.
Index
>
int64
(
len
(
br
.
Uncles
))
||
args
.
Index
<
0
{
return
NewValidationError
(
"Index"
,
"does not exist"
)
}
uncle
,
err
:=
p
.
GetBlockByHash
(
common
.
ToHex
(
v
.
Uncles
[
args
.
Index
]),
false
)
if
err
!=
nil
{
return
err
}
uhash
:=
common
.
ToHex
(
br
.
Uncles
[
args
.
Index
])
uncle
:=
NewBlockRes
(
p
.
xeth
()
.
EthBlockByHash
(
uhash
))
*
reply
=
uncle
case
"eth_getUncleByBlockNumberAndIndex"
:
args
:=
new
(
BlockNumIndexArgs
)
...
...
@@ -690,59 +280,68 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return
err
}
v
,
err
:=
p
.
GetBlockByNumber
(
args
.
BlockNumber
,
true
)
if
err
!=
nil
{
return
err
}
block
:=
p
.
xeth
()
.
EthBlockByNumber
(
args
.
BlockNumber
)
v
:=
NewBlockRes
(
block
)
v
.
fullTx
=
true
if
args
.
Index
>
int64
(
len
(
v
.
Uncles
))
||
args
.
Index
<
0
{
return
NewValidationError
(
"Index"
,
"does not exist"
)
}
uncle
,
err
:=
p
.
GetBlockByHash
(
common
.
ToHex
(
v
.
Uncles
[
args
.
Index
]),
false
)
if
err
!=
nil
{
return
err
}
uhash
:=
common
.
ToHex
(
v
.
Uncles
[
args
.
Index
])
uncle
:=
NewBlockRes
(
p
.
xeth
()
.
EthBlockByHash
(
uhash
))
*
reply
=
uncle
case
"eth_getCompilers"
:
return
p
.
GetCompilers
(
reply
)
c
:=
[]
string
{
""
}
*
reply
=
c
case
"eth_compileSolidity"
,
"eth_compileLLL"
,
"eth_compileSerpent"
:
return
NewNotImplementedError
(
req
.
Method
)
case
"eth_newFilter"
:
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
NewFilter
(
args
,
reply
)
opts
:=
toFilterOptions
(
args
)
id
:=
p
.
xeth
()
.
RegisterFilter
(
opts
)
*
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
}
return
p
.
NewFilterString
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
id
:=
p
.
xeth
()
.
NewFilterString
(
args
.
Word
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
())
case
"eth_uninstallFilter"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
UninstallFilter
(
args
.
Id
,
reply
)
*
reply
=
p
.
xeth
()
.
UninstallFilter
(
args
.
Id
)
case
"eth_getFilterChanges"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
FilterChanged
(
args
.
Id
,
reply
)
*
reply
=
NewLogsRes
(
p
.
xeth
()
.
FilterChanged
(
args
.
Id
)
)
case
"eth_getFilterLogs"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
Logs
(
args
.
Id
,
reply
)
*
reply
=
NewLogsRes
(
p
.
xeth
()
.
Logs
(
args
.
Id
)
)
case
"eth_getLogs"
:
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
AllLogs
(
args
,
reply
)
opts
:=
toFilterOptions
(
args
)
*
reply
=
NewLogsRes
(
p
.
xeth
()
.
AllLogs
(
opts
))
case
"eth_getWork"
,
"eth_submitWork"
:
return
NewNotImplementedError
(
req
.
Method
)
case
"db_putString"
:
...
...
@@ -750,13 +349,25 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
DbPut
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
p
.
db
.
Put
([]
byte
(
args
.
Database
+
args
.
Key
),
[]
byte
(
args
.
Value
))
*
reply
=
true
case
"db_getString"
:
args
:=
new
(
DbArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
DbGet
(
args
,
reply
)
if
err
:=
args
.
requirements
();
err
!=
nil
{
return
err
}
res
,
_
:=
p
.
db
.
Get
([]
byte
(
args
.
Database
+
args
.
Key
))
*
reply
=
string
(
res
)
case
"db_putHex"
,
"db_getHex"
:
return
NewNotImplementedError
(
req
.
Method
)
case
"shh_post"
:
...
...
@@ -764,21 +375,27 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
WhisperPost
(
args
,
reply
)
err
:=
p
.
xeth
()
.
Whisper
()
.
Post
(
args
.
Payload
,
args
.
To
,
args
.
From
,
args
.
Topics
,
args
.
Priority
,
args
.
Ttl
)
if
err
!=
nil
{
return
err
}
*
reply
=
true
case
"shh_newIdentity"
:
return
p
.
NewWhisperIdentity
(
reply
)
*
reply
=
p
.
xeth
()
.
Whisper
()
.
NewIdentity
(
)
// case "shh_removeIdentity":
// args := new(WhisperIdentityArgs)
// if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
//
return p.RemoveWhisperIdentity(args, repl
y)
//
*reply = p.xeth().Whisper().RemoveIdentity(args.Identit
y)
case
"shh_hasIdentity"
:
args
:=
new
(
WhisperIdentityArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
HasWhisperIdentity
(
args
.
Identity
,
repl
y
)
*
reply
=
p
.
xeth
()
.
Whisper
()
.
HasIdentity
(
args
.
Identit
y
)
case
"shh_newGroup"
,
"shh_addToGroup"
:
return
NewNotImplementedError
(
req
.
Method
)
case
"shh_newFilter"
:
...
...
@@ -786,43 +403,49 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
NewWhisperFilter
(
args
,
reply
)
opts
:=
new
(
xeth
.
Options
)
opts
.
From
=
args
.
From
opts
.
To
=
args
.
To
opts
.
Topics
=
args
.
Topics
id
:=
p
.
xeth
()
.
NewWhisperFilter
(
opts
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
())
case
"shh_uninstallFilter"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
UninstallWhisperFilter
(
args
.
Id
,
reply
)
*
reply
=
p
.
xeth
()
.
UninstallWhisperFilter
(
args
.
Id
)
case
"shh_getFilterChanges"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
MessagesChanged
(
args
.
Id
,
reply
)
*
reply
=
p
.
xeth
()
.
MessagesChanged
(
args
.
Id
)
case
"shh_getMessages"
:
args
:=
new
(
FilterIdArgs
)
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
return
err
}
return
p
.
WhisperMessages
(
args
.
Id
,
reply
)
*
reply
=
p
.
xeth
()
.
Whisper
()
.
Messages
(
args
.
Id
)
// case "eth_register":
// args, err := req.ToRegisterArgs()
// if err != nil {
// // Placeholder for actual type
// args := new(HashIndexArgs)
// if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
//
return p.Register(args, reply
)
//
*reply = p.xeth().Register(args.Hash
)
// case "eth_unregister":
// args
, err := req.ToRegisterArgs(
)
// if err != nil {
// args
:= new(HashIndexArgs
)
// if err
:= json.Unmarshal(req.Params, &args); err
!= nil {
// return err
// }
//
return p.Unregister(args, reply
)
//
*reply = p.xeth().Unregister(args.Hash
)
// case "eth_watchTx":
// args
, err := req.ToWatchTxArgs(
)
// if err != nil {
// args
:= new(HashIndexArgs
)
// if err
:= json.Unmarshal(req.Params, &args); err
!= nil {
// return err
// }
//
return p.WatchTx(args, reply
)
//
*reply = p.xeth().PullWatchTx(args.Hash
)
default
:
return
NewNotImplementedError
(
req
.
Method
)
}
...
...
@@ -831,14 +454,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return
nil
}
func
(
self
*
EthereumApi
)
xeth
()
*
xeth
.
XEth
{
self
.
xethMu
.
RLock
()
defer
self
.
xethMu
.
RUnlock
()
return
self
.
eth
}
func
toFilterOptions
(
options
*
FilterOptions
)
core
.
FilterOptions
{
func
toFilterOptions
(
options
*
BlockFilterArgs
)
*
core
.
FilterOptions
{
var
opts
core
.
FilterOptions
// Convert optional address slice/string to byte slice
...
...
@@ -871,5 +487,5 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
}
opts
.
Topics
=
topics
return
opts
return
&
opts
}
rpc/api_test.go
View file @
38c7c589
...
...
@@ -2,9 +2,9 @@ package rpc
import
(
"encoding/json"
"sync"
//
"sync"
"testing"
"time"
//
"time"
)
func
TestWeb3Sha3
(
t
*
testing
.
T
)
{
...
...
@@ -24,33 +24,33 @@ func TestWeb3Sha3(t *testing.T) {
}
}
func
TestFilterClose
(
t
*
testing
.
T
)
{
t
.
Skip
()
api
:=
&
EthereumApi
{
logs
:
make
(
map
[
int
]
*
logFilter
),
messages
:
make
(
map
[
int
]
*
whisperFilter
),
quit
:
make
(
chan
struct
{}),
}
filterTickerTime
=
1
api
.
logs
[
0
]
=
&
logFilter
{}
api
.
messages
[
0
]
=
&
whisperFilter
{}
var
wg
sync
.
WaitGroup
wg
.
Add
(
1
)
go
api
.
start
()
go
func
()
{
select
{
case
<-
time
.
After
(
500
*
time
.
Millisecond
)
:
api
.
stop
()
wg
.
Done
()
}
}()
wg
.
Wait
()
if
len
(
api
.
logs
)
!=
0
{
t
.
Error
(
"expected logs to be empty"
)
}
if
len
(
api
.
messages
)
!=
0
{
t
.
Error
(
"expected messages to be empty"
)
}
}
//
func TestFilterClose(t *testing.T) {
//
t.Skip()
//
api := &EthereumApi{
//
logs: make(map[int]*logFilter),
//
messages: make(map[int]*whisperFilter),
//
quit: make(chan struct{}),
//
}
//
filterTickerTime = 1
//
api.logs[0] = &logFilter{}
//
api.messages[0] = &whisperFilter{}
//
var wg sync.WaitGroup
//
wg.Add(1)
//
go api.start()
//
go func() {
//
select {
//
case <-time.After(500 * time.Millisecond):
//
api.stop()
//
wg.Done()
//
}
//
}()
//
wg.Wait()
//
if len(api.logs) != 0 {
//
t.Error("expected logs to be empty")
//
}
//
if len(api.messages) != 0 {
//
t.Error("expected messages to be empty")
//
}
//
}
rpc/args.go
View file @
38c7c589
...
...
@@ -35,8 +35,8 @@ func blockAge(raw interface{}, number *int64) (err error) {
}
type
GetBlockByHashArgs
struct
{
BlockHash
string
Transaction
s
bool
BlockHash
string
IncludeTx
s
bool
}
func
(
args
*
GetBlockByHashArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
...
...
@@ -57,15 +57,15 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
args
.
BlockHash
=
argstr
if
len
(
obj
)
>
1
{
args
.
Transaction
s
=
obj
[
1
]
.
(
bool
)
args
.
IncludeTx
s
=
obj
[
1
]
.
(
bool
)
}
return
nil
}
type
GetBlockByNumberArgs
struct
{
BlockNumber
int64
Transactions
bool
BlockNumber
int64
IncludeTxs
bool
}
func
(
args
*
GetBlockByNumberArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
...
...
@@ -86,7 +86,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
}
if
len
(
obj
)
>
1
{
args
.
Transaction
s
=
obj
[
1
]
.
(
bool
)
args
.
IncludeTx
s
=
obj
[
1
]
.
(
bool
)
}
return
nil
...
...
@@ -433,7 +433,7 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
return
nil
}
type
FilterOption
s
struct
{
type
BlockFilterArg
s
struct
{
Earliest
int64
Latest
int64
Address
interface
{}
...
...
@@ -442,7 +442,7 @@ type FilterOptions struct {
Max
int
}
func
(
args
*
FilterOption
s
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
func
(
args
*
BlockFilterArg
s
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
var
obj
[]
struct
{
FromBlock
interface
{}
`json:"fromBlock"`
ToBlock
interface
{}
`json:"toBlock"`
...
...
@@ -609,6 +609,16 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
return
nil
}
func
(
args
*
FilterStringArgs
)
requirements
()
error
{
switch
args
.
Word
{
case
"latest"
,
"pending"
:
break
default
:
return
NewValidationError
(
"Word"
,
"Must be `latest` or `pending`"
)
}
return
nil
}
type
FilterIdArgs
struct
{
Id
int
}
...
...
rpc/args_test.go
View file @
38c7c589
...
...
@@ -82,7 +82,7 @@ func TestGetBlockByHashArgs(t *testing.T) {
input
:=
`["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true]`
expected
:=
new
(
GetBlockByHashArgs
)
expected
.
BlockHash
=
"0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
expected
.
Transaction
s
=
true
expected
.
IncludeTx
s
=
true
args
:=
new
(
GetBlockByHashArgs
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
...
...
@@ -93,8 +93,8 @@ func TestGetBlockByHashArgs(t *testing.T) {
t
.
Errorf
(
"BlockHash should be %v but is %v"
,
expected
.
BlockHash
,
args
.
BlockHash
)
}
if
args
.
Transactions
!=
expected
.
Transaction
s
{
t
.
Errorf
(
"
Transactions should be %v but is %v"
,
expected
.
Transactions
,
args
.
Transaction
s
)
if
args
.
IncludeTxs
!=
expected
.
IncludeTx
s
{
t
.
Errorf
(
"
IncludeTxs should be %v but is %v"
,
expected
.
IncludeTxs
,
args
.
IncludeTx
s
)
}
}
...
...
@@ -112,7 +112,7 @@ func TestGetBlockByNumberArgs(t *testing.T) {
input
:=
`["0x1b4", false]`
expected
:=
new
(
GetBlockByNumberArgs
)
expected
.
BlockNumber
=
436
expected
.
Transaction
s
=
false
expected
.
IncludeTx
s
=
false
args
:=
new
(
GetBlockByNumberArgs
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
...
...
@@ -123,8 +123,8 @@ func TestGetBlockByNumberArgs(t *testing.T) {
t
.
Errorf
(
"BlockHash should be %v but is %v"
,
expected
.
BlockNumber
,
args
.
BlockNumber
)
}
if
args
.
Transactions
!=
expected
.
Transaction
s
{
t
.
Errorf
(
"
Transactions should be %v but is %v"
,
expected
.
Transactions
,
args
.
Transaction
s
)
if
args
.
IncludeTxs
!=
expected
.
IncludeTx
s
{
t
.
Errorf
(
"
IncludeTxs should be %v but is %v"
,
expected
.
IncludeTxs
,
args
.
IncludeTx
s
)
}
}
...
...
@@ -388,7 +388,7 @@ func TestGetDataEmptyArgs(t *testing.T) {
}
}
func
Test
FilterOption
s
(
t
*
testing
.
T
)
{
func
Test
BlockFilterArg
s
(
t
*
testing
.
T
)
{
input
:=
`[{
"fromBlock": "0x1",
"toBlock": "0x2",
...
...
@@ -396,7 +396,7 @@ func TestFilterOptions(t *testing.T) {
"offset": "0x0",
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
"topics": ["0x12341234"]}]`
expected
:=
new
(
FilterOption
s
)
expected
:=
new
(
BlockFilterArg
s
)
expected
.
Earliest
=
1
expected
.
Latest
=
2
expected
.
Max
=
3
...
...
@@ -404,7 +404,7 @@ func TestFilterOptions(t *testing.T) {
expected
.
Address
=
"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
// expected.Topics = []string{"0x12341234"}
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
t
.
Error
(
err
)
}
...
...
@@ -434,16 +434,16 @@ func TestFilterOptions(t *testing.T) {
// }
}
func
Test
FilterOption
sWords
(
t
*
testing
.
T
)
{
func
Test
BlockFilterArg
sWords
(
t
*
testing
.
T
)
{
input
:=
`[{
"fromBlock": "latest",
"toBlock": "pending"
}]`
expected
:=
new
(
FilterOption
s
)
expected
:=
new
(
BlockFilterArg
s
)
expected
.
Earliest
=
0
expected
.
Latest
=
-
1
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
t
.
Error
(
err
)
}
...
...
@@ -457,13 +457,13 @@ func TestFilterOptionsWords(t *testing.T) {
}
}
func
Test
FilterOption
sNums
(
t
*
testing
.
T
)
{
func
Test
BlockFilterArg
sNums
(
t
*
testing
.
T
)
{
input
:=
`[{
"fromBlock": 2,
"toBlock": 3
}]`
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
)
switch
err
.
(
type
)
{
case
*
DecodeParamError
:
...
...
@@ -474,10 +474,10 @@ func TestFilterOptionsNums(t *testing.T) {
}
func
Test
FilterOption
sEmptyArgs
(
t
*
testing
.
T
)
{
func
Test
BlockFilterArg
sEmptyArgs
(
t
*
testing
.
T
)
{
input
:=
`[]`
args
:=
new
(
FilterOption
s
)
args
:=
new
(
BlockFilterArg
s
)
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
)
if
err
==
nil
{
t
.
Error
(
"Expected error but didn't get one"
)
...
...
rpc/http.go
View file @
38c7c589
...
...
@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/xeth"
)
var
rpc
httplogger
=
logger
.
NewLogger
(
"RPC-HTTP
"
)
var
rpc
logger
=
logger
.
NewLogger
(
"RPC
"
)
const
(
jsonrpcver
=
"2.0"
...
...
@@ -28,7 +28,7 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
// Limit request size to resist DoS
if
req
.
ContentLength
>
maxSizeReqLength
{
jsonerr
:=
&
RpcErrorObject
{
-
32700
,
"Request too large"
}
S
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
s
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
return
}
...
...
@@ -37,14 +37,14 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
body
,
err
:=
ioutil
.
ReadAll
(
req
.
Body
)
if
err
!=
nil
{
jsonerr
:=
&
RpcErrorObject
{
-
32700
,
"Could not read request body"
}
S
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
s
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
}
// Try to parse the request as a single
var
reqSingle
RpcRequest
if
err
:=
json
.
Unmarshal
(
body
,
&
reqSingle
);
err
==
nil
{
response
:=
RpcResponse
(
api
,
&
reqSingle
)
S
end
(
w
,
&
response
)
s
end
(
w
,
&
response
)
return
}
...
...
@@ -57,13 +57,13 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
response
:=
RpcResponse
(
api
,
&
request
)
resBatch
[
i
]
=
response
}
S
end
(
w
,
resBatch
)
s
end
(
w
,
resBatch
)
return
}
// Not a batch or single request, error
jsonerr
:=
&
RpcErrorObject
{
-
32600
,
"Could not decode request"
}
S
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
s
end
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
})
}
...
...
@@ -84,11 +84,11 @@ func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} {
response
=
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
request
.
Id
,
Error
:
jsonerr
}
}
rpc
http
logger
.
DebugDetailf
(
"Generated response: %T %s"
,
response
,
response
)
rpclogger
.
DebugDetailf
(
"Generated response: %T %s"
,
response
,
response
)
return
&
response
}
func
S
end
(
writer
io
.
Writer
,
v
interface
{})
(
n
int
,
err
error
)
{
func
s
end
(
writer
io
.
Writer
,
v
interface
{})
(
n
int
,
err
error
)
{
var
payload
[]
byte
payload
,
err
=
json
.
MarshalIndent
(
v
,
""
,
"
\t
"
)
if
err
!=
nil
{
...
...
rpc/messages_test.go
0 → 100644
View file @
38c7c589
package
rpc
import
(
"testing"
)
func
TestInsufficientParamsError
(
t
*
testing
.
T
)
{
err
:=
NewInsufficientParamsError
(
0
,
1
)
expected
:=
"insufficient params, want 1 have 0"
if
err
.
Error
()
!=
expected
{
t
.
Error
(
err
.
Error
())
}
}
func
TestNotImplementedError
(
t
*
testing
.
T
)
{
err
:=
NewNotImplementedError
(
"foo"
)
expected
:=
"foo method not implemented"
if
err
.
Error
()
!=
expected
{
t
.
Error
(
err
.
Error
())
}
}
func
TestDecodeParamError
(
t
*
testing
.
T
)
{
err
:=
NewDecodeParamError
(
"foo"
)
expected
:=
"could not decode, foo"
if
err
.
Error
()
!=
expected
{
t
.
Error
(
err
.
Error
())
}
}
func
TestValidationError
(
t
*
testing
.
T
)
{
err
:=
NewValidationError
(
"foo"
,
"should be `bar`"
)
expected
:=
"foo not valid, should be `bar`"
if
err
.
Error
()
!=
expected
{
t
.
Error
(
err
.
Error
())
}
}
rpc/responses.go
View file @
38c7c589
...
...
@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
)
type
BlockRes
struct
{
...
...
@@ -211,3 +212,28 @@ type FilterWhisperRes struct {
Payload
string
`json:"payload"`
WorkProved
string
`json:"workProved"`
}
type
LogRes
struct
{
Address
string
`json:"address"`
Topic
[]
string
`json:"topic"`
Data
string
`json:"data"`
Number
uint64
`json:"number"`
}
func
NewLogsRes
(
logs
state
.
Logs
)
(
ls
[]
LogRes
)
{
ls
=
make
([]
LogRes
,
len
(
logs
))
for
i
,
log
:=
range
logs
{
var
l
LogRes
l
.
Topic
=
make
([]
string
,
len
(
log
.
Topics
()))
l
.
Address
=
common
.
ToHex
(
log
.
Address
())
l
.
Data
=
common
.
ToHex
(
log
.
Data
())
l
.
Number
=
log
.
Number
()
for
j
,
topic
:=
range
log
.
Topics
()
{
l
.
Topic
[
j
]
=
common
.
ToHex
(
topic
)
}
ls
[
i
]
=
l
}
return
}
rpc/util.go
deleted
100644 → 0
View file @
9edb9a21
/*
This file is part of go-ethereum
go-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
go-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
package
rpc
import
(
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
)
var
rpclogger
=
logger
.
NewLogger
(
"RPC"
)
type
Log
struct
{
Address
string
`json:"address"`
Topic
[]
string
`json:"topic"`
Data
string
`json:"data"`
Number
uint64
`json:"number"`
}
func
toLogs
(
logs
state
.
Logs
)
(
ls
[]
Log
)
{
ls
=
make
([]
Log
,
len
(
logs
))
for
i
,
log
:=
range
logs
{
var
l
Log
l
.
Topic
=
make
([]
string
,
len
(
log
.
Topics
()))
l
.
Address
=
common
.
ToHex
(
log
.
Address
())
l
.
Data
=
common
.
ToHex
(
log
.
Data
())
l
.
Number
=
log
.
Number
()
for
j
,
topic
:=
range
log
.
Topics
()
{
l
.
Topic
[
j
]
=
common
.
ToHex
(
topic
)
}
ls
[
i
]
=
l
}
return
}
type
whisperFilter
struct
{
messages
[]
xeth
.
WhisperMessage
timeout
time
.
Time
id
int
}
func
(
w
*
whisperFilter
)
add
(
msgs
...
xeth
.
WhisperMessage
)
{
w
.
messages
=
append
(
w
.
messages
,
msgs
...
)
}
func
(
w
*
whisperFilter
)
get
()
[]
xeth
.
WhisperMessage
{
w
.
timeout
=
time
.
Now
()
tmp
:=
w
.
messages
w
.
messages
=
nil
return
tmp
}
type
logFilter
struct
{
logs
state
.
Logs
timeout
time
.
Time
id
int
}
func
(
l
*
logFilter
)
add
(
logs
...
state
.
Log
)
{
l
.
logs
=
append
(
l
.
logs
,
logs
...
)
}
func
(
l
*
logFilter
)
get
()
state
.
Logs
{
l
.
timeout
=
time
.
Now
()
tmp
:=
l
.
logs
l
.
logs
=
nil
return
tmp
}
xeth/xeth.go
View file @
38c7c589
...
...
@@ -6,6 +6,8 @@ import (
"encoding/json"
"fmt"
"math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -13,13 +15,19 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper"
)
var
pipelogger
=
logger
.
NewLogger
(
"XETH"
)
var
(
pipelogger
=
logger
.
NewLogger
(
"XETH"
)
filterTickerTime
=
5
*
time
.
Minute
defaultGasPrice
=
big
.
NewInt
(
10000000000000
)
//150000000000
defaultGas
=
big
.
NewInt
(
90000
)
//500000
)
// to resolve the import cycle
type
Backend
interface
{
...
...
@@ -62,6 +70,13 @@ type Frontend interface {
ConfirmTransaction
(
tx
*
types
.
Transaction
)
bool
}
// dummyFrontend is a non-interactive frontend that allows all
// transactions but cannot not unlock any keys.
type
dummyFrontend
struct
{}
func
(
dummyFrontend
)
UnlockAccount
([]
byte
)
bool
{
return
false
}
func
(
dummyFrontend
)
ConfirmTransaction
(
*
types
.
Transaction
)
bool
{
return
true
}
type
XEth
struct
{
eth
Backend
blockProcessor
*
core
.
BlockProcessor
...
...
@@ -71,14 +86,19 @@ type XEth struct {
whisper
*
Whisper
frontend
Frontend
}
// dummyFrontend is a non-interactive frontend that allows all
// transactions but cannot not unlock any keys.
type
dummyFrontend
struct
{}
quit
chan
struct
{}
filterManager
*
filter
.
FilterManager
func
(
dummyFrontend
)
UnlockAccount
([]
byte
)
bool
{
return
false
}
func
(
dummyFrontend
)
ConfirmTransaction
(
*
types
.
Transaction
)
bool
{
return
true
}
logMut
sync
.
RWMutex
logs
map
[
int
]
*
logFilter
messagesMut
sync
.
RWMutex
messages
map
[
int
]
*
whisperFilter
// regmut sync.Mutex
// register map[string][]*interface{} // TODO improve return type
}
// New creates an XEth that uses the given frontend.
// If a nil Frontend is provided, a default frontend which
...
...
@@ -90,15 +110,76 @@ func New(eth Backend, frontend Frontend) *XEth {
chainManager
:
eth
.
ChainManager
(),
accountManager
:
eth
.
AccountManager
(),
whisper
:
NewWhisper
(
eth
.
Whisper
()),
quit
:
make
(
chan
struct
{}),
filterManager
:
filter
.
NewFilterManager
(
eth
.
EventMux
()),
frontend
:
frontend
,
logs
:
make
(
map
[
int
]
*
logFilter
),
messages
:
make
(
map
[
int
]
*
whisperFilter
),
}
if
frontend
==
nil
{
xeth
.
frontend
=
dummyFrontend
{}
}
xeth
.
state
=
NewState
(
xeth
,
xeth
.
chainManager
.
TransState
())
go
xeth
.
start
()
go
xeth
.
filterManager
.
Start
()
return
xeth
}
func
(
self
*
XEth
)
start
()
{
timer
:=
time
.
NewTicker
(
2
*
time
.
Second
)
done
:
for
{
select
{
case
<-
timer
.
C
:
self
.
logMut
.
Lock
()
self
.
messagesMut
.
Lock
()
for
id
,
filter
:=
range
self
.
logs
{
if
time
.
Since
(
filter
.
timeout
)
>
filterTickerTime
{
self
.
filterManager
.
UninstallFilter
(
id
)
delete
(
self
.
logs
,
id
)
}
}
for
id
,
filter
:=
range
self
.
messages
{
if
time
.
Since
(
filter
.
timeout
)
>
filterTickerTime
{
self
.
Whisper
()
.
Unwatch
(
id
)
delete
(
self
.
messages
,
id
)
}
}
self
.
messagesMut
.
Unlock
()
self
.
logMut
.
Unlock
()
case
<-
self
.
quit
:
break
done
}
}
}
func
(
self
*
XEth
)
stop
()
{
close
(
self
.
quit
)
}
func
(
self
*
XEth
)
DefaultGas
()
*
big
.
Int
{
return
defaultGas
}
func
(
self
*
XEth
)
DefaultGasPrice
()
*
big
.
Int
{
return
defaultGasPrice
}
func
(
self
*
XEth
)
AtStateNum
(
num
int64
)
*
XEth
{
chain
:=
self
.
Backend
()
.
ChainManager
()
var
block
*
types
.
Block
if
num
<
0
{
num
=
chain
.
CurrentBlock
()
.
Number
()
.
Int64
()
+
num
+
1
}
block
=
chain
.
GetBlockByNumber
(
uint64
(
num
))
var
st
*
state
.
StateDB
if
block
!=
nil
{
st
=
state
.
New
(
block
.
Root
(),
self
.
Backend
()
.
StateDb
())
}
else
{
st
=
chain
.
State
()
}
return
self
.
WithState
(
st
)
}
func
(
self
*
XEth
)
Backend
()
Backend
{
return
self
.
eth
}
func
(
self
*
XEth
)
WithState
(
statedb
*
state
.
StateDB
)
*
XEth
{
xeth
:=
&
XEth
{
...
...
@@ -241,6 +322,157 @@ func (self *XEth) SecretToAddress(key string) string {
return
common
.
ToHex
(
pair
.
Address
())
}
func
(
self
*
XEth
)
RegisterFilter
(
args
*
core
.
FilterOptions
)
int
{
var
id
int
filter
:=
core
.
NewFilter
(
self
.
Backend
())
filter
.
SetOptions
(
args
)
filter
.
LogsCallback
=
func
(
logs
state
.
Logs
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
self
.
logs
[
id
]
.
add
(
logs
...
)
}
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
return
id
}
func
(
self
*
XEth
)
UninstallFilter
(
id
int
)
bool
{
if
_
,
ok
:=
self
.
logs
[
id
];
ok
{
delete
(
self
.
logs
,
id
)
self
.
filterManager
.
UninstallFilter
(
id
)
return
true
}
return
false
}
func
(
self
*
XEth
)
NewFilterString
(
word
string
)
int
{
var
id
int
filter
:=
core
.
NewFilter
(
self
.
Backend
())
switch
word
{
case
"pending"
:
filter
.
PendingCallback
=
func
(
tx
*
types
.
Transaction
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
self
.
logs
[
id
]
.
add
(
&
state
.
StateLog
{})
}
case
"latest"
:
filter
.
BlockCallback
=
func
(
block
*
types
.
Block
,
logs
state
.
Logs
)
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
for
_
,
log
:=
range
logs
{
self
.
logs
[
id
]
.
add
(
log
)
}
self
.
logs
[
id
]
.
add
(
&
state
.
StateLog
{})
}
}
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
return
id
}
func
(
self
*
XEth
)
FilterChanged
(
id
int
)
state
.
Logs
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
if
self
.
logs
[
id
]
!=
nil
{
return
self
.
logs
[
id
]
.
get
()
}
return
nil
}
func
(
self
*
XEth
)
Logs
(
id
int
)
state
.
Logs
{
self
.
logMut
.
Lock
()
defer
self
.
logMut
.
Unlock
()
filter
:=
self
.
filterManager
.
GetFilter
(
id
)
if
filter
!=
nil
{
return
filter
.
Find
()
}
return
nil
}
func
(
self
*
XEth
)
AllLogs
(
args
*
core
.
FilterOptions
)
state
.
Logs
{
filter
:=
core
.
NewFilter
(
self
.
Backend
())
filter
.
SetOptions
(
args
)
return
filter
.
Find
()
}
func
(
p
*
XEth
)
NewWhisperFilter
(
opts
*
Options
)
int
{
var
id
int
opts
.
Fn
=
func
(
msg
WhisperMessage
)
{
p
.
messagesMut
.
Lock
()
defer
p
.
messagesMut
.
Unlock
()
p
.
messages
[
id
]
.
add
(
msg
)
// = append(p.messages[id], msg)
}
id
=
p
.
Whisper
()
.
Watch
(
opts
)
p
.
messages
[
id
]
=
&
whisperFilter
{
timeout
:
time
.
Now
()}
return
id
}
func
(
p
*
XEth
)
UninstallWhisperFilter
(
id
int
)
bool
{
if
_
,
ok
:=
p
.
messages
[
id
];
ok
{
delete
(
p
.
messages
,
id
)
return
true
}
return
false
}
func
(
self
*
XEth
)
MessagesChanged
(
id
int
)
[]
WhisperMessage
{
self
.
messagesMut
.
Lock
()
defer
self
.
messagesMut
.
Unlock
()
if
self
.
messages
[
id
]
!=
nil
{
return
self
.
messages
[
id
]
.
get
()
}
return
nil
}
// func (self *XEth) Register(args string) bool {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// if _, ok := self.register[args]; ok {
// self.register[args] = nil // register with empty
// }
// return true
// }
// func (self *XEth) Unregister(args string) bool {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// if _, ok := self.register[args]; ok {
// delete(self.register, args)
// return true
// }
// return false
// }
// // TODO improve return type
// func (self *XEth) PullWatchTx(args string) []*interface{} {
// self.regmut.Lock()
// defer self.regmut.Unlock()
// txs := self.register[args]
// self.register[args] = nil
// return txs
// }
type
KeyVal
struct
{
Key
string
`json:"key"`
Value
string
`json:"value"`
...
...
@@ -298,11 +530,6 @@ func (self *XEth) PushTx(encodedTx string) (string, error) {
return
common
.
ToHex
(
tx
.
Hash
()),
nil
}
var
(
defaultGasPrice
=
big
.
NewInt
(
10000000000000
)
defaultGas
=
big
.
NewInt
(
90000
)
)
func
(
self
*
XEth
)
Call
(
fromStr
,
toStr
,
valueStr
,
gasStr
,
gasPriceStr
,
dataStr
string
)
(
string
,
error
)
{
statedb
:=
self
.
State
()
.
State
()
//self.chainManager.TransState()
msg
:=
callmsg
{
...
...
@@ -333,12 +560,44 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
from
[]
byte
to
[]
byte
value
=
common
.
NewValue
(
valueStr
)
gas
=
common
.
NewValue
(
gasStr
)
price
=
common
.
NewValue
(
gasPriceStr
)
gas
=
common
.
Big
(
gasStr
)
price
=
common
.
Big
(
gasPriceStr
)
data
[]
byte
contractCreation
bool
)
// TODO if no_private_key then
//if _, exists := p.register[args.From]; exists {
// p.register[args.From] = append(p.register[args.From], args)
//} else {
/*
account := accounts.Get(common.FromHex(args.From))
if account != nil {
if account.Unlocked() {
if !unlockAccount(account) {
return
}
}
result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data))
if len(result) > 0 {
*reply = common.ToHex(result)
}
} else if _, exists := p.register[args.From]; exists {
p.register[ags.From] = append(p.register[args.From], args)
}
*/
// TODO: align default values to have the same type, e.g. not depend on
// common.Value conversions later on
if
gas
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
gas
=
defaultGas
}
if
price
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
price
=
defaultGasPrice
}
from
=
common
.
FromHex
(
fromStr
)
data
=
common
.
FromHex
(
codeStr
)
to
=
common
.
FromHex
(
toStr
)
...
...
@@ -348,9 +607,9 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
var
tx
*
types
.
Transaction
if
contractCreation
{
tx
=
types
.
NewContractCreationTx
(
value
.
BigInt
(),
gas
.
BigInt
(),
price
.
BigInt
()
,
data
)
tx
=
types
.
NewContractCreationTx
(
value
.
BigInt
(),
gas
,
price
,
data
)
}
else
{
tx
=
types
.
NewTransactionMessage
(
to
,
value
.
BigInt
(),
gas
.
BigInt
(),
price
.
BigInt
()
,
data
)
tx
=
types
.
NewTransactionMessage
(
to
,
value
.
BigInt
(),
gas
,
price
,
data
)
}
state
:=
self
.
chainManager
.
TxState
()
...
...
@@ -411,3 +670,36 @@ func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
func
(
m
callmsg
)
Gas
()
*
big
.
Int
{
return
m
.
gas
}
func
(
m
callmsg
)
Value
()
*
big
.
Int
{
return
m
.
value
}
func
(
m
callmsg
)
Data
()
[]
byte
{
return
m
.
data
}
type
whisperFilter
struct
{
messages
[]
WhisperMessage
timeout
time
.
Time
id
int
}
func
(
w
*
whisperFilter
)
add
(
msgs
...
WhisperMessage
)
{
w
.
messages
=
append
(
w
.
messages
,
msgs
...
)
}
func
(
w
*
whisperFilter
)
get
()
[]
WhisperMessage
{
w
.
timeout
=
time
.
Now
()
tmp
:=
w
.
messages
w
.
messages
=
nil
return
tmp
}
type
logFilter
struct
{
logs
state
.
Logs
timeout
time
.
Time
id
int
}
func
(
l
*
logFilter
)
add
(
logs
...
state
.
Log
)
{
l
.
logs
=
append
(
l
.
logs
,
logs
...
)
}
func
(
l
*
logFilter
)
get
()
state
.
Logs
{
l
.
timeout
=
time
.
Now
()
tmp
:=
l
.
logs
l
.
logs
=
nil
return
tmp
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment