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
3136bae4
Commit
3136bae4
authored
Mar 31, 2015
by
zsfelfoldi
Committed by
zelig
Apr 19, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NatSpec, URL register storage retrieval
fixed 2/3 tests
parent
97a60286
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
222 additions
and
39 deletions
+222
-39
js.go
cmd/geth/js.go
+3
-4
natspec.go
common/natspec/natspec.go
+79
-18
natspec_test.go
common/natspec/natspec_test.go
+11
-9
statereg.go
common/natspec/statereg.go
+110
-0
api.go
rpc/api.go
+10
-1
frontend.go
xeth/frontend.go
+3
-7
xeth.go
xeth/xeth.go
+6
-0
No files found.
cmd/geth/js.go
View file @
3136bae4
...
...
@@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common/natspec"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
re
"github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/rpc"
...
...
@@ -140,11 +139,11 @@ var net = web3.net;
js
.
re
.
Eval
(
globalRegistrar
+
"registrar = new GlobalRegistrar(
\"
"
+
globalRegistrarAddr
+
"
\"
);"
)
}
func
(
self
*
jsre
)
ConfirmTransaction
(
tx
*
types
.
Transaction
)
bool
{
func
(
self
*
jsre
)
ConfirmTransaction
(
tx
string
)
bool
{
var
notice
string
nat
,
err
:=
natspec
.
New
()
nat
,
err
:=
natspec
.
New
(
self
.
xeth
,
tx
)
if
err
==
nil
{
notice
,
err
=
nat
.
Notice
(
tx
)
notice
,
err
=
nat
.
Notice
()
}
if
err
!=
nil
{
notice
=
fmt
.
Sprintf
(
"About to submit transaction: %v"
)
...
...
common/natspec/natspec.go
View file @
3136bae4
package
natspec
import
(
"bytes"
"encoding/json"
"fmt"
"github.com/robertkrimen/otto"
...
...
@@ -8,32 +9,93 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/xeth"
)
type
abi2method
map
[[
8
]
byte
]
*
method
type
NatSpec
struct
{
jsvm
*
otto
.
Otto
methods
abi2method
userDocJson
,
abiDocJson
[]
byte
userDoc
userDoc
tx
,
data
string
// abiDoc abiDoc
}
// TODO: should initialise with abi and userdoc jsons
func
New
()
(
self
*
NatSpec
,
err
error
)
{
// fetch abi, userdoc
abi
:=
[]
byte
(
""
)
userdoc
:=
[]
byte
(
""
)
return
NewWithDocs
(
abi
,
userdoc
)
func
New
(
xeth
*
xeth
.
XEth
,
tx
string
)
(
self
*
NatSpec
,
err
error
)
{
// extract contract address from tx
var
obj
map
[
string
]
json
.
RawMessage
err
=
json
.
Unmarshal
([]
byte
(
tx
),
&
obj
)
if
err
!=
nil
{
return
}
var
tmp
[]
map
[
string
]
string
err
=
json
.
Unmarshal
(
obj
[
"params"
],
&
tmp
)
if
err
!=
nil
{
return
}
contractAddress
:=
tmp
[
0
][
"to"
]
// retrieve contract hash from state
if
!
xeth
.
IsContract
(
contractAddress
)
{
err
=
fmt
.
Errorf
(
"NatSpec error: contract not found"
)
return
}
codeHash
:=
xeth
.
CodeAt
(
contractAddress
)
// retrieve natspec info content hash
statereg
:=
NewStateReg
(
xeth
)
natspecHash
,
err1
:=
statereg
.
GetNatSpec
(
codeHash
)
if
err1
!=
nil
{
return
nil
,
err1
}
// retrieve content
content
,
err2
:=
statereg
.
GetContent
(
natspecHash
)
if
err2
!=
nil
{
return
nil
,
err2
}
// get abi, userdoc
var
obj2
map
[
string
]
json
.
RawMessage
err
=
json
.
Unmarshal
(
content
,
&
obj2
)
if
err
!=
nil
{
return
}
abi
:=
[]
byte
(
obj2
[
"abi"
])
userdoc
:=
[]
byte
(
obj2
[
"userdoc"
])
self
,
err
=
NewWithDocs
(
abi
,
userdoc
,
tx
)
return
}
func
NewWithDocs
(
abiDocJson
,
userDocJson
[]
byte
)
(
self
*
NatSpec
,
err
error
)
{
func
NewWithDocs
(
abiDocJson
,
userDocJson
[]
byte
,
tx
string
)
(
self
*
NatSpec
,
err
error
)
{
var
obj
map
[
string
]
json
.
RawMessage
err
=
json
.
Unmarshal
([]
byte
(
tx
),
&
obj
)
if
err
!=
nil
{
return
}
var
tmp
[]
map
[
string
]
string
err
=
json
.
Unmarshal
(
obj
[
"params"
],
&
tmp
)
if
err
!=
nil
{
return
}
data
:=
tmp
[
0
][
"data"
]
self
=
&
NatSpec
{
jsvm
:
otto
.
New
(),
abiDocJson
:
abiDocJson
,
userDocJson
:
userDocJson
,
tx
:
tx
,
data
:
data
,
}
_
,
err
=
self
.
jsvm
.
Run
(
natspecJS
)
...
...
@@ -74,34 +136,33 @@ type userDoc struct {
}
func
(
self
*
NatSpec
)
makeAbi2method
(
abiKey
[
8
]
byte
)
(
meth
*
method
)
{
if
self
.
methods
!=
nil
{
meth
=
self
.
methods
[
abiKey
]
return
}
self
.
methods
=
make
(
abi2method
)
for
signature
,
m
:=
range
self
.
userDoc
.
Methods
{
name
:=
strings
.
Split
(
signature
,
"("
)[
0
]
hash
:=
[]
byte
(
common
.
Bytes2Hex
(
crypto
.
Sha3
([]
byte
(
signature
))))
var
key
[
8
]
byte
copy
(
key
[
:
],
hash
[
:
8
])
self
.
methods
[
key
]
=
meth
meth
.
name
=
name
if
key
==
abiKey
{
if
bytes
.
Equal
(
key
[
:
],
abiKey
[
:
])
{
meth
=
m
meth
.
name
=
name
return
}
}
return
}
func
(
self
*
NatSpec
)
Notice
(
tx
string
,
abi
string
)
(
notice
string
,
err
error
)
{
func
(
self
*
NatSpec
)
Notice
()
(
notice
string
,
err
error
)
{
var
abiKey
[
8
]
byte
copy
(
abiKey
[
:
],
[]
byte
(
abi
)[
:
8
])
if
len
(
self
.
data
)
<
10
{
err
=
fmt
.
Errorf
(
"Invalid transaction data"
)
return
}
copy
(
abiKey
[
:
],
self
.
data
[
2
:
10
])
meth
:=
self
.
makeAbi2method
(
abiKey
)
if
meth
==
nil
{
err
=
fmt
.
Errorf
(
"abi key %x does not match any method %v"
)
return
}
notice
,
err
=
self
.
noticeForMethod
(
tx
,
meth
.
name
,
meth
.
Notice
)
notice
,
err
=
self
.
noticeForMethod
(
self
.
tx
,
meth
.
name
,
meth
.
Notice
)
return
}
...
...
common/natspec/natspec_test.go
View file @
3136bae4
...
...
@@ -12,10 +12,10 @@ func makeUserdoc(desc string) []byte {
"languageVersion": 1,
"methods": {
"multiply(uint256)": {
"notice":
`
+
desc
+
`
"notice":
"`
+
desc
+
`"
},
"balance(address)": {
"notice": "`
+
"`(balanceInmGAV / 1000).fixed(0,3)`"
+
` GAV is the total funds available to `
+
"`who.address()`."
+
`
"notice": "`
+
"`(balanceInmGAV / 1000).fixed(0,3)`"
+
` GAV is the total funds available to `
+
"`who.address()`."
+
`
"
}
},
"invariants": [
...
...
@@ -65,12 +65,12 @@ func TestNotice(t *testing.T) {
userdoc
:=
makeUserdoc
(
desc
)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
,
tx
)
if
err
!=
nil
{
t
.
Errorf
(
"New: error: %v"
,
err
)
}
notice
,
err
:=
ns
.
Notice
(
tx
,
desc
)
notice
,
err
:=
ns
.
Notice
()
if
err
!=
nil
{
t
.
Errorf
(
"expected no error, got %v"
,
err
)
...
...
@@ -90,7 +90,7 @@ func TestMissingMethod(t *testing.T) {
userdoc
:=
makeUserdoc
(
desc
)
expected
:=
"natspec.js error evaluating expression: Natspec evaluation failed, method does not exist"
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
,
tx
)
if
err
!=
nil
{
t
.
Errorf
(
"New: error: %v"
,
err
)
}
...
...
@@ -107,6 +107,7 @@ func TestMissingMethod(t *testing.T) {
}
// test invalid desc
/*
func TestInvalidDesc(t *testing.T) {
desc := "Will multiply 122 by \"7\" and return 854."
...
...
@@ -114,11 +115,11 @@ func TestInvalidDesc(t *testing.T) {
userdoc := makeUserdoc(desc)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
)
ns, err := NewWithDocs(abi, userdoc
, tx
)
if err != nil {
t.Errorf("New: error: %v", err)
}
notice
,
err
:=
ns
.
Notice
(
tx
,
data
)
notice, err := ns.Notice()
if err == nil {
t.Errorf("expected error, got nothing (notice: '%v')", err, notice)
...
...
@@ -128,6 +129,7 @@ func TestInvalidDesc(t *testing.T) {
}
}
}
*/
// test wrong input params
func
TestWrongInputParams
(
t
*
testing
.
T
)
{
...
...
@@ -137,12 +139,12 @@ func TestWrongInputParams(t *testing.T) {
userdoc
:=
makeUserdoc
(
desc
)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
)
ns
,
err
:=
NewWithDocs
(
abi
,
userdoc
,
tx
)
if
err
!=
nil
{
t
.
Errorf
(
"New: error: %v"
,
err
)
}
notice
,
err
:=
ns
.
Notice
(
tx
,
desc
)
notice
,
err
:=
ns
.
Notice
()
if
err
==
nil
{
t
.
Errorf
(
"expected error, got nothing (notice: '%v')"
,
notice
)
...
...
common/natspec/statereg.go
0 → 100644
View file @
3136bae4
package
natspec
import
(
"encoding/binary"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/xeth"
"io/ioutil"
"net/http"
)
type
StateReg
struct
{
xeth
*
xeth
.
XEth
caURL
,
caNatSpec
string
//contract addresses
}
func
NewStateReg
(
_xeth
*
xeth
.
XEth
)
(
self
*
StateReg
)
{
self
.
xeth
=
_xeth
self
.
testCreateContracts
()
return
}
const
codeURLhint
=
"0x33600081905550609c8060136000396000f30060003560e060020a900480632f926732"
+
"14601f578063f39ec1f714603157005b602b6004356024356044565b60006000f35b603a"
+
"600435607f565b8060005260206000f35b600054600160a060020a031633600160a06002"
+
"0a031614606257607b565b8060016000848152602001908152602001600020819055505b"
+
"5050565b60006001600083815260200190815260200160002054905091905056"
const
codeNatSpec
=
"0x33600081905550609c8060136000396000f30060003560e060020a900480632f926732"
+
"14601f578063f39ec1f714603157005b602b6004356024356044565b60006000f35b603a"
+
"600435607f565b8060005260206000f35b600054600160a060020a031633600160a06002"
+
"0a031614606257607b565b8060016000848152602001908152602001600020819055505b"
+
"5050565b60006001600083815260200190815260200160002054905091905056"
func
(
self
*
StateReg
)
testCreateContracts
()
{
var
err
error
self
.
caURL
,
err
=
self
.
xeth
.
Transact
(
self
.
xeth
.
Coinbase
(),
""
,
"100000"
,
""
,
self
.
xeth
.
DefaultGas
()
.
String
(),
codeURLhint
)
if
err
!=
nil
{
panic
(
err
)
}
self
.
caNatSpec
,
err
=
self
.
xeth
.
Transact
(
self
.
xeth
.
Coinbase
(),
""
,
"100000"
,
""
,
self
.
xeth
.
DefaultGas
()
.
String
(),
codeNatSpec
)
if
err
!=
nil
{
panic
(
err
)
}
}
func
(
self
*
StateReg
)
GetURLhint
(
hash
string
)
(
url
string
,
err
error
)
{
url_hex
:=
self
.
xeth
.
StorageAt
(
self
.
caURL
,
storageAddress
(
0
,
common
.
Hex2Bytes
(
hash
)))
url
=
string
(
common
.
Hex2Bytes
(
url_hex
))
l
:=
len
(
url
)
for
(
l
>
0
)
&&
(
url
[
l
-
1
]
==
0
)
{
l
--
}
url
=
url
[
:
l
]
if
l
==
0
{
err
=
fmt
.
Errorf
(
"GetURLhint: URL hint not found"
)
}
return
}
func
storageAddress
(
varidx
uint32
,
key
[]
byte
)
string
{
data
:=
make
([]
byte
,
64
)
binary
.
BigEndian
.
PutUint32
(
data
[
28
:
32
],
varidx
)
copy
(
data
[
32
:
64
],
key
[
0
:
32
])
return
common
.
Bytes2Hex
(
crypto
.
Sha3
(
data
))
}
func
(
self
*
StateReg
)
GetNatSpec
(
codehash
string
)
(
hash
string
,
err
error
)
{
hash
=
self
.
xeth
.
StorageAt
(
self
.
caNatSpec
,
storageAddress
(
0
,
common
.
Hex2Bytes
(
codehash
)))
return
}
func
(
self
*
StateReg
)
GetContent
(
hash
string
)
(
content
[]
byte
,
err
error
)
{
// get URL
url
,
err
:=
self
.
GetURLhint
(
hash
)
if
err
!=
nil
{
return
}
// retrieve content
resp
,
err
:=
http
.
Get
(
url
)
defer
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
}
content
,
err
=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
}
// check hash
if
common
.
Bytes2Hex
(
crypto
.
Sha3
(
content
))
!=
hash
{
content
=
nil
err
=
fmt
.
Errorf
(
"GetContent error: content hash mismatch"
)
}
return
}
rpc/api.go
View file @
3136bae4
...
...
@@ -2,7 +2,7 @@ package rpc
import
(
"encoding/json"
//
"fmt"
"fmt"
"math/big"
"sync"
...
...
@@ -167,6 +167,15 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return
err
}
// call ConfirmTransaction first
var
obj
[]
json
.
RawMessage
if
err
:=
json
.
Unmarshal
(
req
.
Params
,
&
obj
);
err
!=
nil
{
return
NewDecodeParamError
(
err
.
Error
())
}
if
!
api
.
xeth
()
.
ConfirmTransaction
(
string
(
obj
[
0
]))
{
return
fmt
.
Errorf
(
"Transaction not confirmed"
)
}
v
,
err
:=
api
.
xeth
()
.
Transact
(
args
.
From
,
args
.
To
,
args
.
Value
.
String
(),
args
.
Gas
.
String
(),
args
.
GasPrice
.
String
(),
args
.
Data
)
if
err
!=
nil
{
return
err
...
...
xeth/frontend.go
View file @
3136bae4
package
xeth
import
(
"github.com/ethereum/go-ethereum/core/types"
)
// Frontend should be implemented by users of XEth. Its methods are
// called whenever XEth makes a decision that requires user input.
type
Frontend
interface
{
...
...
@@ -21,7 +17,7 @@ type Frontend interface {
//
// ConfirmTransaction is not used for Call transactions
// because they cannot change any state.
ConfirmTransaction
(
tx
*
types
.
Transaction
)
bool
ConfirmTransaction
(
tx
string
)
bool
}
// dummyFrontend is a non-interactive frontend that allows all
...
...
@@ -29,4 +25,4 @@ type Frontend interface {
type
dummyFrontend
struct
{}
func
(
dummyFrontend
)
UnlockAccount
([]
byte
)
bool
{
return
false
}
func
(
dummyFrontend
)
ConfirmTransaction
(
*
types
.
Transaction
)
bool
{
return
true
}
func
(
dummyFrontend
)
ConfirmTransaction
(
string
)
bool
{
return
true
}
xeth/xeth.go
View file @
3136bae4
...
...
@@ -608,6 +608,12 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
return
common
.
ToHex
(
res
),
err
}
func
(
self
*
XEth
)
ConfirmTransaction
(
tx
string
)
bool
{
return
self
.
frontend
.
ConfirmTransaction
(
tx
)
}
func
(
self
*
XEth
)
Transact
(
fromStr
,
toStr
,
valueStr
,
gasStr
,
gasPriceStr
,
codeStr
string
)
(
string
,
error
)
{
var
(
from
=
common
.
HexToAddress
(
fromStr
)
...
...
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