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
28b14d3e
Commit
28b14d3e
authored
Aug 13, 2015
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1635 from bas-vk/useragent
support for user agents
parents
73c4e600
f9cbd16f
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
361 additions
and
88 deletions
+361
-88
js.go
cmd/geth/js.go
+3
-7
main.go
cmd/geth/main.go
+1
-1
flags.go
cmd/utils/flags.go
+16
-9
admin.go
rpc/api/admin.go
+9
-0
net.go
rpc/api/net.go
+1
-2
personal.go
rpc/api/personal.go
+11
-11
personal_args.go
rpc/api/personal_args.go
+15
-7
shh_js.go
rpc/api/shh_js.go
+0
-0
codec.go
rpc/codec/codec.go
+2
-0
json.go
rpc/codec/json.go
+23
-16
comms.go
rpc/comms/comms.go
+1
-1
inproc.go
rpc/comms/inproc.go
+1
-1
ipc.go
rpc/comms/ipc.go
+9
-26
ipc_unix.go
rpc/comms/ipc_unix.go
+8
-1
ipc_windows.go
rpc/comms/ipc_windows.go
+8
-1
jeth.go
rpc/jeth.go
+84
-5
agent.go
rpc/useragent/agent.go
+24
-0
remote_frontend.go
rpc/useragent/remote_frontend.go
+141
-0
xeth.go
xeth/xeth.go
+4
-0
No files found.
cmd/geth/js.go
View file @
28b14d3e
...
...
@@ -145,19 +145,15 @@ func apiWordCompleter(line string, pos int) (head string, completions []string,
return
begin
,
completionWords
,
end
}
func
newLightweightJSRE
(
libPath
string
,
client
comms
.
EthereumClient
,
interactive
bool
,
f
xeth
.
Frontend
)
*
jsre
{
func
newLightweightJSRE
(
libPath
string
,
client
comms
.
EthereumClient
,
interactive
bool
)
*
jsre
{
js
:=
&
jsre
{
ps1
:
"> "
}
js
.
wait
=
make
(
chan
*
big
.
Int
)
js
.
client
=
client
js
.
ds
=
docserver
.
New
(
"/"
)
if
f
==
nil
{
f
=
js
}
// update state in separare forever blocks
js
.
re
=
re
.
New
(
libPath
)
if
err
:=
js
.
apiBindings
(
f
);
err
!=
nil
{
if
err
:=
js
.
apiBindings
(
js
);
err
!=
nil
{
utils
.
Fatalf
(
"Unable to initialize console - %v"
,
err
)
}
...
...
@@ -291,7 +287,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
utils
.
Fatalf
(
"Unable to determine supported api's: %v"
,
err
)
}
jeth
:=
rpc
.
NewJeth
(
api
.
Merge
(
apiImpl
...
),
js
.
re
,
js
.
client
)
jeth
:=
rpc
.
NewJeth
(
api
.
Merge
(
apiImpl
...
),
js
.
re
,
js
.
client
,
f
)
js
.
re
.
Set
(
"jeth"
,
struct
{}{})
t
,
_
:=
js
.
re
.
Get
(
"jeth"
)
jethObj
:=
t
.
Object
()
...
...
cmd/geth/main.go
View file @
28b14d3e
...
...
@@ -425,7 +425,7 @@ func attach(ctx *cli.Context) {
ctx
.
GlobalString
(
utils
.
JSpathFlag
.
Name
),
client
,
true
,
nil
)
)
if
ctx
.
GlobalString
(
utils
.
ExecFlag
.
Name
)
!=
""
{
repl
.
batch
(
ctx
.
GlobalString
(
utils
.
ExecFlag
.
Name
))
...
...
cmd/utils/flags.go
View file @
28b14d3e
...
...
@@ -21,30 +21,32 @@ import (
"fmt"
"log"
"math/big"
"net"
"net/http"
"os"
"path/filepath"
"runtime"
"strconv"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/metrics"
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth"
)
...
...
@@ -518,15 +520,20 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
Endpoint
:
IpcSocketPath
(
ctx
),
}
xeth
:=
xeth
.
New
(
eth
,
nil
)
codec
:=
codec
.
JSON
initializer
:=
func
(
conn
net
.
Conn
)
(
shared
.
EthereumApi
,
error
)
{
fe
:=
useragent
.
NewRemoteFrontend
(
conn
,
eth
.
AccountManager
())
xeth
:=
xeth
.
New
(
eth
,
fe
)
codec
:=
codec
.
JSON
apis
,
err
:=
api
.
ParseApiString
(
ctx
.
GlobalString
(
IPCApiFlag
.
Name
),
codec
,
xeth
,
eth
)
if
err
!=
nil
{
return
err
apis
,
err
:=
api
.
ParseApiString
(
ctx
.
GlobalString
(
IPCApiFlag
.
Name
),
codec
,
xeth
,
eth
)
if
err
!=
nil
{
return
nil
,
err
}
return
api
.
Merge
(
apis
...
),
nil
}
return
comms
.
StartIpc
(
config
,
codec
,
api
.
Merge
(
apis
...
)
)
return
comms
.
StartIpc
(
config
,
codec
.
JSON
,
initializer
)
}
func
StartRPC
(
eth
*
eth
.
Ethereum
,
ctx
*
cli
.
Context
)
error
{
...
...
rpc/api/admin.go
View file @
28b14d3e
...
...
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth"
)
...
...
@@ -71,6 +72,7 @@ var (
"admin_httpGet"
:
(
*
adminApi
)
.
HttpGet
,
"admin_sleepBlocks"
:
(
*
adminApi
)
.
SleepBlocks
,
"admin_sleep"
:
(
*
adminApi
)
.
Sleep
,
"admin_enableUserAgent"
:
(
*
adminApi
)
.
EnableUserAgent
,
}
)
...
...
@@ -474,3 +476,10 @@ func (self *adminApi) HttpGet(req *shared.Request) (interface{}, error) {
return
string
(
resp
),
nil
}
func
(
self
*
adminApi
)
EnableUserAgent
(
req
*
shared
.
Request
)
(
interface
{},
error
)
{
if
fe
,
ok
:=
self
.
xeth
.
Frontend
()
.
(
*
useragent
.
RemoteFrontend
);
ok
{
fe
.
Enable
()
}
return
true
,
nil
}
rpc/api/net.go
View file @
28b14d3e
...
...
@@ -32,7 +32,7 @@ var (
netMapping
=
map
[
string
]
nethandler
{
"net_peerCount"
:
(
*
netApi
)
.
PeerCount
,
"net_listening"
:
(
*
netApi
)
.
IsListening
,
"net_version"
:
(
*
netApi
)
.
Version
,
"net_version"
:
(
*
netApi
)
.
Version
,
}
)
...
...
@@ -97,4 +97,3 @@ func (self *netApi) IsListening(req *shared.Request) (interface{}, error) {
func
(
self
*
netApi
)
Version
(
req
*
shared
.
Request
)
(
interface
{},
error
)
{
return
self
.
xeth
.
NetworkVersion
(),
nil
}
rpc/api/personal.go
View file @
28b14d3e
...
...
@@ -17,6 +17,7 @@
package
api
import
(
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -125,18 +126,17 @@ func (self *personalApi) UnlockAccount(req *shared.Request) (interface{}, error)
return
nil
,
shared
.
NewDecodeParamError
(
err
.
Error
())
}
var
err
error
if
len
(
args
.
Passphrase
)
==
0
{
fe
:=
self
.
xeth
.
Frontend
()
if
fe
==
nil
{
return
false
,
fmt
.
Errorf
(
"No password provided"
)
}
return
fe
.
UnlockAccount
(
common
.
HexToAddress
(
args
.
Address
)
.
Bytes
()),
nil
}
am
:=
self
.
ethereum
.
AccountManager
()
addr
:=
common
.
HexToAddress
(
args
.
Address
)
if
args
.
Duration
==
-
1
{
err
=
am
.
Unlock
(
addr
,
args
.
Passphrase
)
}
else
{
err
=
am
.
TimedUnlock
(
addr
,
args
.
Passphrase
,
time
.
Duration
(
args
.
Duration
)
*
time
.
Second
)
}
if
err
==
nil
{
return
true
,
nil
}
return
false
,
err
err
:=
am
.
TimedUnlock
(
addr
,
args
.
Passphrase
,
time
.
Duration
(
args
.
Duration
)
*
time
.
Second
)
return
err
==
nil
,
err
}
rpc/api/personal_args.go
View file @
28b14d3e
...
...
@@ -86,10 +86,10 @@ func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
return
shared
.
NewDecodeParamError
(
err
.
Error
())
}
args
.
Duration
=
-
1
args
.
Duration
=
0
if
len
(
obj
)
<
2
{
return
shared
.
NewInsufficientParamsError
(
len
(
obj
),
2
)
if
len
(
obj
)
<
1
{
return
shared
.
NewInsufficientParamsError
(
len
(
obj
),
1
)
}
if
addrstr
,
ok
:=
obj
[
0
]
.
(
string
);
ok
{
...
...
@@ -98,10 +98,18 @@ func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
return
shared
.
NewInvalidTypeError
(
"address"
,
"not a string"
)
}
if
passphrasestr
,
ok
:=
obj
[
1
]
.
(
string
);
ok
{
args
.
Passphrase
=
passphrasestr
}
else
{
return
shared
.
NewInvalidTypeError
(
"passphrase"
,
"not a string"
)
if
len
(
obj
)
>=
2
&&
obj
[
1
]
!=
nil
{
if
passphrasestr
,
ok
:=
obj
[
1
]
.
(
string
);
ok
{
args
.
Passphrase
=
passphrasestr
}
else
{
return
shared
.
NewInvalidTypeError
(
"passphrase"
,
"not a string"
)
}
}
if
len
(
obj
)
>=
3
&&
obj
[
2
]
!=
nil
{
if
duration
,
ok
:=
obj
[
2
]
.
(
float64
);
ok
{
args
.
Duration
=
int
(
duration
)
}
}
return
nil
...
...
rpc/api/s
s
h_js.go
→
rpc/api/s
h
h_js.go
View file @
28b14d3e
File moved
rpc/codec/codec.go
View file @
28b14d3e
...
...
@@ -31,6 +31,8 @@ type ApiCoder interface {
ReadRequest
()
([]
*
shared
.
Request
,
bool
,
error
)
// Parse response message from underlying stream
ReadResponse
()
(
interface
{},
error
)
// Read raw message from underlying stream
Recv
()
(
interface
{},
error
)
// Encode response to encoded form in underlying stream
WriteResponse
(
interface
{})
error
// Decode single message from data
...
...
rpc/codec/json.go
View file @
28b14d3e
...
...
@@ -21,6 +21,7 @@ import (
"fmt"
"net"
"time"
"strings"
"github.com/ethereum/go-ethereum/rpc/shared"
)
...
...
@@ -73,35 +74,41 @@ func (self *JsonCodec) ReadRequest() (requests []*shared.Request, isBatch bool,
return
nil
,
false
,
err
}
func
(
self
*
JsonCodec
)
ReadResponse
()
(
interface
{},
error
)
{
bytesInBuffer
:=
0
buf
:=
make
([]
byte
,
MAX_RESPONSE_SIZE
)
func
(
self
*
JsonCodec
)
Recv
()
(
interface
{},
error
)
{
var
msg
json
.
RawMessage
err
:=
self
.
d
.
Decode
(
&
msg
)
if
err
!=
nil
{
self
.
c
.
Close
()
return
nil
,
err
}
deadline
:=
time
.
Now
()
.
Add
(
READ_TIMEOUT
*
time
.
Second
)
if
err
:=
self
.
c
.
SetDeadline
(
deadline
);
err
!=
nil
{
return
msg
,
err
}
func
(
self
*
JsonCodec
)
ReadResponse
()
(
interface
{},
error
)
{
in
,
err
:=
self
.
Recv
()
if
err
!=
nil
{
return
nil
,
err
}
for
{
n
,
err
:=
self
.
c
.
Read
(
buf
[
bytesInBuffer
:
])
if
err
!=
nil
{
return
nil
,
err
if
msg
,
ok
:=
in
.
(
json
.
RawMessage
);
ok
{
var
req
*
shared
.
Request
if
err
=
json
.
Unmarshal
(
msg
,
&
req
);
err
==
nil
&&
strings
.
HasPrefix
(
req
.
Method
,
"agent_"
)
{
return
req
,
nil
}
bytesInBuffer
+=
n
var
failure
shared
.
ErrorResponse
if
err
=
json
.
Unmarshal
(
buf
[
:
bytesInBuffer
]
,
&
failure
);
err
==
nil
&&
failure
.
Error
!=
nil
{
var
failure
*
shared
.
ErrorResponse
if
err
=
json
.
Unmarshal
(
msg
,
&
failure
);
err
==
nil
&&
failure
.
Error
!=
nil
{
return
failure
,
fmt
.
Errorf
(
failure
.
Error
.
Message
)
}
var
success
shared
.
SuccessResponse
if
err
=
json
.
Unmarshal
(
buf
[
:
bytesInBuffer
]
,
&
success
);
err
==
nil
{
var
success
*
shared
.
SuccessResponse
if
err
=
json
.
Unmarshal
(
msg
,
&
success
);
err
==
nil
{
return
success
,
nil
}
}
self
.
c
.
Close
()
return
nil
,
fmt
.
Errorf
(
"Unable to read response"
)
return
in
,
err
}
// Decode data
...
...
rpc/comms/comms.go
View file @
28b14d3e
...
...
@@ -49,7 +49,7 @@ var (
)
type
EthereumClient
interface
{
// Close underl
a
ying connection
// Close underlying connection
Close
()
// Send request
Send
(
interface
{})
error
...
...
rpc/comms/inproc.go
View file @
28b14d3e
...
...
@@ -60,7 +60,7 @@ func (self *InProcClient) Send(req interface{}) error {
}
func
(
self
*
InProcClient
)
Recv
()
(
interface
{},
error
)
{
return
self
.
lastRes
,
self
.
lastErr
return
*
shared
.
NewRpcResponse
(
self
.
lastId
,
self
.
lastJsonrpc
,
self
.
lastRes
,
self
.
lastErr
),
nil
}
func
(
self
*
InProcClient
)
SupportedModules
()
(
map
[
string
]
string
,
error
)
{
...
...
rpc/comms/ipc.go
View file @
28b14d3e
...
...
@@ -44,35 +44,18 @@ func (self *ipcClient) Close() {
func
(
self
*
ipcClient
)
Send
(
req
interface
{})
error
{
var
err
error
if
r
,
ok
:=
req
.
(
*
shared
.
Request
);
ok
{
if
err
=
self
.
coder
.
WriteResponse
(
r
);
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
{
// connection lost, retry once
if
err
=
self
.
reconnect
();
err
==
nil
{
err
=
self
.
coder
.
WriteResponse
(
r
)
}
if
err
=
self
.
coder
.
WriteResponse
(
req
);
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
{
// connection lost, retry once
if
err
=
self
.
reconnect
();
err
==
nil
{
err
=
self
.
coder
.
WriteResponse
(
req
)
}
}
return
err
}
return
fmt
.
Errorf
(
"Invalid request (%T)"
,
req
)
return
err
}
func
(
self
*
ipcClient
)
Recv
()
(
interface
{},
error
)
{
res
,
err
:=
self
.
coder
.
ReadResponse
()
if
err
!=
nil
{
return
nil
,
err
}
if
r
,
ok
:=
res
.
(
shared
.
SuccessResponse
);
ok
{
return
r
.
Result
,
nil
}
if
r
,
ok
:=
res
.
(
shared
.
ErrorResponse
);
ok
{
return
r
.
Error
,
nil
}
return
res
,
err
return
self
.
coder
.
ReadResponse
()
}
func
(
self
*
ipcClient
)
SupportedModules
()
(
map
[
string
]
string
,
error
)
{
...
...
@@ -91,7 +74,7 @@ func (self *ipcClient) SupportedModules() (map[string]string, error) {
return
nil
,
err
}
if
sucRes
,
ok
:=
res
.
(
shared
.
SuccessResponse
);
ok
{
if
sucRes
,
ok
:=
res
.
(
*
shared
.
SuccessResponse
);
ok
{
data
,
_
:=
json
.
Marshal
(
sucRes
.
Result
)
modules
:=
make
(
map
[
string
]
string
)
err
=
json
.
Unmarshal
(
data
,
&
modules
)
...
...
@@ -109,8 +92,8 @@ func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
}
// Start IPC server
func
StartIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
offeredApi
shared
.
EthereumApi
)
error
{
return
startIpc
(
cfg
,
codec
,
offeredApi
)
func
StartIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
initializer
func
(
conn
net
.
Conn
)
(
shared
.
EthereumApi
,
error
)
)
error
{
return
startIpc
(
cfg
,
codec
,
initializer
)
}
func
newIpcConnId
()
int
{
...
...
rpc/comms/ipc_unix.go
View file @
28b14d3e
...
...
@@ -48,7 +48,7 @@ func (self *ipcClient) reconnect() error {
return
err
}
func
startIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
api
shared
.
EthereumApi
)
error
{
func
startIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
initializer
func
(
conn
net
.
Conn
)
(
shared
.
EthereumApi
,
error
)
)
error
{
os
.
Remove
(
cfg
.
Endpoint
)
// in case it still exists from a previous run
l
,
err
:=
net
.
Listen
(
"unix"
,
cfg
.
Endpoint
)
...
...
@@ -69,6 +69,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id
:=
newIpcConnId
()
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"New IPC connection with id %06d started
\n
"
,
id
)
api
,
err
:=
initializer
(
conn
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to initialize IPC connection - %v
\n
"
,
err
)
conn
.
Close
()
continue
}
go
handle
(
id
,
conn
,
api
,
codec
)
}
...
...
rpc/comms/ipc_windows.go
View file @
28b14d3e
...
...
@@ -667,7 +667,7 @@ func (self *ipcClient) reconnect() error {
return
err
}
func
startIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
api
shared
.
EthereumApi
)
error
{
func
startIpc
(
cfg
IpcConfig
,
codec
codec
.
Codec
,
initializer
func
(
conn
net
.
Conn
)
(
shared
.
EthereumApi
,
error
)
)
error
{
os
.
Remove
(
cfg
.
Endpoint
)
// in case it still exists from a previous run
l
,
err
:=
Listen
(
cfg
.
Endpoint
)
...
...
@@ -687,6 +687,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id
:=
newIpcConnId
()
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"New IPC connection with id %06d started
\n
"
,
id
)
api
,
err
:=
initializer
(
conn
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to initialize IPC connection - %v
\n
"
,
err
)
conn
.
Close
()
continue
}
go
handle
(
id
,
conn
,
api
,
codec
)
}
...
...
rpc/jeth.go
View file @
28b14d3e
...
...
@@ -18,12 +18,17 @@ package rpc
import
(
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto"
)
...
...
@@ -31,10 +36,21 @@ type Jeth struct {
ethApi
shared
.
EthereumApi
re
*
jsre
.
JSRE
client
comms
.
EthereumClient
fe
xeth
.
Frontend
}
func
NewJeth
(
ethApi
shared
.
EthereumApi
,
re
*
jsre
.
JSRE
,
client
comms
.
EthereumClient
)
*
Jeth
{
return
&
Jeth
{
ethApi
,
re
,
client
}
func
NewJeth
(
ethApi
shared
.
EthereumApi
,
re
*
jsre
.
JSRE
,
client
comms
.
EthereumClient
,
fe
xeth
.
Frontend
)
*
Jeth
{
// enable the jeth as the user agent
req
:=
shared
.
Request
{
Id
:
0
,
Method
:
useragent
.
EnableUserAgentMethod
,
Jsonrpc
:
shared
.
JsonRpcVersion
,
Params
:
[]
byte
(
"[]"
),
}
client
.
Send
(
&
req
)
client
.
Recv
()
return
&
Jeth
{
ethApi
,
re
,
client
,
fe
}
}
func
(
self
*
Jeth
)
err
(
call
otto
.
FunctionCall
,
code
int
,
msg
string
,
id
interface
{})
(
response
otto
.
Value
)
{
...
...
@@ -72,16 +88,34 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
if
err
!=
nil
{
return
self
.
err
(
call
,
-
32603
,
err
.
Error
(),
req
.
Id
)
}
respif
,
err
=
self
.
client
.
Recv
()
recv
:
respif
,
err
=
self
.
client
.
Recv
()
if
err
!=
nil
{
return
self
.
err
(
call
,
-
32603
,
err
.
Error
(),
req
.
Id
)
}
agentreq
,
isRequest
:=
respif
.
(
*
shared
.
Request
)
if
isRequest
{
self
.
handleRequest
(
agentreq
)
goto
recv
// receive response after agent interaction
}
sucres
,
isSuccessResponse
:=
respif
.
(
*
shared
.
SuccessResponse
)
errres
,
isErrorResponse
:=
respif
.
(
*
shared
.
ErrorResponse
)
if
!
isSuccessResponse
&&
!
isErrorResponse
{
return
self
.
err
(
call
,
-
32603
,
fmt
.
Sprintf
(
"Invalid response type (%T)"
,
respif
),
req
.
Id
)
}
call
.
Otto
.
Set
(
"ret_jsonrpc"
,
shared
.
JsonRpcVersion
)
call
.
Otto
.
Set
(
"ret_id"
,
req
.
Id
)
res
,
_
:=
json
.
Marshal
(
respif
)
var
res
[]
byte
if
isSuccessResponse
{
res
,
err
=
json
.
Marshal
(
sucres
.
Result
)
}
else
if
isErrorResponse
{
res
,
err
=
json
.
Marshal
(
errres
.
Error
)
}
call
.
Otto
.
Set
(
"ret_result"
,
string
(
res
))
call
.
Otto
.
Set
(
"response_idx"
,
i
)
...
...
@@ -105,3 +139,48 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
return
}
// handleRequest will handle user agent requests by interacting with the user and sending
// the user response back to the geth service
func
(
self
*
Jeth
)
handleRequest
(
req
*
shared
.
Request
)
bool
{
var
err
error
var
args
[]
interface
{}
if
err
=
json
.
Unmarshal
(
req
.
Params
,
&
args
);
err
!=
nil
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Unable to parse agent request - %v
\n
"
,
err
)
return
false
}
switch
req
.
Method
{
case
useragent
.
AskPasswordMethod
:
return
self
.
askPassword
(
req
.
Id
,
req
.
Jsonrpc
,
args
)
case
useragent
.
ConfirmTransactionMethod
:
return
self
.
confirmTransaction
(
req
.
Id
,
req
.
Jsonrpc
,
args
)
}
return
false
}
// askPassword will ask the user to supply the password for a given account
func
(
self
*
Jeth
)
askPassword
(
id
interface
{},
jsonrpc
string
,
args
[]
interface
{})
bool
{
var
err
error
var
passwd
string
if
len
(
args
)
>=
1
{
if
account
,
ok
:=
args
[
0
]
.
(
string
);
ok
{
fmt
.
Printf
(
"Unlock account %s
\n
"
,
account
)
passwd
,
err
=
utils
.
PromptPassword
(
"Passphrase: "
,
true
)
}
else
{
return
false
}
}
if
err
=
self
.
client
.
Send
(
shared
.
NewRpcResponse
(
id
,
jsonrpc
,
passwd
,
err
));
err
!=
nil
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Unable to send user agent ask password response - %v
\n
"
,
err
)
}
return
err
==
nil
}
func
(
self
*
Jeth
)
confirmTransaction
(
id
interface
{},
jsonrpc
string
,
args
[]
interface
{})
bool
{
// Accept all tx which are send from this console
return
self
.
client
.
Send
(
shared
.
NewRpcResponse
(
id
,
jsonrpc
,
true
,
nil
))
==
nil
}
rpc/useragent/agent.go
0 → 100644
View file @
28b14d3e
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// package user agent provides frontends and agents which can interact with the user
package
useragent
var
(
AskPasswordMethod
=
"agent_askPassword"
ConfirmTransactionMethod
=
"agent_confirmTransaction"
EnableUserAgentMethod
=
"admin_enableUserAgent"
)
rpc/useragent/remote_frontend.go
0 → 100644
View file @
28b14d3e
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
useragent
import
(
"encoding/json"
"fmt"
"net"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/shared"
)
// remoteFrontend implements xeth.Frontend and will communicate with an external
// user agent over a connection
type
RemoteFrontend
struct
{
enabled
bool
mgr
*
accounts
.
Manager
d
*
json
.
Decoder
e
*
json
.
Encoder
n
int
}
// NewRemoteFrontend creates a new frontend which will interact with an user agent
// over the given connection
func
NewRemoteFrontend
(
conn
net
.
Conn
,
mgr
*
accounts
.
Manager
)
*
RemoteFrontend
{
return
&
RemoteFrontend
{
false
,
mgr
,
json
.
NewDecoder
(
conn
),
json
.
NewEncoder
(
conn
),
0
}
}
// Enable will enable user interaction
func
(
fe
*
RemoteFrontend
)
Enable
()
{
fe
.
enabled
=
true
}
// UnlockAccount asks the user agent for the user password and tries to unlock the account.
// It will try 3 attempts before giving up.
func
(
fe
*
RemoteFrontend
)
UnlockAccount
(
address
[]
byte
)
bool
{
if
!
fe
.
enabled
{
return
false
}
err
:=
fe
.
send
(
AskPasswordMethod
,
common
.
Bytes2Hex
(
address
))
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to send password request to agent - %v
\n
"
,
err
)
return
false
}
passwdRes
,
err
:=
fe
.
recv
()
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to recv password response from agent - %v
\n
"
,
err
)
return
false
}
if
passwd
,
ok
:=
passwdRes
.
Result
.
(
string
);
ok
{
err
=
fe
.
mgr
.
Unlock
(
common
.
BytesToAddress
(
address
),
passwd
)
}
if
err
==
nil
{
return
true
}
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"3 invalid account unlock attempts"
)
return
false
}
// ConfirmTransaction asks the user for approval
func
(
fe
*
RemoteFrontend
)
ConfirmTransaction
(
tx
string
)
bool
{
if
!
fe
.
enabled
{
return
true
// backwards compatibility
}
err
:=
fe
.
send
(
ConfirmTransactionMethod
,
tx
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to send tx confirmation request to agent - %v
\n
"
,
err
)
return
false
}
confirmResponse
,
err
:=
fe
.
recv
()
if
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Unable to recv tx confirmation response from agent - %v
\n
"
,
err
)
return
false
}
if
confirmed
,
ok
:=
confirmResponse
.
Result
.
(
bool
);
ok
{
return
confirmed
}
return
false
}
// send request to the agent
func
(
fe
*
RemoteFrontend
)
send
(
method
string
,
params
...
interface
{})
error
{
fe
.
n
+=
1
p
,
err
:=
json
.
Marshal
(
params
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"Unable to send agent request %v
\n
"
,
err
)
return
err
}
req
:=
shared
.
Request
{
Method
:
method
,
Jsonrpc
:
shared
.
JsonRpcVersion
,
Id
:
fe
.
n
,
Params
:
p
,
}
return
fe
.
e
.
Encode
(
&
req
)
}
// recv user response from agent
func
(
fe
*
RemoteFrontend
)
recv
()
(
*
shared
.
SuccessResponse
,
error
)
{
var
res
json
.
RawMessage
if
err
:=
fe
.
d
.
Decode
(
&
res
);
err
!=
nil
{
return
nil
,
err
}
var
response
shared
.
SuccessResponse
if
err
:=
json
.
Unmarshal
(
res
,
&
response
);
err
==
nil
{
return
&
response
,
nil
}
return
nil
,
fmt
.
Errorf
(
"Invalid user agent response"
)
}
xeth/xeth.go
View file @
28b14d3e
...
...
@@ -885,6 +885,10 @@ func isAddress(addr string) bool {
return
addrReg
.
MatchString
(
addr
)
}
func
(
self
*
XEth
)
Frontend
()
Frontend
{
return
self
.
frontend
}
func
(
self
*
XEth
)
Transact
(
fromStr
,
toStr
,
nonceStr
,
valueStr
,
gasStr
,
gasPriceStr
,
codeStr
string
)
(
string
,
error
)
{
// this minimalistic recoding is enough (works for natspec.js)
...
...
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