ewasm由于變化比較大,導致文章2018-11-26 ewasm在以太坊私有鏈測試
和2019-03-15 ewasm在以太坊私有鏈測試(2)已經無法成功發(fā)布和調用合約了,參考文章initial version of wrc20 token修改得到以下方法:
1、發(fā)布合約
先拉取代碼,并按readme的方法操作
git clone https://github.com/hugo-dc/deploy-ewasm
cargo install chisel
cd deploy-ewasm\example
chisel run
能夠獲取store_deployer.wasm文件,然后執(zhí)行:
cd ..
./sendtx.sh ./example/store_deployer.wasm 9 '8DFFB7687E432CF9540728F41579452F2F9B646DD29BBCA57B1AFE76817EC379'
Generating transaction...
Sending transaction...
0xf9012d09843b9aca00830f42408080b8dc0061736d0100000001090260027f7f0060000002130108657468657265756d0666696e697368000003030200010503010001071102046d61696e0002066d656d6f727902000a0e0202000b0900410041fe0010000b0b8401010041000b7e0061736d0100000001090260027f7f0060000002190108657468657265756d0c73746f7261676553746f72650000030201010503010001071102066d656d6f72790200046d61696e00010a0a0108004100412010000b0b26010041200b2000000000000000000000000000000000000000000000000000000000000000011ba055e580e1cdd74e63edac6114055b9293e2c2d32b1073e079152f6e9a69df039ea068fb6f81cce137032af8c716154866bc75b4b2b166ffacdd9c08a26f8f89b973
{"jsonrpc":"2.0","id":2,"error":{"code":-32000,"message":"intrinsic gas too low"}}
注:參數說明,參數9是nonce值,參數'8DFFB7687E432CF9540728F41579452F2F9B646DD29BBCA57B1AFE76817EC379'是當前發(fā)送交易的賬戶的私鑰
出現了錯誤信息,"intrinsic gas too low"
修改文件txn.js
修改了txParams.gasLimit = gas
為:txParams.gasLimit = 1000000
再次執(zhí)行:
./sendtx.sh ./example/store_deployer.wasm 9 '8DFFB7687E432CF9540728F41579452F2F9B646DD29BBCA57B1AFE76817EC379'
Generating transaction...
Sending transaction...
0xf9012d09843b9aca00830f42408080b8dc0061736d0100000001090260027f7f0060000002130108657468657265756d0666696e697368000003030200010503010001071102046d61696e0002066d656d6f727902000a0e0202000b0900410041fe0010000b0b8401010041000b7e0061736d0100000001090260027f7f0060000002190108657468657265756d0c73746f7261676553746f72650000030201010503010001071102066d656d6f72790200046d61696e00010a0a0108004100412010000b0b26010041200b2000000000000000000000000000000000000000000000000000000000000000011ba055e580e1cdd74e63edac6114055b9293e2c2d32b1073e079152f6e9a69df039ea068fb6f81cce137032af8c716154866bc75b4b2b166ffacdd9c08a26f8f89b973
{"jsonrpc":"2.0","id":2,"result":"0xda7a8778c5c2af8898a04995c200a347c2e000e985613b1c60e92c2accf6be88"}
這次成功了,查詢交易0xda7a8778c5c2af8898a04995c200a347c2e000e985613b1c60e92c2accf6be88
可能還處于pending狀態(tài),需要等一段時間,這個網站好慢,然后可以看到| To: | New Contract (deployment address:0x7E729E5353C8AE3eD3Fe5669Ccd771A613acB17b) |
打開上面的連接,可以看到當前合約的wast代碼,storage為空
2、調用合約
需要自己寫個腳本和js
文件calltx.sh
#!/bin/bash
echo Generating transaction...
tx=$(node calltxn.js --nonce $1 --priv $2 --to $3)
echo Sending transaction...
echo $tx
curl -X POST -H 'Content-Type: application/json' --data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"$tx\"],\"id\":2}" http://ewasm.ethereum.org:8545
文件calltxn.js
const EthereumTx = require('ethereumjs-tx')
var Web3 = require('web3')
var web3Provider = new Web3.providers.HttpProvider('http://ewasm.ethereum.org:8545')
var web3 = new Web3(web3Provider)
const argv = require('yargs').argv;
const fs = require('fs')
const request = require('request')
let data = ''
let nonce = argv.nonce ? argv.nonce : ''
let to = argv.to ? argv.to : ''
let priv = argv.priv
const privateKey = Buffer.from(priv, 'hex')
var txParams = {}
txParams.data = data
txParams.value = '0x0'
txParams.nonce = nonce
txParams.to = to
var gasPrice = 1000000000 // web3.eth.gasPrice
web3.eth.estimateGas(txParams, function(err, gas) {
txParams.gasLimit = 1000000
txParams.gasPrice = gasPrice
let tx = new EthereumTx(txParams)
tx.sign(privateKey)
let serializedTx = tx.serialize()
serializedTx = serializedTx.toString('hex')
console.log("0x"+serializedTx)
})
執(zhí)行:
./calltx.sh 10 '8DFFB7687E432CF9540728F41579452F2F9B646DD29BBCA57B1AFE76817EC379' '0x7E729E5353C8AE3eD3Fe5669Ccd771A613acB17b'
注:參數說明:10是nonce,'8DFFB7687E432CF9540728F41579452F2F9B646DD29BBCA57B1AFE76817EC379' 是私鑰,'0x7E729E5353C8AE3eD3Fe5669Ccd771A613acB17b'是合約地址
成功后查詢交易0x9f6c8aed86b64c3a021685bfedc18a767dbd32a134cc4ddfd5649171234d5688
查詢合約存儲0x7E729E5353C8AE3eD3Fe5669Ccd771A613acB17b
可以看到storage中已經存儲有值:
[
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000000",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
]
3、使用自己的私有鏈測試
參考文章2018-11-26 ewasm在以太坊私有鏈測試啟動私有鏈
修改sendtx.sh、txn.js、calltx.sh、calltxn.js中
http://ewasm.ethereum.org:8545
為
http://localhost:8545
啟動go ethereum
./geth \
--vm.ewasm="./libhera.so,metering=true,fallback=true" \
--datadir ewasm-testnet-data \
--rpc --rpcapi "web3,net,eth,debug" \
--rpcvhosts="*" --rpcaddr "0.0.0.0" \
--rpccorsdomain "*" \
--nodiscover \
--networkid 66 \
--ipcpath geth1.ipc console
獲取當前賬戶的私鑰,參考2018-12-14 查看以太坊私鑰
得到,
然后執(zhí)行發(fā)布腳本:
./sendtx.sh ./example/store_deployer.wasm 1 '63fe0326d54575e4546bad24eb32776fcae08edbf9256b75ee7fcfed2b7d9822'
出現錯誤
{"jsonrpc":"2.0","id":2,"error":{"code":-32000,"message":"nonce too low"}}
在geth下查詢當前nonce
eth.getTransactionCount('0xb338d763691dcfcff4720bc8f3e627901e239b30')
返回10
./sendtx.sh ./example/store_deployer.wasm 10 '63fe0326d54575e4546bad24eb32776fcae08edbf9256b75ee7fcfed2b7d9822'
返回正確:
{"jsonrpc":"2.0","id":2,"result":"0xff31a32577a67ff019ec686e245167adc39de8c18a85afd1f9131db49bcc7afa"}
開始挖礦
miner.start(1);admin.sleepBlocks(1);miner.stop();
在geth中查詢
eth.getTransactionReceipt("0xff31a32577a67ff019ec686e245167adc39de8c18a85afd1f9131db49bcc7afa")
查詢不到,但是日志信息中:
INFO [07-05|10:24:12.521] Submitted contract creation fullhash=0xff31a32577a67ff019ec686e245167adc39de8c18a85afd1f9131db49bcc7afa contract=0x9e14cE0f3B9AE6006E9E9039E336DB6196Ecb422
我們查詢一下合約:
eth.getCode("0x9e14cE0f3B9AE6006E9E9039E336DB6196Ecb422")
也查詢不到,
eth.getTransaction('0xff31a32577a67ff019ec686e245167adc39de8c18a85afd1f9131db49bcc7afa')
還在,使用
txpool.status
返回:
{
pending: 1,
queued: 0
}
發(fā)現還需要挖礦,繼續(xù)
miner.start(1);admin.sleepBlocks(1);miner.stop();
這次總是可以查詢到了,結論是必須挖礦兩次,而不是一次
4、私有鏈下使用rpc測試
操作參考2019-03-14 通過rpc發(fā)布和調用以太坊合約
創(chuàng)建合約
{
"jsonrpc": "2.0",
"id": 171,
"method": "eth_sendTransaction",
"params": [
{
"data": "0x0061736d0100000001090260027f7f0060000002130108657468657265756d0666696e697368000003030200010503010001071102046d61696e0002066d656d6f727902000a0e0202000b0900410041fe0010000b0b8401010041000b7e0061736d0100000001090260027f7f0060000002190108657468657265756d0c73746f7261676553746f72650000030201010503010001071102066d656d6f72790200046d61696e00010a0a0108004100412010000b0b26010041200b200000000000000000000000000000000000000000000000000000000000000001",
"from": "0xb338d763691dcfcff4720bc8f3e627901e239b30",
"gas": "0x47b760"
}
]
}
獲得結果
{
"jsonrpc": "2.0",
"id": 171,
"result": "0xcce335377ff76cfa135c88fbc6b337539f03e7808f77473095a670104c3c8929"
}
如果出現"authentication needed: password or unlock",需要解鎖
personal.unlockAccount("0xb338d763691dcfcff4720bc8f3e627901e239b30")
上面data中的數據可以通過wasm2hex.js獲取,其內容
var fs=require('fs');
var path=require('path');
var args = process.argv.splice(2)
var file=path.resolve(args[0]);
var content=Buffer.alloc(0);//累計合并讀取片段
fs.readFile(file,function(err,chunk){
if(err)
return console.error(err);
console.log(chunk);
//將數據轉換為hex字符串
console.log(chunk.toString('hex'));
//合并Buffer
content=Buffer.concat([content,chunk]);
//保存成文件
var imgData=Buffer.from(content);
fs.writeFile(path.resolve('test.txt'),imgData.toString('hex'),function(err){
if(err)
return console.error(err);
});
});
執(zhí)行:
node wasm2hex.js store_deployer.wasm
從生成的文件test.txt復制,記得data前綴是0x,否則出現錯誤:"invalid argument 0: json: cannot unmarshal hex string without 0x prefix into Go struct field SendTxArgs.data of type hexutil.Bytes"
同樣的問題,我們需要挖礦兩次,才能正確獲得交易結果
miner.start(1);admin.sleepBlocks(1);miner.stop();
miner.start(1);admin.sleepBlocks(1);miner.stop();
獲得交易結果:
{
"jsonrpc": "2.0",
"id": 2192787296,
"method": "eth_getTransactionReceipt",
"params": [
"0xcce335377ff76cfa135c88fbc6b337539f03e7808f77473095a670104c3c8929"
]
}
返回:
{
"jsonrpc": "2.0",
"id": 2192787296,
"result": {
"blockHash": "0x8ef493560a75fcab08a04fc0dd2a903daa53952912e57bf1fe746361d05f4df5",
"blockNumber": "0x136",
"contractAddress": "0xfbd68b1fffd21ba3112583383c4b51d9f8a6e4ff",
"cumulativeGasUsed": "0x16f7c",
"from": "0xb338d763691dcfcff4720bc8f3e627901e239b30",
"gasUsed": "0x16f7c",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": null,
"transactionHash": "0xcce335377ff76cfa135c88fbc6b337539f03e7808f77473095a670104c3c8929",
"transactionIndex": "0x0"
}
}
獲得合約地址:0xfbd68b1fffd21ba3112583383c4b51d9f8a6e4ff
調用合約:
{
"jsonrpc": "2.0",
"id": 171,
"method": "eth_sendTransaction",
"params": [
{
"data": "0x",
"from": "0xb338d763691dcfcff4720bc8f3e627901e239b30",
"to": "0xfbd68b1fffd21ba3112583383c4b51d9f8a6e4ff",
"gas": "0x47b760"
}
]
}
返回:
{
"jsonrpc": "2.0",
"id": 171,
"result": "0xd7452ccafbff75e5653213f5324137c90d5b74acd683e193eb5a756a90e8dd79"
}
執(zhí)行一次挖礦
miner.start(1);admin.sleepBlocks(1);miner.stop();
查詢合約存儲信息
{
"jsonrpc": "2.0",
"id": 1115,
"method": "eth_getStorageAt",
"params": [
"0xfbd68b1fffd21ba3112583383c4b51d9f8a6e4ff",
"0x0",
"latest"
]
}
返回
{
"jsonrpc": "2.0",
"id": 1115,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
完全正確
5、使用包裝前的wasm測試
采用4的方法,對包裝前的store.wasm測試了發(fā)布和調用,都是成功的,因此不理解為啥deploy-ewasm強調wasm需要通過chisel run處理wasm文件
找到原因了,chisel run處理后的合約發(fā)布后,保存到鏈上的是chisel run處理前的合約,這樣就可以保證合約在發(fā)布的時候不會被執(zhí)行,只有調用的時候才能夠執(zhí)行,另外也是通過這個包裝確保了合約在發(fā)布的時候可以調用哨兵合約進行檢查。
但是這塊也是個漏洞,因為不使用chisel run處理wasm文件,就發(fā)布合約,會規(guī)避了哨兵合約的檢查。