前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2019-03-14 通过rpc发布和调用以太坊合约

2019-03-14 通过rpc发布和调用以太坊合约

作者头像
oracle3
发布2022-05-13 08:31:39
4200
发布2022-05-13 08:31:39
举报
文章被收录于专栏:oracle3技术大杂烩

这里研究一下通过rpc发布和调用以太坊合约的过程(windows10环境)

1、准备工作

1.1、启动geth,创建一个专门用来发布合约的账户

参考2018-11-22 Debug以太坊go-ethereum实战 启动geth,并attach一个geth执行创建账户的命令:

代码语言:javascript
复制
geth --datadir "D:\gopath\src\github.com\ethereum\geth-data0" --networkid 1314 --nodiscover --rpcaddr "127.0.0.1" --rpcport 8545 --rpc --rpcapi "db,eth,net,web3" --port 30001 --ipcpath geth1.ipc console --allow-insecure-unlock

新建一个终端

代码语言:javascript
复制
geth attach ipc:\\.\pipe\geth1.ipc
personal.newAccount("123")

获得账户地址:"0x80284209f81e620ce62e40cd969906ed07b87c50" 给其转账10个eth

代码语言:javascript
复制
personal.unlockAccount(eth.accounts[0])
eth.sendTransaction({from:eth.accounts[0],to:"0x80284209f81e620ce62e40cd969906ed07b87c50",value:web3.toWei(10,"ether")})
miner.start(1);admin.sleepBlocks(1);miner.stop();
eth.getBalance("0x80284209f81e620ce62e40cd969906ed07b87c50")

获得账户余额:10000000000000000000

1.2、安装nodejs需要的库
代码语言:javascript
复制
cd temp
mkdir web3test
cd web3test
npm install keythereum
npm install ethereumjs-tx
1.3、还需要安装postman来执行rpc

2、发布合约

发布合约使用的rpc是eth_sendRawTransaction,但是参数是签名字符串,这里需要用nodejs代码实现签名 合约代码如下:

代码语言:javascript
复制
pragma solidity ^0.4.25;

contract helloworld {
    string content;

    function setContent(string memory _str) public {
        content = _str;
    }

    function getContent() view public returns (string memory){
        return content;
    }
}

通过remix获取web3的js

代码语言:javascript
复制
var helloworldContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"_str","type":"string"}],"name":"setContent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContent","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]);
var helloworld = helloworldContract.new(
   {
     from: web3.eth.accounts[0], 
     data: '0x608060405234801561001057600080fd5b506102d7806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633be8fd6a1461005157806359016c79146100ba575b600080fd5b34801561005d57600080fd5b506100b8600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061014a565b005b3480156100c657600080fd5b506100cf610164565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010f5780820151818401526020810190506100f4565b50505050905090810190601f16801561013c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b8060009080519060200190610160929190610206565b5050565b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101fc5780601f106101d1576101008083540402835291602001916101fc565b820191906000526020600020905b8154815290600101906020018083116101df57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061024757805160ff1916838001178555610275565b82800160010185558215610275579182015b82811115610274578251825591602001919060010190610259565b5b5090506102829190610286565b5090565b6102a891905b808211156102a457600081600090555060010161028c565b5090565b905600a165627a7a7230582063b1c8ec79802b75b1777bd30256814a628ddb908967a3dbd2597a032f52257c0029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

构造eth_sendTransaction,仅需要改使用上面的data填充下面的data,

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 171,
    "method": "eth_sendTransaction",
    "params": [
        {
            "data": "0x608060405234801561001057600080fd5b506102d7806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633be8fd6a1461005157806359016c79146100ba575b600080fd5b34801561005d57600080fd5b506100b8600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061014a565b005b3480156100c657600080fd5b506100cf610164565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010f5780820151818401526020810190506100f4565b50505050905090810190601f16801561013c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b8060009080519060200190610160929190610206565b5050565b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101fc5780601f106101d1576101008083540402835291602001916101fc565b820191906000526020600020905b8154815290600101906020018083116101df57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061024757805160ff1916838001178555610275565b82800160010185558215610275579182015b82811115610274578251825591602001919060010190610259565b5b5090506102829190610286565b5090565b6102a891905b808211156102a457600081600090555060010161028c565b5090565b905600a165627a7a7230582063b1c8ec79802b75b1777bd30256814a628ddb908967a3dbd2597a032f52257c0029",
            "from": "0x80284209f81e620ce62e40cd969906ed07b87c50",
            "gas": "0x47b760"
        }
    ]
}

放在postman中执行,post给http://127.0.0.1:8545,注意设置body为raw,选择JSON(application) 获得执行结果

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 171,
    "error": {
        "code": -32000,
        "message": "authentication needed: password or unlock"
    }
}

需要先去geth出解锁

代码语言:javascript
复制
personal.unlockAccount("0x80284209f81e620ce62e40cd969906ed07b87c50")

