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
4c596809
Commit
4c596809
authored
Jan 28, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'jsonrpc' into qt5.4
parents
f3e78c8f
159c4d56
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
965 additions
and
353 deletions
+965
-353
.gitignore
.gitignore
+2
-0
cmd.go
cmd/utils/cmd.go
+8
-0
args.go
rpc/args.go
+218
-0
json.go
rpc/json.go
+37
-0
message.go
rpc/message.go
+161
-8
packages.go
rpc/packages.go
+108
-211
server.go
rpc/server.go
+49
-12
writer.go
rpc/writer.go
+0
-75
gh_test.go
tests/vm/gh_test.go
+9
-9
vm_jit.go
vm/vm_jit.go
+349
-9
vm_jit_fake.go
vm/vm_jit_fake.go
+10
-0
util.go
websocket/util.go
+14
-29
No files found.
.gitignore
View file @
4c596809
...
@@ -15,3 +15,5 @@
...
@@ -15,3 +15,5 @@
.#*
.#*
*#
*#
*~
*~
.project
.settings
cmd/utils/cmd.go
View file @
4c596809
...
@@ -40,6 +40,7 @@ import (
...
@@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/websocket"
"github.com/ethereum/go-ethereum/xeth"
"github.com/ethereum/go-ethereum/xeth"
)
)
...
@@ -200,6 +201,13 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
...
@@ -200,6 +201,13 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
}
}
}
}
func
StartWebSockets
(
eth
*
eth
.
Ethereum
)
{
clilogger
.
Infoln
(
"Starting WebSockets"
)
sock
:=
websocket
.
NewWebSocketServer
(
eth
)
go
sock
.
Serv
()
}
var
gminer
*
miner
.
Miner
var
gminer
*
miner
.
Miner
func
GetMiner
()
*
miner
.
Miner
{
func
GetMiner
()
*
miner
.
Miner
{
...
...
rpc/args.go
0 → 100644
View file @
4c596809
package
rpc
import
(
"encoding/json"
)
type
GetBlockArgs
struct
{
BlockNumber
int32
Hash
string
}
func
(
obj
*
GetBlockArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
argint
,
argstr
:=
int32
(
0
),
""
if
err
=
json
.
Unmarshal
(
b
,
&
argint
);
err
==
nil
{
obj
.
BlockNumber
=
argint
return
}
if
err
=
json
.
Unmarshal
(
b
,
&
argstr
);
err
==
nil
{
obj
.
Hash
=
argstr
return
}
return
NewErrorResponse
(
ErrorDecodeArgs
)
}
func
(
obj
*
GetBlockArgs
)
requirements
()
error
{
if
obj
.
BlockNumber
==
0
&&
obj
.
Hash
==
""
{
return
NewErrorResponse
(
"GetBlock requires either a block 'number' or a block 'hash' as argument"
)
}
return
nil
}
type
NewTxArgs
struct
{
Sec
string
`json:"sec"`
Recipient
string
`json:"recipient"`
Value
string
`json:"value"`
Gas
string
`json:"gas"`
GasPrice
string
`json:"gasprice"`
Init
string
`json:"init"`
Body
string
`json:"body"`
}
// type TxResponse struct {
// Hash string
// }
func
(
obj
*
NewTxArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
if
err
=
json
.
Unmarshal
(
b
,
obj
);
err
==
nil
{
return
}
return
NewErrorResponse
(
ErrorDecodeArgs
)
}
func
(
a
*
NewTxArgs
)
requirements
()
error
{
if
a
.
Recipient
==
""
{
return
NewErrorResponse
(
"Transact requires a 'recipient' address as argument"
)
}
if
a
.
Value
==
""
{
return
NewErrorResponse
(
"Transact requires a 'value' as argument"
)
}
if
a
.
Gas
==
""
{
return
NewErrorResponse
(
"Transact requires a 'gas' value as argument"
)
}
if
a
.
GasPrice
==
""
{
return
NewErrorResponse
(
"Transact requires a 'gasprice' value as argument"
)
}
return
nil
}
func
(
a
*
NewTxArgs
)
requirementsContract
()
error
{
if
a
.
Value
==
""
{
return
NewErrorResponse
(
"Create requires a 'value' as argument"
)
}
if
a
.
Gas
==
""
{
return
NewErrorResponse
(
"Create requires a 'gas' value as argument"
)
}
if
a
.
GasPrice
==
""
{
return
NewErrorResponse
(
"Create requires a 'gasprice' value as argument"
)
}
if
a
.
Body
==
""
{
return
NewErrorResponse
(
"Create requires a 'body' value as argument"
)
}
return
nil
}
type
PushTxArgs
struct
{
Tx
string
`json:"tx"`
}
func
(
obj
*
PushTxArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
arg0
:=
""
if
err
=
json
.
Unmarshal
(
b
,
arg0
);
err
==
nil
{
obj
.
Tx
=
arg0
return
}
return
NewErrorResponse
(
ErrorDecodeArgs
)
}
func
(
a
*
PushTxArgs
)
requirementsPushTx
()
error
{
if
a
.
Tx
==
""
{
return
NewErrorResponse
(
"PushTx requires a 'tx' as argument"
)
}
return
nil
}
type
GetStorageArgs
struct
{
Address
string
Key
string
}
func
(
obj
*
GetStorageArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
arg0
:=
""
if
err
=
json
.
Unmarshal
(
b
,
arg0
);
err
==
nil
{
obj
.
Address
=
arg0
return
}
return
NewErrorResponse
(
ErrorDecodeArgs
)
}
func
(
a
*
GetStorageArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetStorageAt requires an 'address' value as argument"
)
}
if
a
.
Key
==
""
{
return
NewErrorResponse
(
"GetStorageAt requires an 'key' value as argument"
)
}
return
nil
}
type
GetStorageAtRes
struct
{
Key
string
`json:"key"`
Value
string
`json:"value"`
Address
string
`json:"address"`
}
type
GetTxCountArgs
struct
{
Address
string
`json:"address"`
}
// type GetTxCountRes struct {
// Nonce int `json:"nonce"`
// }
func
(
obj
*
GetTxCountArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
arg0
:=
""
if
err
=
json
.
Unmarshal
(
b
,
arg0
);
err
==
nil
{
obj
.
Address
=
arg0
return
}
return
NewErrorResponse
(
"Could not determine JSON parameters"
)
}
func
(
a
*
GetTxCountArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetTxCountAt requires an 'address' value as argument"
)
}
return
nil
}
// type GetPeerCountRes struct {
// PeerCount int `json:"peerCount"`
// }
// type GetListeningRes struct {
// IsListening bool `json:"isListening"`
// }
// type GetCoinbaseRes struct {
// Coinbase string `json:"coinbase"`
// }
// type GetMiningRes struct {
// IsMining bool `json:"isMining"`
// }
type
GetBalanceArgs
struct
{
Address
string
}
func
(
obj
*
GetBalanceArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
arg0
:=
""
if
err
=
json
.
Unmarshal
(
b
,
&
arg0
);
err
==
nil
{
obj
.
Address
=
arg0
return
}
return
NewErrorResponse
(
"Could not determine JSON parameters"
)
}
func
(
a
*
GetBalanceArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetBalanceAt requires an 'address' value as argument"
)
}
return
nil
}
type
BalanceRes
struct
{
Balance
string
`json:"balance"`
Address
string
`json:"address"`
}
type
GetCodeAtArgs
struct
{
Address
string
}
func
(
obj
*
GetCodeAtArgs
)
UnmarshalJSON
(
b
[]
byte
)
(
err
error
)
{
arg0
:=
""
if
err
=
json
.
Unmarshal
(
b
,
&
arg0
);
err
==
nil
{
obj
.
Address
=
arg0
return
}
return
NewErrorResponse
(
ErrorDecodeArgs
)
}
func
(
a
*
GetCodeAtArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetCodeAt requires an 'address' value as argument"
)
}
return
nil
}
rpc/json.go
View file @
4c596809
/*
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
package
rpc
import
(
import
(
"encoding/json"
"encoding/json"
"io"
"io"
"net/http"
)
)
type
jsonWrapper
struct
{}
type
jsonWrapper
struct
{}
...
@@ -11,10 +28,30 @@ func (self jsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error)
...
@@ -11,10 +28,30 @@ func (self jsonWrapper) Send(writer io.Writer, v interface{}) (n int, err error)
var
payload
[]
byte
var
payload
[]
byte
payload
,
err
=
json
.
Marshal
(
v
)
payload
,
err
=
json
.
Marshal
(
v
)
if
err
!=
nil
{
if
err
!=
nil
{
jsonlogger
.
Fatalln
(
"Error marshalling JSON"
,
err
)
return
0
,
err
return
0
,
err
}
}
jsonlogger
.
Infof
(
"Sending payload: %s"
,
payload
)
return
writer
.
Write
(
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
)
// d.UseNumber()
defer
req
.
Body
.
Close
()
err
:=
d
.
Decode
(
&
reqParsed
)
if
err
!=
nil
{
jsonlogger
.
Errorln
(
"Error decoding JSON: "
,
err
)
return
reqParsed
,
err
}
jsonlogger
.
DebugDetailf
(
"Parsed request: %s"
,
reqParsed
)
return
reqParsed
,
nil
}
var
JSON
jsonWrapper
var
JSON
jsonWrapper
rpc/message.go
View file @
4c596809
/*
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
package
rpc
import
"github.com/ethereum/go-ethereum/ethutil"
import
(
"bytes"
"encoding/json"
"errors"
)
const
(
ErrorArguments
=
"Error: Insufficient arguments"
ErrorNotImplemented
=
"Error: Method not implemented"
ErrorUnknown
=
"Error: Unknown error"
ErrorParseRequest
=
"Error: Could not parse request"
ErrorDecodeArgs
=
"Error: Could not decode arguments"
)
type
ErrorResponse
struct
{
Error
bool
`json:"error"`
ErrorText
string
`json:"errorText"`
}
type
RpcSuccessResponse
struct
{
ID
int
`json:"id"`
JsonRpc
string
`json:"jsonrpc"`
Error
bool
`json:"error"`
Result
interface
{}
`json:"result"`
}
type
RpcErrorResponse
struct
{
ID
int
`json:"id"`
JsonRpc
string
`json:"jsonrpc"`
Error
bool
`json:"error"`
ErrorText
string
`json:"errortext"`
}
type
RpcRequest
struct
{
JsonRpc
string
`json:"jsonrpc"`
ID
int
`json:"id"`
Method
string
`json:"method"`
Params
[]
json
.
RawMessage
`json:"params"`
}
func
(
req
*
RpcRequest
)
ToGetBlockArgs
()
(
*
GetBlockArgs
,
error
)
{
if
len
(
req
.
Params
)
<
1
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
GetBlockArgs
)
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToNewTxArgs
()
(
*
NewTxArgs
,
error
)
{
if
len
(
req
.
Params
)
<
7
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
NewTxArgs
)
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToPushTxArgs
()
(
*
PushTxArgs
,
error
)
{
if
len
(
req
.
Params
)
<
1
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
PushTxArgs
)
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToGetStorageArgs
()
(
*
GetStorageArgs
,
error
)
{
if
len
(
req
.
Params
)
<
2
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
GetStorageArgs
)
// TODO need to pass both arguments
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToGetTxCountArgs
()
(
*
GetTxCountArgs
,
error
)
{
if
len
(
req
.
Params
)
<
1
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
GetTxCountArgs
)
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToGetBalanceArgs
()
(
*
GetBalanceArgs
,
error
)
{
if
len
(
req
.
Params
)
<
1
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
args
:=
new
(
GetBalanceArgs
)
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
if
err
!=
nil
{
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
func
(
req
*
RpcRequest
)
ToGetCodeAtArgs
()
(
*
GetCodeAtArgs
,
error
)
{
if
len
(
req
.
Params
)
<
1
{
return
nil
,
NewErrorResponse
(
ErrorArguments
)
}
type
Message
struct
{
args
:=
new
(
GetCodeAtArgs
)
Call
string
`json:"call"`
r
:=
bytes
.
NewReader
(
req
.
Params
[
0
])
Args
[]
interface
{}
`json:"args"`
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
args
)
Id
int
`json:"_id"`
if
err
!=
nil
{
Data
interface
{}
`json:"data"`
return
nil
,
NewErrorResponse
(
ErrorDecodeArgs
)
}
jsonlogger
.
DebugDetailf
(
"%T %v"
,
args
,
args
)
return
args
,
nil
}
}
func
(
self
*
Message
)
Arguments
()
*
ethutil
.
Value
{
func
NewErrorResponse
(
msg
string
)
error
{
return
e
thutil
.
NewValue
(
self
.
Args
)
return
e
rrors
.
New
(
msg
)
}
}
rpc/packages.go
View file @
4c596809
/*
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/>.
*/
/*
For each request type, define the following:
1. RpcRequest "To" method [message.go], which does basic validation and conversion to "Args" type via json.Decoder()
2. json.Decoder() calls "UnmarshalJSON" defined on each "Args" struct
3. EthereumApi method, taking the "Args" type and replying with an interface to be marshalled to JSON
*/
package
rpc
package
rpc
import
(
import
(
"encoding/json"
"errors"
"math/big"
"math/big"
"strings"
"strings"
...
@@ -14,185 +37,57 @@ type EthereumApi struct {
...
@@ -14,185 +37,57 @@ type EthereumApi struct {
pipe
*
xeth
.
JSXEth
pipe
*
xeth
.
JSXEth
}
}
type
JsonArgs
interface
{
func
(
p
*
EthereumApi
)
GetBlock
(
args
*
GetBlockArgs
,
reply
*
interface
{})
error
{
requirements
()
error
}
type
BlockResponse
struct
{
JsonResponse
}
type
GetBlockArgs
struct
{
BlockNumber
int
Hash
string
}
type
ErrorResponse
struct
{
Error
bool
`json:"error"`
ErrorText
string
`json:"errorText"`
}
type
JsonResponse
interface
{
}
type
SuccessRes
struct
{
Error
bool
`json:"error"`
Result
JsonResponse
`json:"result"`
}
func
NewSuccessRes
(
object
JsonResponse
)
string
{
e
:=
SuccessRes
{
Error
:
false
,
Result
:
object
}
res
,
err
:=
json
.
Marshal
(
e
)
if
err
!=
nil
{
// This should never happen
panic
(
"Creating json error response failed, help"
)
}
success
:=
string
(
res
)
return
success
}
func
NewErrorResponse
(
msg
string
)
error
{
e
:=
ErrorResponse
{
Error
:
true
,
ErrorText
:
msg
}
res
,
err
:=
json
.
Marshal
(
e
)
if
err
!=
nil
{
// This should never happen
panic
(
"Creating json error response failed, help"
)
}
newErr
:=
errors
.
New
(
string
(
res
))
return
newErr
}
func
(
b
*
GetBlockArgs
)
requirements
()
error
{
if
b
.
BlockNumber
==
0
&&
b
.
Hash
==
""
{
return
NewErrorResponse
(
"GetBlock requires either a block 'number' or a block 'hash' as argument"
)
}
return
nil
}
func
(
p
*
EthereumApi
)
GetBlock
(
args
*
GetBlockArgs
,
reply
*
string
)
error
{
err
:=
args
.
requirements
()
err
:=
args
.
requirements
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
block
:=
p
.
pipe
.
BlockByHash
(
args
.
Hash
)
if
args
.
BlockNumber
>
0
{
*
reply
=
NewSuccessRes
(
block
)
*
reply
=
p
.
pipe
.
BlockByNumber
(
args
.
BlockNumber
)
return
nil
}
else
{
}
*
reply
=
p
.
pipe
.
BlockByHash
(
args
.
Hash
)
type
NewTxArgs
struct
{
Sec
string
Recipient
string
Value
string
Gas
string
GasPrice
string
Init
string
Body
string
}
type
TxResponse
struct
{
Hash
string
}
func
(
a
*
NewTxArgs
)
requirements
()
error
{
if
a
.
Recipient
==
""
{
return
NewErrorResponse
(
"Transact requires a 'recipient' address as argument"
)
}
if
a
.
Value
==
""
{
return
NewErrorResponse
(
"Transact requires a 'value' as argument"
)
}
if
a
.
Gas
==
""
{
return
NewErrorResponse
(
"Transact requires a 'gas' value as argument"
)
}
if
a
.
GasPrice
==
""
{
return
NewErrorResponse
(
"Transact requires a 'gasprice' value as argument"
)
}
return
nil
}
func
(
a
*
NewTxArgs
)
requirementsContract
()
error
{
if
a
.
Value
==
""
{
return
NewErrorResponse
(
"Create requires a 'value' as argument"
)
}
if
a
.
Gas
==
""
{
return
NewErrorResponse
(
"Create requires a 'gas' value as argument"
)
}
if
a
.
GasPrice
==
""
{
return
NewErrorResponse
(
"Create requires a 'gasprice' value as argument"
)
}
if
a
.
Body
==
""
{
return
NewErrorResponse
(
"Create requires a 'body' value as argument"
)
}
}
return
nil
return
nil
}
}
func
(
p
*
EthereumApi
)
Transact
(
args
*
NewTxArgs
,
reply
*
string
)
error
{
func
(
p
*
EthereumApi
)
Transact
(
args
*
NewTxArgs
,
reply
*
interface
{}
)
error
{
err
:=
args
.
requirements
()
err
:=
args
.
requirements
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
result
,
_
:=
p
.
pipe
.
Transact
(
p
.
pipe
.
Key
()
.
PrivateKey
,
args
.
Recipient
,
args
.
Value
,
args
.
Gas
,
args
.
GasPrice
,
args
.
Body
)
result
,
_
:=
p
.
pipe
.
Transact
(
p
.
pipe
.
Key
()
.
PrivateKey
,
args
.
Recipient
,
args
.
Value
,
args
.
Gas
,
args
.
GasPrice
,
args
.
Body
)
*
reply
=
NewSuccessRes
(
result
)
*
reply
=
result
return
nil
return
nil
}
}
func
(
p
*
EthereumApi
)
Create
(
args
*
NewTxArgs
,
reply
*
string
)
error
{
func
(
p
*
EthereumApi
)
Create
(
args
*
NewTxArgs
,
reply
*
interface
{}
)
error
{
err
:=
args
.
requirementsContract
()
err
:=
args
.
requirementsContract
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
result
,
_
:=
p
.
pipe
.
Transact
(
p
.
pipe
.
Key
()
.
PrivateKey
,
""
,
args
.
Value
,
args
.
Gas
,
args
.
GasPrice
,
args
.
Body
)
result
,
_
:=
p
.
pipe
.
Transact
(
p
.
pipe
.
Key
()
.
PrivateKey
,
""
,
args
.
Value
,
args
.
Gas
,
args
.
GasPrice
,
args
.
Body
)
*
reply
=
NewSuccessRes
(
result
)
*
reply
=
result
return
nil
}
type
PushTxArgs
struct
{
Tx
string
}
func
(
a
*
PushTxArgs
)
requirementsPushTx
()
error
{
if
a
.
Tx
==
""
{
return
NewErrorResponse
(
"PushTx requires a 'tx' as argument"
)
}
return
nil
return
nil
}
}
func
(
p
*
EthereumApi
)
PushTx
(
args
*
PushTxArgs
,
reply
*
string
)
error
{
func
(
p
*
EthereumApi
)
PushTx
(
args
*
PushTxArgs
,
reply
*
interface
{}
)
error
{
err
:=
args
.
requirementsPushTx
()
err
:=
args
.
requirementsPushTx
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
result
,
_
:=
p
.
pipe
.
PushTx
(
args
.
Tx
)
result
,
_
:=
p
.
pipe
.
PushTx
(
args
.
Tx
)
*
reply
=
NewSuccessRes
(
result
)
*
reply
=
result
return
nil
return
nil
}
}
func
(
p
*
EthereumApi
)
GetKey
(
args
interface
{},
reply
*
string
)
error
{
func
(
p
*
EthereumApi
)
GetKey
(
args
interface
{},
reply
*
interface
{}
)
error
{
*
reply
=
NewSuccessRes
(
p
.
pipe
.
Key
()
)
*
reply
=
p
.
pipe
.
Key
(
)
return
nil
return
nil
}
}
type
GetStorageArgs
struct
{
func
(
p
*
EthereumApi
)
GetStorageAt
(
args
*
GetStorageArgs
,
reply
*
interface
{})
error
{
Address
string
Key
string
}
func
(
a
*
GetStorageArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetStorageAt requires an 'address' value as argument"
)
}
if
a
.
Key
==
""
{
return
NewErrorResponse
(
"GetStorageAt requires an 'key' value as argument"
)
}
return
nil
}
type
GetStorageAtRes
struct
{
Key
string
`json:"key"`
Value
string
`json:"value"`
Address
string
`json:"address"`
}
func
(
p
*
EthereumApi
)
GetStorageAt
(
args
*
GetStorageArgs
,
reply
*
string
)
error
{
err
:=
args
.
requirements
()
err
:=
args
.
requirements
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -210,102 +105,104 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
...
@@ -210,102 +105,104 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *string) error {
}
}
jsonlogger
.
Debugf
(
"GetStorageAt(%s, %s)
\n
"
,
args
.
Address
,
hx
)
jsonlogger
.
Debugf
(
"GetStorageAt(%s, %s)
\n
"
,
args
.
Address
,
hx
)
value
:=
state
.
Storage
(
ethutil
.
Hex2Bytes
(
hx
))
value
:=
state
.
Storage
(
ethutil
.
Hex2Bytes
(
hx
))
*
reply
=
NewSuccessRes
(
GetStorageAtRes
{
Address
:
args
.
Address
,
Key
:
args
.
Key
,
Value
:
value
.
Str
()})
*
reply
=
GetStorageAtRes
{
Address
:
args
.
Address
,
Key
:
args
.
Key
,
Value
:
value
.
Str
()}
return
nil
return
nil
}
}
type
GetTxCountArgs
struct
{
func
(
p
*
EthereumApi
)
GetPeerCount
(
reply
*
interface
{})
error
{
Address
string
`json:"address"`
*
reply
=
p
.
pipe
.
PeerCount
()
}
type
GetTxCountRes
struct
{
Nonce
int
`json:"nonce"`
}
func
(
a
*
GetTxCountArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetTxCountAt requires an 'address' value as argument"
)
}
return
nil
return
nil
}
}
type
GetPeerCountRes
struct
{
func
(
p
*
EthereumApi
)
GetIsListening
(
reply
*
interface
{})
error
{
PeerCount
int
`json:"peerCount"`
*
reply
=
p
.
pipe
.
IsListening
()
}
func
(
p
*
EthereumApi
)
GetPeerCount
(
args
*
interface
{},
reply
*
string
)
error
{
*
reply
=
NewSuccessRes
(
GetPeerCountRes
{
PeerCount
:
p
.
pipe
.
PeerCount
()})
return
nil
return
nil
}
}
type
GetListeningRes
struct
{
func
(
p
*
EthereumApi
)
GetCoinbase
(
reply
*
interface
{})
error
{
IsListening
bool
`json:"isListening"`
*
reply
=
p
.
pipe
.
CoinBase
()
}
func
(
p
*
EthereumApi
)
GetIsListening
(
args
*
interface
{},
reply
*
string
)
error
{
*
reply
=
NewSuccessRes
(
GetListeningRes
{
IsListening
:
p
.
pipe
.
IsListening
()})
return
nil
return
nil
}
}
type
GetCoinbaseRes
struct
{
func
(
p
*
EthereumApi
)
GetIsMining
(
reply
*
interface
{})
error
{
Coinbase
string
`json:"coinbase"`
*
reply
=
p
.
pipe
.
IsMining
()
}
func
(
p
*
EthereumApi
)
GetCoinbase
(
args
*
interface
{},
reply
*
string
)
error
{
*
reply
=
NewSuccessRes
(
GetCoinbaseRes
{
Coinbase
:
p
.
pipe
.
CoinBase
()})
return
nil
return
nil
}
}
type
GetMiningRes
struct
{
func
(
p
*
EthereumApi
)
GetTxCountAt
(
args
*
GetTxCountArgs
,
reply
*
interface
{})
error
{
IsMining
bool
`json:"isMining"`
}
func
(
p
*
EthereumApi
)
GetIsMining
(
args
*
interface
{},
reply
*
string
)
error
{
*
reply
=
NewSuccessRes
(
GetMiningRes
{
IsMining
:
p
.
pipe
.
IsMining
()})
return
nil
}
func
(
p
*
EthereumApi
)
GetTxCountAt
(
args
*
GetTxCountArgs
,
reply
*
string
)
error
{
err
:=
args
.
requirements
()
err
:=
args
.
requirements
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
state
:=
p
.
pipe
.
TxCountAt
(
args
.
Address
)
*
reply
=
p
.
pipe
.
TxCountAt
(
args
.
Address
)
*
reply
=
NewSuccessRes
(
GetTxCountRes
{
Nonce
:
state
})
return
nil
}
type
GetBalanceArgs
struct
{
Address
string
}
func
(
a
*
GetBalanceArgs
)
requirements
()
error
{
if
a
.
Address
==
""
{
return
NewErrorResponse
(
"GetBalanceAt requires an 'address' value as argument"
)
}
return
nil
return
nil
}
}
type
BalanceRes
struct
{
func
(
p
*
EthereumApi
)
GetBalanceAt
(
args
*
GetBalanceArgs
,
reply
*
interface
{})
error
{
Balance
string
`json:"balance"`
Address
string
`json:"address"`
}
func
(
p
*
EthereumApi
)
GetBalanceAt
(
args
*
GetBalanceArgs
,
reply
*
string
)
error
{
err
:=
args
.
requirements
()
err
:=
args
.
requirements
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
state
:=
p
.
pipe
.
World
()
.
SafeGet
(
ethutil
.
Hex2Bytes
(
args
.
Address
))
state
:=
p
.
pipe
.
World
()
.
SafeGet
(
ethutil
.
Hex2Bytes
(
args
.
Address
))
*
reply
=
NewSuccessRes
(
BalanceRes
{
Balance
:
state
.
Balance
()
.
String
(),
Address
:
args
.
Address
})
*
reply
=
BalanceRes
{
Balance
:
state
.
Balance
()
.
String
(),
Address
:
args
.
Address
}
return
nil
return
nil
}
}
type
TestRes
struct
{
func
(
p
*
EthereumApi
)
GetCodeAt
(
args
*
GetCodeAtArgs
,
reply
*
interface
{})
error
{
JsonResponse
`json:"-"`
err
:=
args
.
requirements
()
Answer
int
`json:"answer"`
if
err
!=
nil
{
}
return
err
}
func
(
p
*
EthereumApi
)
Test
(
args
*
GetBlockArgs
,
reply
*
string
)
error
{
*
reply
=
p
.
pipe
.
CodeAt
(
args
.
Address
)
*
reply
=
NewSuccessRes
(
TestRes
{
Answer
:
15
})
return
nil
}
func
(
p
*
EthereumApi
)
GetRequestReply
(
req
*
RpcRequest
,
reply
*
interface
{})
error
{
// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
jsonlogger
.
DebugDetailf
(
"%T %s"
,
req
.
Params
,
req
.
Params
)
switch
req
.
Method
{
case
"eth_coinbase"
:
return
p
.
GetCoinbase
(
reply
)
case
"eth_listening"
:
return
p
.
GetIsListening
(
reply
)
case
"eth_mining"
:
return
p
.
GetIsMining
(
reply
)
case
"eth_peerCount"
:
return
p
.
GetPeerCount
(
reply
)
case
"eth_countAt"
:
args
,
err
:=
req
.
ToGetTxCountArgs
()
if
err
!=
nil
{
return
err
}
return
p
.
GetTxCountAt
(
args
,
reply
)
case
"eth_codeAt"
:
args
,
err
:=
req
.
ToGetCodeAtArgs
()
if
err
!=
nil
{
return
err
}
return
p
.
GetCodeAt
(
args
,
reply
)
case
"eth_balanceAt"
:
args
,
err
:=
req
.
ToGetBalanceArgs
()
if
err
!=
nil
{
return
err
}
return
p
.
GetBalanceAt
(
args
,
reply
)
case
"eth_stateAt"
:
args
,
err
:=
req
.
ToGetStorageArgs
()
if
err
!=
nil
{
return
err
}
return
p
.
GetStorageAt
(
args
,
reply
)
case
"eth_blockByNumber"
,
"eth_blockByHash"
:
args
,
err
:=
req
.
ToGetBlockArgs
()
if
err
!=
nil
{
return
err
}
return
p
.
GetBlock
(
args
,
reply
)
default
:
return
NewErrorResponse
(
ErrorNotImplemented
)
}
jsonlogger
.
DebugDetailf
(
"Reply: %T %s"
,
reply
,
reply
)
return
nil
return
nil
}
}
rpc/server.go
View file @
4c596809
/*
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
package
rpc
import
(
import
(
"fmt"
"fmt"
"net"
"net"
"net/rpc"
"net/http"
"net/rpc/jsonrpc"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/xeth"
"github.com/ethereum/go-ethereum/xeth"
...
@@ -38,17 +53,14 @@ func (s *JsonRpcServer) Stop() {
...
@@ -38,17 +53,14 @@ func (s *JsonRpcServer) Stop() {
func
(
s
*
JsonRpcServer
)
Start
()
{
func
(
s
*
JsonRpcServer
)
Start
()
{
jsonlogger
.
Infoln
(
"Starting JSON-RPC server"
)
jsonlogger
.
Infoln
(
"Starting JSON-RPC server"
)
go
s
.
exitHandler
()
go
s
.
exitHandler
()
rpc
.
Register
(
&
EthereumApi
{
pipe
:
s
.
pipe
})
rpc
.
HandleHTTP
()
for
{
h
:=
apiHandler
(
&
EthereumApi
{
pipe
:
s
.
pipe
})
conn
,
err
:=
s
.
listener
.
Accept
()
http
.
Handle
(
"/"
,
h
)
if
err
!=
nil
{
jsonlogger
.
Infoln
(
"Error starting JSON-RPC:"
,
err
)
err
:=
http
.
Serve
(
s
.
listener
,
nil
)
break
// FIX Complains on shutdown due to listner already being closed
}
if
err
!=
nil
{
jsonlogger
.
Debugln
(
"Incoming request."
)
jsonlogger
.
Errorln
(
"Error on JSON-RPC interface:"
,
err
)
go
jsonrpc
.
ServeConn
(
conn
)
}
}
}
}
...
@@ -65,3 +77,28 @@ func NewJsonRpcServer(pipe *xeth.JSXEth, port int) (*JsonRpcServer, error) {
...
@@ -65,3 +77,28 @@ func NewJsonRpcServer(pipe *xeth.JSXEth, port int) (*JsonRpcServer, error) {
pipe
:
pipe
,
pipe
:
pipe
,
},
nil
},
nil
}
}
func
apiHandler
(
xeth
*
EthereumApi
)
http
.
Handler
{
fn
:=
func
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
jsonlogger
.
Debugln
(
"Handling request"
)
reqParsed
,
reqerr
:=
JSON
.
ParseRequestBody
(
req
)
if
reqerr
!=
nil
{
JSON
.
Send
(
w
,
&
RpcErrorResponse
{
JsonRpc
:
reqParsed
.
JsonRpc
,
ID
:
reqParsed
.
ID
,
Error
:
true
,
ErrorText
:
ErrorParseRequest
})
return
}
var
response
interface
{}
reserr
:=
xeth
.
GetRequestReply
(
&
reqParsed
,
&
response
)
if
reserr
!=
nil
{
jsonlogger
.
Errorln
(
reserr
)
JSON
.
Send
(
w
,
&
RpcErrorResponse
{
JsonRpc
:
reqParsed
.
JsonRpc
,
ID
:
reqParsed
.
ID
,
Error
:
true
,
ErrorText
:
reserr
.
Error
()})
return
}
jsonlogger
.
Debugf
(
"Generated response: %T %s"
,
response
,
response
)
JSON
.
Send
(
w
,
&
RpcSuccessResponse
{
JsonRpc
:
reqParsed
.
JsonRpc
,
ID
:
reqParsed
.
ID
,
Error
:
false
,
Result
:
response
})
}
return
http
.
HandlerFunc
(
fn
)
}
rpc/writer.go
deleted
100644 → 0
View file @
f3e78c8f
package
rpc
/*
func pack(id int, v ...interface{}) Message {
return Message{Data: v, Id: id}
}
func WriteOn(msg *Message, writer io.Writer) {
//msg := &Message{Seed: seed, Data: data}
switch msg.Call {
case "compile":
data := ethutil.NewValue(msg.Args)
bcode, err := ethutil.Compile(data.Get(0).Str(), false)
if err != nil {
JSON.Send(writer, pack(msg.Id, err.Error()))
}
code := ethutil.Bytes2Hex(bcode)
JSON.Send(writer, pack(msg.Id, code, nil))
case "block":
args := msg.Arguments()
block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
JSON.Send(writer, pack(msg.Id, block))
case "transact":
if mp, ok := msg.Args[0].(map[string]interface{}); ok {
object := mapToTxParams(mp)
JSON.Send(
writer,
pack(msg.Id, args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"]))),
)
}
case "coinbase":
JSON.Send(writer, pack(msg.Id, pipe.CoinBase(), msg.Seed))
case "listening":
JSON.Send(writer, pack(msg.Id, pipe.IsListening()))
case "mining":
JSON.Send(writer, pack(msg.Id, pipe.IsMining()))
case "peerCoint":
JSON.Send(writer, pack(msg.Id, pipe.PeerCount()))
case "countAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.TxCountAt(args.Get(0).Str())))
case "codeAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, len(pipe.CodeAt(args.Get(0).Str()))))
case "stateAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str())))
case "balanceAt":
args := msg.Arguments()
JSON.Send(writer, pack(msg.Id, pipe.BalanceAt(args.Get(0).Str())))
case "newFilter":
case "newFilterString":
case "messages":
// TODO
}
}
*/
tests/vm/gh_test.go
View file @
4c596809
...
@@ -172,47 +172,47 @@ func RunVmTest(p string, t *testing.T) {
...
@@ -172,47 +172,47 @@ func RunVmTest(p string, t *testing.T) {
// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail.
// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail.
func
TestVMArithmetic
(
t
*
testing
.
T
)
{
func
TestVMArithmetic
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmArithmeticTest.json"
const
fn
=
"../files/
VMT
ests/vmArithmeticTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestBitwiseLogicOperation
(
t
*
testing
.
T
)
{
func
TestBitwiseLogicOperation
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmBitwiseLogicOperationTest.json"
const
fn
=
"../files/
VMT
ests/vmBitwiseLogicOperationTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestBlockInfo
(
t
*
testing
.
T
)
{
func
TestBlockInfo
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmBlockInfoTest.json"
const
fn
=
"../files/
VMT
ests/vmBlockInfoTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestEnvironmentalInfo
(
t
*
testing
.
T
)
{
func
TestEnvironmentalInfo
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmEnvironmentalInfoTest.json"
const
fn
=
"../files/
VMT
ests/vmEnvironmentalInfoTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestFlowOperation
(
t
*
testing
.
T
)
{
func
TestFlowOperation
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmIOandFlowOperationsTest.json"
const
fn
=
"../files/
VMT
ests/vmIOandFlowOperationsTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestPushDupSwap
(
t
*
testing
.
T
)
{
func
TestPushDupSwap
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmPushDupSwapTest.json"
const
fn
=
"../files/
VMT
ests/vmPushDupSwapTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestVMSha3
(
t
*
testing
.
T
)
{
func
TestVMSha3
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmSha3Test.json"
const
fn
=
"../files/
VMT
ests/vmSha3Test.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestVm
(
t
*
testing
.
T
)
{
func
TestVm
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmtests.json"
const
fn
=
"../files/
VMT
ests/vmtests.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
func
TestVmLog
(
t
*
testing
.
T
)
{
func
TestVmLog
(
t
*
testing
.
T
)
{
const
fn
=
"../files/
vmt
ests/vmLogTest.json"
const
fn
=
"../files/
VMT
ests/vmLogTest.json"
RunVmTest
(
fn
,
t
)
RunVmTest
(
fn
,
t
)
}
}
...
...
vm/vm_jit.go
View file @
4c596809
// +build evmjit
package
vm
package
vm
import
"math/big"
/*
void* evmjit_create();
int evmjit_run(void* _jit, void* _data, void* _env);
void evmjit_destroy(void* _jit);
// Shared library evmjit (e.g. libevmjit.so) is expected to be installed in /usr/local/lib
// More: https://github.com/ethereum/evmjit
#cgo LDFLAGS: -levmjit
*/
import
"C"
import
(
"bytes"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/state"
"math/big"
"unsafe"
)
type
JitVm
struct
{
type
JitVm
struct
{
env
Environment
env
Environment
backup
*
Vm
me
ContextRef
callerAddr
[]
byte
price
*
big
.
Int
data
RuntimeData
}
type
i256
[
32
]
byte
type
RuntimeData
struct
{
gas
int64
gasPrice
int64
callData
*
byte
callDataSize
uint64
address
i256
caller
i256
origin
i256
callValue
i256
coinBase
i256
difficulty
i256
gasLimit
i256
number
uint64
timestamp
int64
code
*
byte
codeSize
uint64
}
func
hash2llvm
(
h
[]
byte
)
i256
{
var
m
i256
copy
(
m
[
len
(
m
)
-
len
(
h
)
:
],
h
)
// right aligned copy
return
m
}
func
llvm2hash
(
m
*
i256
)
[]
byte
{
return
C
.
GoBytes
(
unsafe
.
Pointer
(
m
),
C
.
int
(
len
(
m
)))
}
func
llvm2hashRef
(
m
*
i256
)
[]
byte
{
return
(
*
[
1
<<
30
]
byte
)(
unsafe
.
Pointer
(
m
))[
:
len
(
m
)
:
len
(
m
)]
}
func
address2llvm
(
addr
[]
byte
)
i256
{
n
:=
hash2llvm
(
addr
)
bswap
(
&
n
)
return
n
}
// bswap swap bytes of the 256-bit integer on LLVM side
// TODO: Do not change memory on LLVM side, that can conflict with memory access optimizations
func
bswap
(
m
*
i256
)
*
i256
{
for
i
,
l
:=
0
,
len
(
m
);
i
<
l
/
2
;
i
++
{
m
[
i
],
m
[
l
-
i
-
1
]
=
m
[
l
-
i
-
1
],
m
[
i
]
}
return
m
}
func
trim
(
m
[]
byte
)
[]
byte
{
skip
:=
0
for
i
:=
0
;
i
<
len
(
m
);
i
++
{
if
m
[
i
]
==
0
{
skip
++
}
else
{
break
}
}
return
m
[
skip
:
]
}
func
getDataPtr
(
m
[]
byte
)
*
byte
{
var
p
*
byte
if
len
(
m
)
>
0
{
p
=
&
m
[
0
]
}
return
p
}
func
big2llvm
(
n
*
big
.
Int
)
i256
{
m
:=
hash2llvm
(
n
.
Bytes
())
bswap
(
&
m
)
return
m
}
func
llvm2big
(
m
*
i256
)
*
big
.
Int
{
n
:=
big
.
NewInt
(
0
)
for
i
:=
0
;
i
<
len
(
m
);
i
++
{
b
:=
big
.
NewInt
(
int64
(
m
[
i
]))
b
.
Lsh
(
b
,
uint
(
i
)
*
8
)
n
.
Add
(
n
,
b
)
}
return
n
}
// llvm2bytesRef creates a []byte slice that references byte buffer on LLVM side (as of that not controller by GC)
// User must asure that referenced memory is available to Go until the data is copied or not needed any more
func
llvm2bytesRef
(
data
*
byte
,
length
uint64
)
[]
byte
{
if
length
==
0
{
return
nil
}
if
data
==
nil
{
panic
(
"Unexpected nil data pointer"
)
}
return
(
*
[
1
<<
30
]
byte
)(
unsafe
.
Pointer
(
data
))[
:
length
:
length
]
}
func
untested
(
condition
bool
,
message
string
)
{
if
condition
{
panic
(
"Condition `"
+
message
+
"` tested. Remove assert."
)
}
}
func
assert
(
condition
bool
,
message
string
)
{
if
!
condition
{
panic
(
"Assert `"
+
message
+
"` failed!"
)
}
}
}
func
NewJitVm
(
env
Environment
)
*
JitVm
{
func
NewJitVm
(
env
Environment
)
*
JitVm
{
backupVm
:=
New
(
env
)
return
&
JitVm
{
env
:
env
}
return
&
JitVm
{
env
:
env
,
backup
:
backupVm
}
}
}
func
(
self
*
JitVm
)
Run
(
me
,
caller
ContextRef
,
code
[]
byte
,
value
,
gas
,
price
*
big
.
Int
,
callData
[]
byte
)
(
ret
[]
byte
,
err
error
)
{
func
(
self
*
JitVm
)
Run
(
me
,
caller
ContextRef
,
code
[]
byte
,
value
,
gas
,
price
*
big
.
Int
,
callData
[]
byte
)
(
ret
[]
byte
,
err
error
)
{
return
self
.
backup
.
Run
(
me
,
caller
,
code
,
value
,
gas
,
price
,
callData
)
// TODO: depth is increased but never checked by VM. VM should not know about it at all.
self
.
env
.
SetDepth
(
self
.
env
.
Depth
()
+
1
)
// TODO: Move it to Env.Call() or sth
if
Precompiled
[
string
(
me
.
Address
())]
!=
nil
{
// if it's address of precopiled contract
// fallback to standard VM
stdVm
:=
New
(
self
.
env
)
return
stdVm
.
Run
(
me
,
caller
,
code
,
value
,
gas
,
price
,
callData
)
}
if
self
.
me
!=
nil
{
panic
(
"JitVm.Run() can be called only once per JitVm instance"
)
}
self
.
me
=
me
self
.
callerAddr
=
caller
.
Address
()
self
.
price
=
price
self
.
data
.
gas
=
gas
.
Int64
()
self
.
data
.
gasPrice
=
price
.
Int64
()
self
.
data
.
callData
=
getDataPtr
(
callData
)
self
.
data
.
callDataSize
=
uint64
(
len
(
callData
))
self
.
data
.
address
=
address2llvm
(
self
.
me
.
Address
())
self
.
data
.
caller
=
address2llvm
(
caller
.
Address
())
self
.
data
.
origin
=
address2llvm
(
self
.
env
.
Origin
())
self
.
data
.
callValue
=
big2llvm
(
value
)
self
.
data
.
coinBase
=
address2llvm
(
self
.
env
.
Coinbase
())
self
.
data
.
difficulty
=
big2llvm
(
self
.
env
.
Difficulty
())
self
.
data
.
gasLimit
=
big2llvm
(
self
.
env
.
GasLimit
())
self
.
data
.
number
=
self
.
env
.
BlockNumber
()
.
Uint64
()
self
.
data
.
timestamp
=
self
.
env
.
Time
()
self
.
data
.
code
=
getDataPtr
(
code
)
self
.
data
.
codeSize
=
uint64
(
len
(
code
))
jit
:=
C
.
evmjit_create
()
retCode
:=
C
.
evmjit_run
(
jit
,
unsafe
.
Pointer
(
&
self
.
data
),
unsafe
.
Pointer
(
self
))
if
retCode
<
0
{
err
=
errors
.
New
(
"OOG from JIT"
)
gas
.
SetInt64
(
0
)
// Set gas to 0, JIT does not bother
}
else
{
gas
.
SetInt64
(
self
.
data
.
gas
)
if
retCode
==
1
{
// RETURN
ret
=
C
.
GoBytes
(
unsafe
.
Pointer
(
self
.
data
.
callData
),
C
.
int
(
self
.
data
.
callDataSize
))
}
else
if
retCode
==
2
{
// SUICIDE
// TODO: Suicide support logic should be moved to Env to be shared by VM implementations
state
:=
self
.
Env
()
.
State
()
receiverAddr
:=
llvm2hashRef
(
bswap
(
&
self
.
data
.
address
))
receiver
:=
state
.
GetOrNewStateObject
(
receiverAddr
)
balance
:=
state
.
GetBalance
(
me
.
Address
())
receiver
.
AddAmount
(
balance
)
state
.
Delete
(
me
.
Address
())
}
}
C
.
evmjit_destroy
(
jit
);
return
}
}
func
(
self
*
JitVm
)
Printf
(
format
string
,
v
...
interface
{})
VirtualMachine
{
func
(
self
*
JitVm
)
Printf
(
format
string
,
v
...
interface
{})
VirtualMachine
{
return
self
.
backup
.
Printf
(
format
,
v
)
return
self
}
}
func
(
self
*
JitVm
)
Endl
()
VirtualMachine
{
func
(
self
*
JitVm
)
Endl
()
VirtualMachine
{
return
self
.
backup
.
Endl
()
return
self
}
}
func
(
self
*
JitVm
)
Env
()
Environment
{
func
(
self
*
JitVm
)
Env
()
Environment
{
return
self
.
env
return
self
.
env
}
}
//go is nice
//export env_sha3
func
env_sha3
(
dataPtr
*
byte
,
length
uint64
,
resultPtr
unsafe
.
Pointer
)
{
data
:=
llvm2bytesRef
(
dataPtr
,
length
)
hash
:=
crypto
.
Sha3
(
data
)
result
:=
(
*
i256
)(
resultPtr
)
*
result
=
hash2llvm
(
hash
)
}
//export env_sstore
func
env_sstore
(
vmPtr
unsafe
.
Pointer
,
indexPtr
unsafe
.
Pointer
,
valuePtr
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
vmPtr
)
index
:=
llvm2hash
(
bswap
((
*
i256
)(
indexPtr
)))
value
:=
llvm2hash
(
bswap
((
*
i256
)(
valuePtr
)))
value
=
trim
(
value
)
if
len
(
value
)
==
0
{
prevValue
:=
vm
.
env
.
State
()
.
GetState
(
vm
.
me
.
Address
(),
index
)
if
len
(
prevValue
)
!=
0
{
vm
.
Env
()
.
State
()
.
Refund
(
vm
.
callerAddr
,
GasSStoreRefund
)
}
}
vm
.
env
.
State
()
.
SetState
(
vm
.
me
.
Address
(),
index
,
value
)
}
//export env_sload
func
env_sload
(
vmPtr
unsafe
.
Pointer
,
indexPtr
unsafe
.
Pointer
,
resultPtr
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
vmPtr
)
index
:=
llvm2hash
(
bswap
((
*
i256
)(
indexPtr
)))
value
:=
vm
.
env
.
State
()
.
GetState
(
vm
.
me
.
Address
(),
index
)
result
:=
(
*
i256
)(
resultPtr
)
*
result
=
hash2llvm
(
value
)
bswap
(
result
)
}
//export env_balance
func
env_balance
(
_vm
unsafe
.
Pointer
,
_addr
unsafe
.
Pointer
,
_result
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
_vm
)
addr
:=
llvm2hash
((
*
i256
)(
_addr
))
balance
:=
vm
.
Env
()
.
State
()
.
GetBalance
(
addr
)
result
:=
(
*
i256
)(
_result
)
*
result
=
big2llvm
(
balance
)
}
//export env_blockhash
func
env_blockhash
(
_vm
unsafe
.
Pointer
,
_number
unsafe
.
Pointer
,
_result
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
_vm
)
number
:=
llvm2big
((
*
i256
)(
_number
))
result
:=
(
*
i256
)(
_result
)
currNumber
:=
vm
.
Env
()
.
BlockNumber
()
limit
:=
big
.
NewInt
(
0
)
.
Sub
(
currNumber
,
big
.
NewInt
(
256
))
if
number
.
Cmp
(
limit
)
>=
0
&&
number
.
Cmp
(
currNumber
)
<
0
{
hash
:=
vm
.
Env
()
.
GetHash
(
uint64
(
number
.
Int64
()))
*
result
=
hash2llvm
(
hash
)
}
else
{
*
result
=
i256
{}
}
}
//export env_call
func
env_call
(
_vm
unsafe
.
Pointer
,
_gas
unsafe
.
Pointer
,
_receiveAddr
unsafe
.
Pointer
,
_value
unsafe
.
Pointer
,
inDataPtr
unsafe
.
Pointer
,
inDataLen
uint64
,
outDataPtr
*
byte
,
outDataLen
uint64
,
_codeAddr
unsafe
.
Pointer
)
bool
{
vm
:=
(
*
JitVm
)(
_vm
)
//fmt.Printf("env_call (depth %d)\n", vm.Env().Depth())
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
fmt
.
Printf
(
"Recovered in env_call (depth %d, out %p %d): %s
\n
"
,
vm
.
Env
()
.
Depth
(),
outDataPtr
,
outDataLen
,
r
)
}
}()
balance
:=
vm
.
Env
()
.
State
()
.
GetBalance
(
vm
.
me
.
Address
())
value
:=
llvm2big
((
*
i256
)(
_value
))
if
balance
.
Cmp
(
value
)
>=
0
{
receiveAddr
:=
llvm2hash
((
*
i256
)(
_receiveAddr
))
inData
:=
C
.
GoBytes
(
inDataPtr
,
C
.
int
(
inDataLen
))
outData
:=
llvm2bytesRef
(
outDataPtr
,
outDataLen
)
codeAddr
:=
llvm2hash
((
*
i256
)(
_codeAddr
))
llvmGas
:=
(
*
i256
)(
_gas
)
gas
:=
llvm2big
(
llvmGas
)
var
out
[]
byte
var
err
error
if
bytes
.
Equal
(
codeAddr
,
receiveAddr
)
{
out
,
err
=
vm
.
env
.
Call
(
vm
.
me
,
codeAddr
,
inData
,
gas
,
vm
.
price
,
value
)
}
else
{
out
,
err
=
vm
.
env
.
CallCode
(
vm
.
me
,
codeAddr
,
inData
,
gas
,
vm
.
price
,
value
)
}
*
llvmGas
=
big2llvm
(
gas
)
if
err
==
nil
{
copy
(
outData
,
out
)
return
true
}
}
return
false
}
//export env_create
func
env_create
(
_vm
unsafe
.
Pointer
,
_gas
unsafe
.
Pointer
,
_value
unsafe
.
Pointer
,
initDataPtr
unsafe
.
Pointer
,
initDataLen
uint64
,
_result
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
_vm
)
value
:=
llvm2big
((
*
i256
)(
_value
))
initData
:=
C
.
GoBytes
(
initDataPtr
,
C
.
int
(
initDataLen
))
// TODO: Unnecessary if low balance
result
:=
(
*
i256
)(
_result
)
*
result
=
i256
{}
llvmGas
:=
(
*
i256
)(
_gas
)
gas
:=
llvm2big
(
llvmGas
)
ret
,
suberr
,
ref
:=
vm
.
env
.
Create
(
vm
.
me
,
nil
,
initData
,
gas
,
vm
.
price
,
value
)
if
suberr
==
nil
{
dataGas
:=
big
.
NewInt
(
int64
(
len
(
ret
)))
// TODO: Nto the best design. env.Create can do it, it has the reference to gas counter
dataGas
.
Mul
(
dataGas
,
GasCreateByte
)
gas
.
Sub
(
gas
,
dataGas
)
*
result
=
hash2llvm
(
ref
.
Address
())
}
*
llvmGas
=
big2llvm
(
gas
)
}
//export env_log
func
env_log
(
_vm
unsafe
.
Pointer
,
dataPtr
unsafe
.
Pointer
,
dataLen
uint64
,
_topic1
unsafe
.
Pointer
,
_topic2
unsafe
.
Pointer
,
_topic3
unsafe
.
Pointer
,
_topic4
unsafe
.
Pointer
)
{
vm
:=
(
*
JitVm
)(
_vm
)
data
:=
C
.
GoBytes
(
dataPtr
,
C
.
int
(
dataLen
))
topics
:=
make
([][]
byte
,
0
,
4
)
if
_topic1
!=
nil
{
topics
=
append
(
topics
,
llvm2hash
((
*
i256
)(
_topic1
)))
}
if
_topic2
!=
nil
{
topics
=
append
(
topics
,
llvm2hash
((
*
i256
)(
_topic2
)))
}
if
_topic3
!=
nil
{
topics
=
append
(
topics
,
llvm2hash
((
*
i256
)(
_topic3
)))
}
if
_topic4
!=
nil
{
topics
=
append
(
topics
,
llvm2hash
((
*
i256
)(
_topic4
)))
}
vm
.
Env
()
.
AddLog
(
state
.
NewLog
(
vm
.
me
.
Address
(),
topics
,
data
))
}
//export env_extcode
func
env_extcode
(
_vm
unsafe
.
Pointer
,
_addr
unsafe
.
Pointer
,
o_size
*
uint64
)
*
byte
{
vm
:=
(
*
JitVm
)(
_vm
)
addr
:=
llvm2hash
((
*
i256
)(
_addr
))
code
:=
vm
.
Env
()
.
State
()
.
GetCode
(
addr
)
*
o_size
=
uint64
(
len
(
code
))
return
getDataPtr
(
code
)
}
vm/vm_jit_fake.go
0 → 100644
View file @
4c596809
// +build !evmjit
package
vm
import
"fmt"
func
NewJitVm
(
env
Environment
)
VirtualMachine
{
fmt
.
Printf
(
"Warning! EVM JIT not enabled.
\n
"
)
return
New
(
env
)
}
cmd/utils/websockets
.go
→
websocket/util
.go
View file @
4c596809
/*
/*
This file is part of go-ethereum
This file is part of go-ethereum
go-ethereum is free software: you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
go-ethereum is distributed in the hope that it will be useful,
go-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
*/
/**
package
websocket
* @authors
* Jeffrey Wilcke <i@jev.io>
*/
package
utils
import
(
import
(
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
...
@@ -26,15 +22,11 @@ import (
...
@@ -26,15 +22,11 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/websocket"
"github.com/ethereum/go-ethereum/xeth"
"github.com/ethereum/go-ethereum/xeth"
)
)
var
wslogger
=
logger
.
NewLogger
(
"WS"
)
func
args
(
v
...
interface
{})
[]
interface
{}
{
func
args
(
v
...
interface
{})
[]
interface
{}
{
return
v
return
v
}
}
...
@@ -54,8 +46,8 @@ func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
...
@@ -54,8 +46,8 @@ func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
func
(
self
*
WebSocketServer
)
Serv
()
{
func
(
self
*
WebSocketServer
)
Serv
()
{
pipe
:=
xeth
.
NewJSXEth
(
self
.
eth
)
pipe
:=
xeth
.
NewJSXEth
(
self
.
eth
)
wsServ
:=
websocket
.
NewServer
(
"/eth"
,
":40404"
)
wsServ
:=
NewServer
(
"/eth"
,
":40404"
)
wsServ
.
MessageFunc
(
func
(
c
*
websocket
.
Client
,
msg
*
websocket
.
Message
)
{
wsServ
.
MessageFunc
(
func
(
c
*
Client
,
msg
*
Message
)
{
switch
msg
.
Call
{
switch
msg
.
Call
{
case
"compile"
:
case
"compile"
:
data
:=
ethutil
.
NewValue
(
msg
.
Args
)
data
:=
ethutil
.
NewValue
(
msg
.
Args
)
...
@@ -162,13 +154,6 @@ func toMessages(messages state.Messages) (msgs []xeth.JSMessage) {
...
@@ -162,13 +154,6 @@ func toMessages(messages state.Messages) (msgs []xeth.JSMessage) {
return
return
}
}
func
StartWebSockets
(
eth
*
eth
.
Ethereum
)
{
wslogger
.
Infoln
(
"Starting WebSockets"
)
sock
:=
NewWebSocketServer
(
eth
)
go
sock
.
Serv
()
}
// TODO This is starting to become a generic method. Move to utils
// TODO This is starting to become a generic method. Move to utils
func
mapToTxParams
(
object
map
[
string
]
interface
{})
map
[
string
]
string
{
func
mapToTxParams
(
object
map
[
string
]
interface
{})
map
[
string
]
string
{
// Default values
// Default values
...
...
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