|
|
|
@ -6,16 +6,19 @@ import ( |
|
|
|
|
"math/big" |
|
|
|
|
"os" |
|
|
|
|
"testing" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/accounts" |
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/common/docserver" |
|
|
|
|
"github.com/ethereum/go-ethereum/common/natspec" |
|
|
|
|
"github.com/ethereum/go-ethereum/common/resolver" |
|
|
|
|
"github.com/ethereum/go-ethereum/core" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/state" |
|
|
|
|
//"github.com/ethereum/go-ethereum/core/state"
|
|
|
|
|
//"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
|
"github.com/ethereum/go-ethereum/crypto" |
|
|
|
|
"github.com/ethereum/go-ethereum/eth" |
|
|
|
|
"github.com/ethereum/go-ethereum/rpc" |
|
|
|
|
xe "github.com/ethereum/go-ethereum/xeth" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -23,19 +26,81 @@ type testFrontend struct { |
|
|
|
|
t *testing.T |
|
|
|
|
ethereum *eth.Ethereum |
|
|
|
|
xeth *xe.XEth |
|
|
|
|
stateDb *state.StateDB |
|
|
|
|
api *rpc.EthereumApi |
|
|
|
|
coinbase string |
|
|
|
|
txc int |
|
|
|
|
lastConfirm string |
|
|
|
|
makeNatSpec bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const testNotice = "Register key `_key` <- content `_content`" |
|
|
|
|
const testExpNotice = "Register key 8.9477152217924674838424037953991966239322087453347756267410168184682657981552e+76 <- content 2.9345842665291639932787537650068479186757226656217642728276414736233000517704e+76" |
|
|
|
|
|
|
|
|
|
const testUserDoc = ` |
|
|
|
|
{ |
|
|
|
|
"source": "...", |
|
|
|
|
"language": "Solidity", |
|
|
|
|
"languageVersion": 1, |
|
|
|
|
"methods": { |
|
|
|
|
"register(uint256,uint256)": { |
|
|
|
|
"notice": "` + testNotice + `" |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"invariants": [ |
|
|
|
|
{ "notice": "" } |
|
|
|
|
], |
|
|
|
|
"construction": [ |
|
|
|
|
{ "notice": "" } |
|
|
|
|
] |
|
|
|
|
} |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
const testABI = ` |
|
|
|
|
[{ |
|
|
|
|
"name": "register", |
|
|
|
|
"constant": false, |
|
|
|
|
"type": "function", |
|
|
|
|
"inputs": [{ |
|
|
|
|
"name": "_key", |
|
|
|
|
"type": "uint256" |
|
|
|
|
}, { |
|
|
|
|
"name": "_content", |
|
|
|
|
"type": "uint256" |
|
|
|
|
}], |
|
|
|
|
"outputs": [] |
|
|
|
|
}] |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
const testDocs = ` |
|
|
|
|
{ |
|
|
|
|
"userdoc": ` + testUserDoc + `, |
|
|
|
|
"abi": ` + testABI + ` |
|
|
|
|
} |
|
|
|
|
` |
|
|
|
|
|
|
|
|
|
func (f *testFrontend) UnlockAccount(acc []byte) bool { |
|
|
|
|
f.t.Logf("Unlocking account %v\n", common.Bytes2Hex(acc)) |
|
|
|
|
f.ethereum.AccountManager().Unlock(acc, "password") |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *testFrontend) ConfirmTransaction(message string) bool { |
|
|
|
|
f.lastConfirm = message |
|
|
|
|
func (f *testFrontend) ConfirmTransaction(tx string) bool { |
|
|
|
|
//f.t.Logf("ConfirmTransaction called tx = %v", tx)
|
|
|
|
|
if f.makeNatSpec { |
|
|
|
|
ds, err := docserver.New("/tmp/") |
|
|
|
|
if err != nil { |
|
|
|
|
f.t.Errorf("Error creating DocServer: %v", err) |
|
|
|
|
} |
|
|
|
|
nat, err2 := natspec.New(f.xeth, tx, ds) |
|
|
|
|
if err2 == nil { |
|
|
|
|
f.lastConfirm, err = nat.Notice() |
|
|
|
|
if err != nil { |
|
|
|
|
f.t.Errorf("Notice error: %v", err) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
f.t.Errorf("Error creating NatSpec: %v", err2) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -89,6 +154,7 @@ func testInit(t *testing.T) (self *testFrontend) { |
|
|
|
|
|
|
|
|
|
self = &testFrontend{t: t, ethereum: ethereum} |
|
|
|
|
self.xeth = xe.New(ethereum, self) |
|
|
|
|
self.api = rpc.NewEthereumApi(self.xeth) |
|
|
|
|
|
|
|
|
|
addr := self.xeth.Coinbase() |
|
|
|
|
self.coinbase = addr |
|
|
|
@ -103,8 +169,6 @@ func testInit(t *testing.T) (self *testFrontend) { |
|
|
|
|
} |
|
|
|
|
t.Logf("Balance is %v", balance) |
|
|
|
|
|
|
|
|
|
self.stateDb = self.ethereum.ChainManager().State().Copy() |
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -117,33 +181,87 @@ func (self *testFrontend) insertTx(addr, contract, fnsig string, args []string) |
|
|
|
|
data = data + common.Bytes2Hex(common.Hex2BytesFixed(arg, 32)) |
|
|
|
|
} |
|
|
|
|
self.t.Logf("Tx data: %v", data) |
|
|
|
|
self.xeth.Transact(addr, contract, "100000000000", "100000", "100000", data) |
|
|
|
|
|
|
|
|
|
cb := common.HexToAddress(addr) |
|
|
|
|
jsontx := ` |
|
|
|
|
[{ |
|
|
|
|
"from": "` + addr + `", |
|
|
|
|
"to": "0x` + contract + `", |
|
|
|
|
"value": "100000000000", |
|
|
|
|
"gas": "100000", |
|
|
|
|
"gasPrice": "100000", |
|
|
|
|
"data": "` + data + `" |
|
|
|
|
}] |
|
|
|
|
` |
|
|
|
|
self.txc++ |
|
|
|
|
req := &rpc.RpcRequest{ |
|
|
|
|
Jsonrpc: "2.0", |
|
|
|
|
Method: "eth_transact", |
|
|
|
|
Params: []byte(jsontx), |
|
|
|
|
Id: self.txc, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
txcount := self.ethereum.TxPool().Size() |
|
|
|
|
|
|
|
|
|
var reply interface{} |
|
|
|
|
err0 := self.api.GetRequestReply(req, &reply) |
|
|
|
|
if err0 != nil { |
|
|
|
|
self.t.Errorf("GetRequestReply error: %v", err0) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for txcount == self.ethereum.TxPool().Size() { |
|
|
|
|
time.Sleep(time.Millisecond) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//self.xeth.Transact(addr, contract, "100000000000", "100000", "100000", data)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *testFrontend) applyTxs() { |
|
|
|
|
|
|
|
|
|
coinbase := self.stateDb.GetStateObject(cb) |
|
|
|
|
coinbase.SetGasPool(big.NewInt(100000)) |
|
|
|
|
cb := common.HexToAddress(self.coinbase) |
|
|
|
|
stateDb := self.ethereum.ChainManager().State().Copy() |
|
|
|
|
block := self.ethereum.ChainManager().NewBlock(cb) |
|
|
|
|
coinbase := stateDb.GetStateObject(cb) |
|
|
|
|
coinbase.SetGasPool(big.NewInt(1000000)) |
|
|
|
|
txs := self.ethereum.TxPool().GetTransactions() |
|
|
|
|
tx := txs[0] |
|
|
|
|
|
|
|
|
|
_, gas, err := core.ApplyMessage(core.NewEnv(self.stateDb, self.ethereum.ChainManager(), tx, block), tx, coinbase) |
|
|
|
|
|
|
|
|
|
self.t.Logf("ApplyMessage: gas %v err %v", gas, err) |
|
|
|
|
for _, tx := range txs { |
|
|
|
|
_, gas, err := core.ApplyMessage(core.NewEnv(stateDb, self.ethereum.ChainManager(), tx, block), tx, coinbase) |
|
|
|
|
//self.ethereum.TxPool().RemoveSet([]*types.Transaction{tx})
|
|
|
|
|
time.Sleep(time.Millisecond * 100) |
|
|
|
|
self.t.Logf("ApplyMessage: gas %v err %v", gas, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
self.ethereum.TxPool().RemoveSet(txs) |
|
|
|
|
self.xeth = self.xeth.WithState(self.stateDb) |
|
|
|
|
self.xeth = self.xeth.WithState(stateDb) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *testFrontend) registerURL(hash common.Hash, url string) { |
|
|
|
|
hashHex := common.Bytes2Hex(hash[:]) |
|
|
|
|
urlHex := common.Bytes2Hex([]byte(url)) |
|
|
|
|
self.insertTx(self.coinbase, core.ContractAddrURLhint, "register(bytes32,bytes32)", []string{hashHex, urlHex}) |
|
|
|
|
self.insertTx(self.coinbase, core.ContractAddrURLhint, "register(uint256,uint256)", []string{hashHex, urlHex}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *testFrontend) setOwner() { |
|
|
|
|
|
|
|
|
|
self.insertTx(self.coinbase, core.ContractAddrHashReg, "setowner()", []string{}) |
|
|
|
|
|
|
|
|
|
/*owner := self.xeth.StorageAt("0x"+core.ContractAddrHashReg, "0x0000000000000000000000000000000000000000000000000000000000000000") |
|
|
|
|
self.t.Logf("owner = %v", owner) |
|
|
|
|
if owner != self.coinbase { |
|
|
|
|
self.t.Errorf("setowner() unsuccessful, owner != coinbase") |
|
|
|
|
}*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *testFrontend) registerNatSpec(codehash, dochash common.Hash) { |
|
|
|
|
|
|
|
|
|
codeHex := common.Bytes2Hex(codehash[:]) |
|
|
|
|
docHex := common.Bytes2Hex(dochash[:]) |
|
|
|
|
self.insertTx(self.coinbase, core.ContractAddrHashReg, "register(uint256,uint256)", []string{codeHex, docHex}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *testFrontend) testResolver() *resolver.Resolver { |
|
|
|
|
return resolver.New(self.xeth, resolver.URLHintContractAddress, resolver.NameRegContractAddress) |
|
|
|
|
return resolver.New(self.xeth, resolver.URLHintContractAddress, resolver.HashRegContractAddress) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestNatspecE2E(t *testing.T) { |
|
|
|
@ -151,16 +269,34 @@ func TestNatspecE2E(t *testing.T) { |
|
|
|
|
tf := testInit(t) |
|
|
|
|
defer tf.ethereum.Stop() |
|
|
|
|
|
|
|
|
|
ds, _ := docserver.New("/tmp/") |
|
|
|
|
ioutil.WriteFile("/tmp/test.content", []byte(testDocs), os.ModePerm) |
|
|
|
|
dochash := common.BytesToHash(crypto.Sha3([]byte(testDocs))) |
|
|
|
|
|
|
|
|
|
chash := common.BytesToHash(crypto.Sha3([]byte("kutyafasza"))) |
|
|
|
|
tf.registerURL(chash, "file:///test.content") |
|
|
|
|
tf.registerURL(chash, "kf") |
|
|
|
|
codehex := tf.xeth.CodeAt(core.ContractAddrHashReg) |
|
|
|
|
codehash := common.BytesToHash(crypto.Sha3(common.Hex2Bytes(codehex))) |
|
|
|
|
|
|
|
|
|
url, err2 := tf.testResolver().ContentHashToUrl(chash) |
|
|
|
|
tf.setOwner() |
|
|
|
|
tf.registerNatSpec(codehash, dochash) |
|
|
|
|
tf.registerURL(dochash, "file:///test.content") |
|
|
|
|
tf.applyTxs() |
|
|
|
|
|
|
|
|
|
t.Logf("URL: %v err: %v", url, err2) |
|
|
|
|
chash, err := tf.testResolver().KeyToContentHash(codehash) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Errorf("Can't find content hash") |
|
|
|
|
} |
|
|
|
|
t.Logf("chash = %x err = %v", chash, err) |
|
|
|
|
url, err2 := tf.testResolver().ContentHashToUrl(dochash) |
|
|
|
|
if err2 != nil { |
|
|
|
|
t.Errorf("Can't find URL hint") |
|
|
|
|
} |
|
|
|
|
t.Logf("url = %v err = %v", url, err2) |
|
|
|
|
|
|
|
|
|
tf.makeNatSpec = true |
|
|
|
|
tf.registerNatSpec(codehash, dochash) // call again just to get a confirm message
|
|
|
|
|
t.Logf("Confirm message: %v\n", tf.lastConfirm) |
|
|
|
|
|
|
|
|
|
ds.GetAuthContent(url, chash) |
|
|
|
|
if tf.lastConfirm != testExpNotice { |
|
|
|
|
t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice, tf.lastConfirm) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|