然后重新执行,获得结果

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 171,
    "result": "0xcd38e4c93cb9ce1971f25ba488c7c8f6600840d569ce7d3307604bf0ca0d6eb6"
}

由于这个发起了交易,还需要去geth出挖矿,才能执行完成

代码语言:javascript
复制
miner.start(1);admin.sleepBlocks(1);miner.stop();

查询执行结果:

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 2192787296,
    "method": "eth_getTransactionReceipt",
    "params": [
        "0xcd38e4c93cb9ce1971f25ba488c7c8f6600840d569ce7d3307604bf0ca0d6eb6"
    ]
}

返回:

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 2192787296,
    "result": {
        "blockHash": "0xe01ebc2eb6214c8c82f20331fd6dbba34608afe7c6dd3e9772d81be75fb4bebf",
        "blockNumber": "0x1872",
        "contractAddress": "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245",
        "cumulativeGasUsed": "0x3c19a",
        "from": "0x80284209f81e620ce62e40cd969906ed07b87c50",
        "gasUsed": "0x3c19a",
        "logs": [],
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "root": "0x5e4af4ef2e96abf728e3fabee5dcdda6ddbc25f484938ed110a446fa1df12474",
        "to": null,
        "transactionHash": "0xcd38e4c93cb9ce1971f25ba488c7c8f6600840d569ce7d3307604bf0ca0d6eb6",
        "transactionIndex": "0x0"
    }
}

获得合约地址:0xb9c4e02ab322fefb26ec422b07d9cdacb9036245

3、调用合约

3.1、调用设置函数

由于合约函数调用需要编码,这里使用myencode.js编码,其中的abi依然来自于remix

代码语言:javascript
复制
const Web3 = require('web3');
const web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");

// example of encode a function call
let abi = {
        "constant": false,
        "inputs": [
            {
                "name": "_str",
                "type": "string"
            }
        ],
        "name": "setContent",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    };


let funCall = web3.eth.abi.encodeFunctionCall(abi, ['123']);
console.log(funCall);

获得: 0x3be8fd6a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000033132330000000000000000000000000000000000000000000000000000000000

构造eth_sendTransaction,只需要用这个返回值替换data,to替换为合约地址

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 171,
    "method": "eth_sendTransaction",
    "params": [
        {
            "data": "0x3be8fd6a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000033132330000000000000000000000000000000000000000000000000000000000",
            "from": "0x80284209f81e620ce62e40cd969906ed07b87c50",
            "to": "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245",
            "gas": "0x47b760"
        }
    ]
}

获得结果:

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 171,
    "result": "0x58e6e328d48b3c66481b631ec9015e88a247bd36a9565643203b27d0f7bc2c85"
}

由于这个发起了交易,还需要去geth出挖矿,才能执行完成

代码语言:javascript
复制
miner.start(1);admin.sleepBlocks(1);miner.stop();
3.2、调用读取函数

直接调用eth_call就可以了,下面的data来自于remix的detail里面的

代码语言:javascript
复制
FUNCTIONHASHES
{
    "59016c79": "getContent()",
    "3be8fd6a": "setContent(string)"
}

组合eth_call

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 1114,
    "method": "eth_call",
    "params": [
        {
            "data": "0x59016c79",
            "to": "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245"
        },
        "latest"
    ]
}

返回:

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 1114,
    "result": "0x"
}

比较奇怪,居然无法读出来 使用eth_getStorageAt可以读出

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 1115,
    "method": "eth_getStorageAt",
    "params": [
        "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245",
        "0x0",
        "latest"
    ]
}

返回:

代码语言:javascript
复制
{
    "jsonrpc": "2.0",
    "id": 1115,
    "result": "0x3132330000000000000000000000000000000000000000000000000000000006"
}

在geth下也可以读取到:

代码语言:javascript
复制
// 合约ABI
var abi=[{"constant":false,"inputs":[{"name":"_str","type":"string"}],"name":"setContent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContent","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}];
// 合约地址
var address = "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245";
// 通过ABI和地址获取已部署的合约对象
var helloworld = web3.eth.contract(abi).at(address);
helloworld.getContent()

返回:

代码语言:javascript
复制
"123"

或者直接调用:

代码语言:javascript
复制
eth.call({to: "0xb9c4e02ab322fefb26ec422b07d9cdacb9036245", data: "0x59016c79"})

也能够返回结果:

代码语言:javascript
复制
"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000033132330000000000000000000000000000000000000000000000000000000000"
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、准备工作
    • 1.1、启动geth,创建一个专门用来发布合约的账户
      • 1.2、安装nodejs需要的库
        • 1.3、还需要安装postman来执行rpc
        • 2、发布合约
        • 3、调用合约
          • 3.1、调用设置函数
            • 3.2、调用读取函数
            相关产品与服务
            区块链
            云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档