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
03b8ddd1
Commit
03b8ddd1
authored
Mar 19, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'rpcfrontier' into develop
parents
93ba3df4
14a2f42f
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
341 additions
and
242 deletions
+341
-242
block_processor.go
core/block_processor.go
+8
-12
chain_makers.go
core/chain_makers.go
+2
-2
chain_manager.go
core/chain_manager.go
+5
-5
events.go
core/events.go
+23
-6
filter.go
core/filter.go
+2
-2
common.go
core/types/common.go
+6
-2
eth_filter.go
event/filter/eth_filter.go
+3
-3
api.go
rpc/api.go
+16
-8
args.go
rpc/args.go
+132
-62
args_test.go
rpc/args_test.go
+79
-1
http.go
rpc/http.go
+65
-33
util.go
rpc/util.go
+0
-106
No files found.
core/block_processor.go
View file @
03b8ddd1
...
...
@@ -7,8 +7,8 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
...
...
@@ -17,10 +17,6 @@ import (
"gopkg.in/fatih/set.v0"
)
type
PendingBlockEvent
struct
{
Block
*
types
.
Block
}
var
statelogger
=
logger
.
NewLogger
(
"BLOCK"
)
type
BlockProcessor
struct
{
...
...
@@ -137,7 +133,7 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
block
.
Header
()
.
GasUsed
=
totalUsedGas
if
transientProcess
{
go
self
.
eventMux
.
Post
(
PendingBlockEvent
{
block
})
go
self
.
eventMux
.
Post
(
PendingBlockEvent
{
block
,
statedb
.
Logs
()
})
}
return
receipts
,
handled
,
unhandled
,
erroneous
,
err
...
...
@@ -146,25 +142,25 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
// Process block will attempt to process the given block's transactions and applies them
// on top of the block's parent state (given it exists) and will return wether it was
// successful or not.
func
(
sm
*
BlockProcessor
)
Process
(
block
*
types
.
Block
)
(
td
*
big
.
Int
,
err
error
)
{
func
(
sm
*
BlockProcessor
)
Process
(
block
*
types
.
Block
)
(
td
*
big
.
Int
,
logs
state
.
Logs
,
err
error
)
{
// Processing a blocks may never happen simultaneously
sm
.
mutex
.
Lock
()
defer
sm
.
mutex
.
Unlock
()
header
:=
block
.
Header
()
if
sm
.
bc
.
HasBlock
(
header
.
Hash
())
{
return
nil
,
&
KnownBlockError
{
header
.
Number
,
header
.
Hash
()}
return
nil
,
nil
,
&
KnownBlockError
{
header
.
Number
,
header
.
Hash
()}
}
if
!
sm
.
bc
.
HasBlock
(
header
.
ParentHash
)
{
return
nil
,
ParentError
(
header
.
ParentHash
)
return
nil
,
nil
,
ParentError
(
header
.
ParentHash
)
}
parent
:=
sm
.
bc
.
GetBlock
(
header
.
ParentHash
)
return
sm
.
processWithParent
(
block
,
parent
)
}
func
(
sm
*
BlockProcessor
)
processWithParent
(
block
,
parent
*
types
.
Block
)
(
td
*
big
.
Int
,
err
error
)
{
func
(
sm
*
BlockProcessor
)
processWithParent
(
block
,
parent
*
types
.
Block
)
(
td
*
big
.
Int
,
logs
state
.
Logs
,
err
error
)
{
sm
.
lastAttemptedBlock
=
block
// Create a new state based on the parent's root (e.g., create copy)
...
...
@@ -177,7 +173,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// There can be at most two uncles
if
len
(
block
.
Uncles
())
>
2
{
return
nil
,
ValidationError
(
"Block can only contain one uncle (contained %v)"
,
len
(
block
.
Uncles
()))
return
nil
,
nil
,
ValidationError
(
"Block can only contain one uncle (contained %v)"
,
len
(
block
.
Uncles
()))
}
receipts
,
err
:=
sm
.
TransitionState
(
state
,
parent
,
block
,
false
)
...
...
@@ -236,7 +232,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
chainlogger
.
Infof
(
"processed block #%d (%x...)
\n
"
,
header
.
Number
,
block
.
Hash
()[
0
:
4
])
return
td
,
nil
return
td
,
state
.
Logs
(),
nil
}
// Validates the current block. Returns an error if the block was invalid,
...
...
core/chain_makers.go
View file @
03b8ddd1
...
...
@@ -4,8 +4,8 @@ import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/state"
...
...
@@ -93,7 +93,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Dat
blocks
:=
make
(
types
.
Blocks
,
max
)
for
i
:=
0
;
i
<
max
;
i
++
{
block
:=
makeBlock
(
bman
,
parent
,
i
,
db
,
seed
)
td
,
err
:=
bman
.
processWithParent
(
block
,
parent
)
td
,
_
,
err
:=
bman
.
processWithParent
(
block
,
parent
)
if
err
!=
nil
{
fmt
.
Println
(
"process with parent failed"
,
err
)
panic
(
err
)
...
...
core/chain_manager.go
View file @
03b8ddd1
...
...
@@ -6,8 +6,8 @@ import (
"math/big"
"sync"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -411,7 +411,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
for
i
,
block
:=
range
chain
{
// Call in to the block processor and check for errors. It's likely that if one block fails
// all others will fail too (unless a known block is returned).
td
,
err
:=
self
.
processor
.
Process
(
block
)
td
,
logs
,
err
:=
self
.
processor
.
Process
(
block
)
if
err
!=
nil
{
if
IsKnownBlockErr
(
err
)
{
continue
...
...
@@ -437,7 +437,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
if
block
.
Header
()
.
Number
.
Cmp
(
new
(
big
.
Int
)
.
Add
(
cblock
.
Header
()
.
Number
,
common
.
Big1
))
<
0
{
chainlogger
.
Infof
(
"Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v
\n
"
,
block
.
Header
()
.
Number
,
block
.
Hash
()[
:
4
],
td
,
cblock
.
Header
()
.
Number
,
cblock
.
Hash
()[
:
4
],
self
.
td
)
queue
[
i
]
=
ChainSplitEvent
{
block
}
queue
[
i
]
=
ChainSplitEvent
{
block
,
logs
}
queueEvent
.
splitCount
++
}
...
...
@@ -456,10 +456,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self
.
setTransState
(
state
.
New
(
block
.
Root
(),
self
.
stateDb
))
self
.
setTxState
(
state
.
New
(
block
.
Root
(),
self
.
stateDb
))
queue
[
i
]
=
ChainEvent
{
block
}
queue
[
i
]
=
ChainEvent
{
block
,
logs
}
queueEvent
.
canonicalCount
++
}
else
{
queue
[
i
]
=
ChainSideEvent
{
block
}
queue
[
i
]
=
ChainSideEvent
{
block
,
logs
}
queueEvent
.
sideCount
++
}
}
...
...
core/events.go
View file @
03b8ddd1
package
core
import
"github.com/ethereum/go-ethereum/core/types"
import
(
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
)
// TxPreEvent is posted when a transaction enters the transaction pool.
type
TxPreEvent
struct
{
Tx
*
types
.
Transaction
}
...
...
@@ -15,11 +18,25 @@ type NewBlockEvent struct{ Block *types.Block }
type
NewMinedBlockEvent
struct
{
Block
*
types
.
Block
}
// ChainSplit is posted when a new head is detected
type
ChainSplitEvent
struct
{
Block
*
types
.
Block
}
type
ChainEvent
struct
{
Block
*
types
.
Block
}
type
ChainSideEvent
struct
{
Block
*
types
.
Block
}
type
ChainSplitEvent
struct
{
Block
*
types
.
Block
Logs
state
.
Logs
}
type
ChainEvent
struct
{
Block
*
types
.
Block
Logs
state
.
Logs
}
type
ChainSideEvent
struct
{
Block
*
types
.
Block
Logs
state
.
Logs
}
type
PendingBlockEvent
struct
{
Block
*
types
.
Block
Logs
state
.
Logs
}
type
ChainHeadEvent
struct
{
Block
*
types
.
Block
}
...
...
core/filter.go
View file @
03b8ddd1
...
...
@@ -33,8 +33,8 @@ type Filter struct {
max
int
topics
[][][]
byte
BlockCallback
func
(
*
types
.
Block
)
PendingCallback
func
(
*
types
.
Block
)
BlockCallback
func
(
*
types
.
Block
,
state
.
Logs
)
PendingCallback
func
(
*
types
.
Block
,
state
.
Logs
)
LogsCallback
func
(
state
.
Logs
)
}
...
...
core/types/common.go
View file @
03b8ddd1
package
types
import
"math/big"
import
(
"math/big"
"github.com/ethereum/go-ethereum/state"
)
type
BlockProcessor
interface
{
Process
(
*
Block
)
(
*
big
.
Int
,
error
)
Process
(
*
Block
)
(
*
big
.
Int
,
state
.
Logs
,
error
)
}
event/filter/eth_filter.go
View file @
03b8ddd1
...
...
@@ -63,7 +63,7 @@ func (self *FilterManager) filterLoop() {
// Subscribe to events
events
:=
self
.
eventMux
.
Subscribe
(
core
.
PendingBlockEvent
{},
//
core.ChainEvent{},
core
.
ChainEvent
{},
state
.
Logs
(
nil
))
out
:
...
...
@@ -77,7 +77,7 @@ out:
self
.
filterMu
.
RLock
()
for
_
,
filter
:=
range
self
.
filters
{
if
filter
.
BlockCallback
!=
nil
{
filter
.
BlockCallback
(
event
.
Block
)
filter
.
BlockCallback
(
event
.
Block
,
event
.
Logs
)
}
}
self
.
filterMu
.
RUnlock
()
...
...
@@ -86,7 +86,7 @@ out:
self
.
filterMu
.
RLock
()
for
_
,
filter
:=
range
self
.
filters
{
if
filter
.
PendingCallback
!=
nil
{
filter
.
PendingCallback
(
event
.
Block
)
filter
.
PendingCallback
(
event
.
Block
,
event
.
Logs
)
}
}
self
.
filterMu
.
RUnlock
()
...
...
rpc/api.go
View file @
03b8ddd1
...
...
@@ -86,7 +86,7 @@ func (self *EthereumApi) getStateWithNum(num int64) *xeth.State {
}
func
(
self
*
EthereumApi
)
start
()
{
timer
:=
time
.
NewTicker
(
filterTickerTime
)
timer
:=
time
.
NewTicker
(
2
*
time
.
Second
)
done
:
for
{
select
{
...
...
@@ -94,20 +94,20 @@ done:
self
.
logMut
.
Lock
()
self
.
messagesMut
.
Lock
()
for
id
,
filter
:=
range
self
.
logs
{
if
time
.
Since
(
filter
.
timeout
)
>
20
*
time
.
Second
{
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
)
>
20
*
time
.
Second
{
if
time
.
Since
(
filter
.
timeout
)
>
filterTickerTime
{
self
.
xeth
()
.
Whisper
()
.
Unwatch
(
id
)
delete
(
self
.
messages
,
id
)
}
}
self
.
logMut
.
Unlock
()
self
.
messagesMut
.
Unlock
()
self
.
logMut
.
Unlock
()
case
<-
self
.
quit
:
break
done
}
...
...
@@ -161,7 +161,7 @@ func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) erro
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
*
reply
=
i2hex
(
id
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
()
)
return
nil
}
...
...
@@ -180,10 +180,13 @@ func (self *EthereumApi) NewFilterString(args *FilterStringArgs, reply *interfac
var
id
int
filter
:=
core
.
NewFilter
(
self
.
xeth
()
.
Backend
())
callback
:=
func
(
block
*
types
.
Block
)
{
callback
:=
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
{})
}
...
...
@@ -198,7 +201,7 @@ func (self *EthereumApi) NewFilterString(args *FilterStringArgs, reply *interfac
id
=
self
.
filterManager
.
InstallFilter
(
filter
)
self
.
logs
[
id
]
=
&
logFilter
{
timeout
:
time
.
Now
()}
*
reply
=
i2hex
(
id
)
*
reply
=
common
.
ToHex
(
big
.
NewInt
(
int64
(
id
))
.
Bytes
()
)
return
nil
}
...
...
@@ -257,6 +260,11 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) (err error)
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
{
...
...
@@ -478,7 +486,7 @@ func (p *EthereumApi) GetBlockUncleCountByNumber(blocknum int64) (int64, error)
func
(
p
*
EthereumApi
)
GetRequestReply
(
req
*
RpcRequest
,
reply
*
interface
{})
error
{
// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger
.
Debug
f
(
"%s %s"
,
req
.
Method
,
req
.
Params
)
rpclogger
.
Info
f
(
"%s %s"
,
req
.
Method
,
req
.
Params
)
switch
req
.
Method
{
case
"web3_sha3"
:
args
:=
new
(
Sha3Args
)
...
...
rpc/args.go
View file @
03b8ddd1
...
...
@@ -8,10 +8,18 @@ import (
"github.com/ethereum/go-ethereum/common"
)
func
blockNumber
(
raw
json
.
RawMessage
,
number
*
int64
)
(
err
error
)
{
var
str
string
if
err
=
json
.
Unmarshal
(
raw
,
&
str
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
func
blockAge
(
raw
interface
{},
number
*
int64
)
(
err
error
)
{
// Parse as integer
num
,
ok
:=
raw
.
(
float64
)
if
ok
{
*
number
=
int64
(
num
)
return
nil
}
// Parse as string/hexstring
str
,
ok
:=
raw
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"BlockNumber is not a string"
)
}
switch
str
{
...
...
@@ -22,6 +30,7 @@ func blockNumber(raw json.RawMessage, number *int64) (err error) {
default
:
*
number
=
common
.
String2Big
(
str
)
.
Int64
()
}
return
nil
}
...
...
@@ -95,18 +104,51 @@ type NewTxArgs struct {
}
func
(
args
*
NewTxArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
var
obj
struct
{
From
,
To
,
Value
,
Gas
,
GasPrice
,
Data
string
}
if
err
=
UnmarshalRawMessages
(
b
,
&
obj
,
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
var
obj
[]
json
.
RawMessage
var
ext
struct
{
From
,
To
,
Value
,
Gas
,
GasPrice
,
Data
string
}
// Decode byte slice to array of RawMessages
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
// Check for sufficient params
if
len
(
obj
)
<
1
{
return
NewInsufficientParamsError
(
len
(
obj
),
1
)
}
// Decode 0th RawMessage to temporary struct
if
err
:=
json
.
Unmarshal
(
obj
[
0
],
&
ext
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
// var ok bool
args
.
From
=
ext
.
From
args
.
To
=
ext
.
To
args
.
Value
=
common
.
String2Big
(
ext
.
Value
)
args
.
Gas
=
common
.
String2Big
(
ext
.
Gas
)
args
.
GasPrice
=
common
.
String2Big
(
ext
.
GasPrice
)
args
.
Data
=
ext
.
Data
// Check for optional BlockNumber param
if
len
(
obj
)
>
1
{
var
raw
interface
{}
if
err
=
json
.
Unmarshal
(
obj
[
1
],
&
raw
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
err
:=
blockAge
(
raw
,
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
args
.
From
=
obj
.
From
args
.
To
=
obj
.
To
args
.
Value
=
common
.
Big
(
obj
.
Value
)
args
.
Gas
=
common
.
Big
(
obj
.
Gas
)
args
.
GasPrice
=
common
.
Big
(
obj
.
GasPrice
)
args
.
Data
=
obj
.
Data
return
nil
}
func
(
args
*
NewTxArgs
)
requirements
()
error
{
if
len
(
args
.
From
)
==
0
{
return
NewValidationError
(
"From"
,
"Is required"
)
}
return
nil
}
...
...
@@ -116,10 +158,27 @@ type GetStorageArgs struct {
}
func
(
args
*
GetStorageArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
if
err
=
UnmarshalRawMessages
(
b
,
&
args
.
Address
,
&
args
.
BlockNumber
);
err
!=
nil
{
var
obj
[]
interface
{}
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
len
(
obj
)
<
1
{
return
NewInsufficientParamsError
(
len
(
obj
),
1
)
}
addstr
,
ok
:=
obj
[
0
]
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"Address is not a string"
)
}
args
.
Address
=
addstr
if
len
(
obj
)
>
1
{
if
err
:=
blockAge
(
obj
[
1
],
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
return
nil
}
...
...
@@ -137,16 +196,32 @@ type GetStorageAtArgs struct {
}
func
(
args
*
GetStorageAtArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
var
obj
[]
string
if
err
=
UnmarshalRawMessages
(
b
,
&
obj
,
&
args
.
BlockNumber
);
err
!=
nil
{
var
obj
[]
interface
{}
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
len
(
obj
)
<
2
{
return
NewInsufficientParamsError
(
len
(
obj
),
2
)
}
args
.
Address
=
obj
[
0
]
args
.
Key
=
obj
[
1
]
addstr
,
ok
:=
obj
[
0
]
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"Address is not a string"
)
}
args
.
Address
=
addstr
keystr
,
ok
:=
obj
[
1
]
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"Key is not a string"
)
}
args
.
Key
=
keystr
if
len
(
obj
)
>
2
{
if
err
:=
blockAge
(
obj
[
2
],
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
return
nil
}
...
...
@@ -168,10 +243,27 @@ type GetTxCountArgs struct {
}
func
(
args
*
GetTxCountArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
if
err
=
UnmarshalRawMessages
(
b
,
&
args
.
Address
,
&
args
.
BlockNumber
);
err
!=
nil
{
var
obj
[]
interface
{}
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
len
(
obj
)
<
1
{
return
NewInsufficientParamsError
(
len
(
obj
),
1
)
}
addstr
,
ok
:=
obj
[
0
]
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"Address is not a string"
)
}
args
.
Address
=
addstr
if
len
(
obj
)
>
1
{
if
err
:=
blockAge
(
obj
[
1
],
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
return
nil
}
...
...
@@ -189,8 +281,7 @@ type GetBalanceArgs struct {
func
(
args
*
GetBalanceArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
var
obj
[]
interface
{}
r
:=
bytes
.
NewReader
(
b
)
if
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
&
obj
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
...
...
@@ -205,17 +296,11 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
args
.
Address
=
addstr
if
len
(
obj
)
>
1
{
if
obj
[
1
]
.
(
string
)
==
"latest"
{
args
.
BlockNumber
=
-
1
}
else
{
args
.
BlockNumber
=
common
.
Big
(
obj
[
1
]
.
(
string
))
.
Int64
()
if
err
:=
blockAge
(
obj
[
1
],
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
// if err = UnmarshalRawMessages(b, &args.Address, &args.BlockNumber); err != nil {
// return NewDecodeParamError(err.Error())
// }
return
nil
}
...
...
@@ -232,10 +317,27 @@ type GetDataArgs struct {
}
func
(
args
*
GetDataArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
if
err
=
UnmarshalRawMessages
(
b
,
&
args
.
Address
,
&
args
.
BlockNumber
);
err
!=
nil
{
var
obj
[]
interface
{}
if
err
:=
json
.
Unmarshal
(
b
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
len
(
obj
)
<
1
{
return
NewInsufficientParamsError
(
len
(
obj
),
1
)
}
addstr
,
ok
:=
obj
[
0
]
.
(
string
)
if
!
ok
{
return
NewDecodeParamError
(
"Address is not a string"
)
}
args
.
Address
=
addstr
if
len
(
obj
)
>
1
{
if
err
:=
blockAge
(
obj
[
1
],
&
args
.
BlockNumber
);
err
!=
nil
{
return
err
}
}
return
nil
}
...
...
@@ -392,10 +494,6 @@ func (args *FilterOptions) UnmarshalJSON(b []byte) (err error) {
return
nil
}
// type FilterChangedArgs struct {
// n int
// }
type
DbArgs
struct
{
Database
string
Key
string
...
...
@@ -578,31 +676,3 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
return
nil
}
// func (req *RpcRequest) ToRegisterArgs() (string, error) {
// if len(req.Params) < 1 {
// return "", errArguments
// }
// var args string
// err := json.Unmarshal(req.Params, &args)
// if err != nil {
// return "", err
// }
// return args, nil
// }
// func (req *RpcRequest) ToWatchTxArgs() (string, error) {
// if len(req.Params) < 1 {
// return "", errArguments
// }
// var args string
// err := json.Unmarshal(req.Params, &args)
// if err != nil {
// return "", err
// }
// return args, nil
// }
rpc/args_test.go
View file @
03b8ddd1
...
...
@@ -43,6 +43,30 @@ func TestGetBalanceArgs(t *testing.T) {
}
}
func
TestGetBalanceArgsLatest
(
t
*
testing
.
T
)
{
input
:=
`["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
expected
:=
new
(
GetBalanceArgs
)
expected
.
Address
=
"0x407d73d8a49eeb85d32cf465507dd71d507100c1"
expected
.
BlockNumber
=
-
1
args
:=
new
(
GetBalanceArgs
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
t
.
Error
(
err
)
}
if
err
:=
args
.
requirements
();
err
!=
nil
{
t
.
Error
(
err
)
}
if
args
.
Address
!=
expected
.
Address
{
t
.
Errorf
(
"Address should be %v but is %v"
,
expected
.
Address
,
args
.
Address
)
}
if
args
.
BlockNumber
!=
expected
.
BlockNumber
{
t
.
Errorf
(
"BlockNumber should be %v but is %v"
,
expected
.
BlockNumber
,
args
.
BlockNumber
)
}
}
func
TestGetBalanceEmptyArgs
(
t
*
testing
.
T
)
{
input
:=
`[]`
...
...
@@ -120,7 +144,8 @@ func TestNewTxArgs(t *testing.T) {
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a000",
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}]`
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"},
"0x10"]`
expected
:=
new
(
NewTxArgs
)
expected
.
From
=
"0xb60e8dd61c5d32be8058bb8eb970870f07233155"
expected
.
To
=
"0xd46e8dd67c5d32be8058bb8eb970870f072445675"
...
...
@@ -128,6 +153,7 @@ func TestNewTxArgs(t *testing.T) {
expected
.
GasPrice
=
big
.
NewInt
(
10000000000000
)
expected
.
Value
=
big
.
NewInt
(
10000000000000
)
expected
.
Data
=
"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
expected
.
BlockNumber
=
big
.
NewInt
(
16
)
.
Int64
()
args
:=
new
(
NewTxArgs
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
...
...
@@ -157,6 +183,30 @@ func TestNewTxArgs(t *testing.T) {
if
expected
.
Data
!=
args
.
Data
{
t
.
Errorf
(
"Data shoud be %#v but is %#v"
,
expected
.
Data
,
args
.
Data
)
}
if
expected
.
BlockNumber
!=
args
.
BlockNumber
{
t
.
Errorf
(
"BlockNumber shoud be %#v but is %#v"
,
expected
.
BlockNumber
,
args
.
BlockNumber
)
}
}
func
TestNewTxArgsBlockInt
(
t
*
testing
.
T
)
{
input
:=
`[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}, 5]`
expected
:=
new
(
NewTxArgs
)
expected
.
From
=
"0xb60e8dd61c5d32be8058bb8eb970870f07233155"
expected
.
BlockNumber
=
big
.
NewInt
(
5
)
.
Int64
()
args
:=
new
(
NewTxArgs
)
if
err
:=
json
.
Unmarshal
([]
byte
(
input
),
&
args
);
err
!=
nil
{
t
.
Error
(
err
)
}
if
expected
.
From
!=
args
.
From
{
t
.
Errorf
(
"From shoud be %#v but is %#v"
,
expected
.
From
,
args
.
From
)
}
if
expected
.
BlockNumber
!=
args
.
BlockNumber
{
t
.
Errorf
(
"BlockNumber shoud be %#v but is %#v"
,
expected
.
BlockNumber
,
args
.
BlockNumber
)
}
}
func
TestNewTxArgsEmpty
(
t
*
testing
.
T
)
{
...
...
@@ -169,6 +219,34 @@ func TestNewTxArgsEmpty(t *testing.T) {
}
}
func
TestNewTxArgsReqs
(
t
*
testing
.
T
)
{
args
:=
new
(
NewTxArgs
)
args
.
From
=
"0xb60e8dd61c5d32be8058bb8eb970870f07233155"
err
:=
args
.
requirements
()
switch
err
.
(
type
)
{
case
nil
:
break
default
:
t
.
Errorf
(
"Get %T"
,
err
)
}
}
func
TestNewTxArgsReqsFromBlank
(
t
*
testing
.
T
)
{
args
:=
new
(
NewTxArgs
)
args
.
From
=
""
err
:=
args
.
requirements
()
switch
err
.
(
type
)
{
case
nil
:
t
.
Error
(
"Expected error but didn't get one"
)
case
*
ValidationError
:
break
default
:
t
.
Error
(
"Wrong type of error"
)
}
}
func
TestGetStorageArgs
(
t
*
testing
.
T
)
{
input
:=
`["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
expected
:=
new
(
GetStorageArgs
)
...
...
rpc/http.go
View file @
03b8ddd1
package
rpc
import
(
"encoding/json"
"io"
"io/ioutil"
"net/http"
"github.com/ethereum/go-ethereum/logger"
...
...
@@ -16,54 +19,83 @@ const (
// JSONRPC returns a handler that implements the Ethereum JSON-RPC API.
func
JSONRPC
(
pipe
*
xeth
.
XEth
,
dataDir
string
)
http
.
Handler
{
var
json
JsonWrapper
api
:=
NewEthereumApi
(
pipe
,
dataDir
)
return
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
// TODO this needs to be configurable
w
.
Header
()
.
Set
(
"Access-Control-Allow-Origin"
,
"*"
)
rpchttplogger
.
DebugDetailln
(
"Handling request"
)
// Limit request size to resist DoS
if
req
.
ContentLength
>
maxSizeReqLength
{
jsonerr
:=
&
RpcErrorObject
{
-
32700
,
"Request too large"
}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
return
}
reqParsed
,
reqerr
:=
json
.
ParseRequestBody
(
req
)
switch
reqerr
.
(
type
)
{
case
nil
:
break
case
*
DecodeParamError
,
*
InsufficientParamsError
,
*
ValidationError
:
jsonerr
:=
&
RpcErrorObject
{
-
32602
,
reqerr
.
Error
()}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
return
default
:
jsonerr
:=
&
RpcErrorObject
{
-
32700
,
"Could not parse request"
}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
return
// Read request body
defer
req
.
Body
.
Close
()
body
,
err
:=
ioutil
.
ReadAll
(
req
.
Body
)
if
err
!=
nil
{
jsonerr
:=
&
RpcErrorObject
{
-
32700
,
"Could not read request body"
}
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
}
var
response
interface
{}
reserr
:=
api
.
GetRequestReply
(
&
reqParsed
,
&
response
)
switch
reserr
.
(
type
)
{
case
nil
:
break
case
*
NotImplementedError
:
jsonerr
:=
&
RpcErrorObject
{
-
32601
,
reserr
.
Error
()}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
reqParsed
.
Id
,
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
)
Send
(
w
,
&
response
)
return
case
*
DecodeParamError
,
*
InsufficientParamsError
,
*
ValidationError
:
jsonerr
:=
&
RpcErrorObject
{
-
32602
,
reserr
.
Error
()}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
reqParsed
.
Id
,
Error
:
jsonerr
})
return
default
:
jsonerr
:=
&
RpcErrorObject
{
-
32603
,
reserr
.
Error
()}
json
.
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
reqParsed
.
Id
,
Error
:
jsonerr
})
}
// Try to parse the request to batch
var
reqBatch
[]
RpcRequest
if
err
:=
json
.
Unmarshal
(
body
,
&
reqBatch
);
err
==
nil
{
// Build response batch
resBatch
:=
make
([]
*
interface
{},
len
(
reqBatch
))
for
i
,
request
:=
range
reqBatch
{
response
:=
RpcResponse
(
api
,
&
request
)
resBatch
[
i
]
=
response
}
Send
(
w
,
resBatch
)
return
}
rpchttplogger
.
DebugDetailf
(
"Generated response: %T %s"
,
response
,
response
)
json
.
Send
(
w
,
&
RpcSuccessResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
reqParsed
.
Id
,
Result
:
response
})
// Not a batch or single request, error
jsonerr
:=
&
RpcErrorObject
{
-
32600
,
"Could not decode request"
}
Send
(
w
,
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
nil
,
Error
:
jsonerr
})
})
}
func
RpcResponse
(
api
*
EthereumApi
,
request
*
RpcRequest
)
*
interface
{}
{
var
reply
,
response
interface
{}
reserr
:=
api
.
GetRequestReply
(
request
,
&
reply
)
switch
reserr
.
(
type
)
{
case
nil
:
response
=
&
RpcSuccessResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
request
.
Id
,
Result
:
reply
}
case
*
NotImplementedError
:
jsonerr
:=
&
RpcErrorObject
{
-
32601
,
reserr
.
Error
()}
response
=
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
request
.
Id
,
Error
:
jsonerr
}
case
*
DecodeParamError
,
*
InsufficientParamsError
,
*
ValidationError
:
jsonerr
:=
&
RpcErrorObject
{
-
32602
,
reserr
.
Error
()}
response
=
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
request
.
Id
,
Error
:
jsonerr
}
default
:
jsonerr
:=
&
RpcErrorObject
{
-
32603
,
reserr
.
Error
()}
response
=
&
RpcErrorResponse
{
Jsonrpc
:
jsonrpcver
,
Id
:
request
.
Id
,
Error
:
jsonerr
}
}
rpchttplogger
.
DebugDetailf
(
"Generated response: %T %s"
,
response
,
response
)
return
&
response
}
func
Send
(
writer
io
.
Writer
,
v
interface
{})
(
n
int
,
err
error
)
{
var
payload
[]
byte
payload
,
err
=
json
.
MarshalIndent
(
v
,
""
,
"
\t
"
)
if
err
!=
nil
{
rpclogger
.
Fatalln
(
"Error marshalling JSON"
,
err
)
return
0
,
err
}
rpclogger
.
DebugDetailf
(
"Sending payload: %s"
,
payload
)
return
writer
.
Write
(
payload
)
}
rpc/util.go
View file @
03b8ddd1
...
...
@@ -17,12 +17,6 @@
package
rpc
import
(
"encoding/json"
"fmt"
"io"
"math/big"
"net/http"
"reflect"
"time"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -33,106 +27,6 @@ import (
var
rpclogger
=
logger
.
NewLogger
(
"RPC"
)
type
JsonWrapper
struct
{}
// Unmarshal state is a helper method which has the ability to decode messsages
// that use the `defaultBlock` (https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter)
// For example a `call`: [{to: "0x....", data:"0x..."}, "latest"]. The first argument is the transaction
// message and the second one refers to the block height (or state) to which to apply this `call`.
func
UnmarshalRawMessages
(
b
[]
byte
,
iface
interface
{},
number
*
int64
)
(
err
error
)
{
var
data
[]
json
.
RawMessage
if
err
=
json
.
Unmarshal
(
b
,
&
data
);
err
!=
nil
&&
len
(
data
)
==
0
{
return
NewDecodeParamError
(
err
.
Error
())
}
// Hrm... Occurs when no params
if
len
(
data
)
==
0
{
return
NewDecodeParamError
(
"No data"
)
}
// Number index determines the index in the array for a possible block number
numberIndex
:=
0
value
:=
reflect
.
ValueOf
(
iface
)
rvalue
:=
reflect
.
Indirect
(
value
)
switch
rvalue
.
Kind
()
{
case
reflect
.
Slice
:
// This is a bit of a cheat, but `data` is expected to be larger than 2 if iface is a slice
if
number
!=
nil
{
numberIndex
=
len
(
data
)
-
1
}
else
{
numberIndex
=
len
(
data
)
}
slice
:=
reflect
.
MakeSlice
(
rvalue
.
Type
(),
numberIndex
,
numberIndex
)
for
i
,
raw
:=
range
data
[
0
:
numberIndex
]
{
v
:=
slice
.
Index
(
i
)
.
Interface
()
if
err
=
json
.
Unmarshal
(
raw
,
&
v
);
err
!=
nil
{
fmt
.
Println
(
err
,
v
)
return
err
}
slice
.
Index
(
i
)
.
Set
(
reflect
.
ValueOf
(
v
))
}
reflect
.
Indirect
(
rvalue
)
.
Set
(
slice
)
//value.Set(slice)
case
reflect
.
Struct
:
fallthrough
default
:
if
err
=
json
.
Unmarshal
(
data
[
0
],
iface
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
numberIndex
=
1
}
// <0 index means out of bound for block number
if
numberIndex
>=
0
&&
len
(
data
)
>
numberIndex
{
if
err
=
blockNumber
(
data
[
numberIndex
],
number
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
}
return
nil
}
func
(
self
JsonWrapper
)
Send
(
writer
io
.
Writer
,
v
interface
{})
(
n
int
,
err
error
)
{
var
payload
[]
byte
payload
,
err
=
json
.
MarshalIndent
(
v
,
""
,
"
\t
"
)
if
err
!=
nil
{
rpclogger
.
Fatalln
(
"Error marshalling JSON"
,
err
)
return
0
,
err
}
rpclogger
.
DebugDetailf
(
"Sending payload: %s"
,
payload
)
return
writer
.
Write
(
payload
)
}
func
(
self
JsonWrapper
)
ParseRequestBody
(
req
*
http
.
Request
)
(
RpcRequest
,
error
)
{
var
reqParsed
RpcRequest
// Convert JSON to native types
d
:=
json
.
NewDecoder
(
req
.
Body
)
defer
req
.
Body
.
Close
()
err
:=
d
.
Decode
(
&
reqParsed
)
if
err
!=
nil
{
rpclogger
.
Errorln
(
"Error decoding JSON: "
,
err
)
return
reqParsed
,
err
}
rpclogger
.
DebugDetailf
(
"Parsed request: %s"
,
reqParsed
)
return
reqParsed
,
nil
}
func
i2hex
(
n
int
)
string
{
return
common
.
ToHex
(
big
.
NewInt
(
int64
(
n
))
.
Bytes
())
}
type
RpcServer
interface
{
Start
()
Stop
()
}
type
Log
struct
{
Address
string
`json:"address"`
Topic
[]
string
`json:"topic"`
...
...
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