美文网首页
智能合约简单编程

智能合约简单编程

作者: 小朴同学 | 来源:发表于2019-02-18 10:49 被阅读8次
  1. 编译问题

    1.6版本之前和1.6版本及之后,最大的差异就是就是得到abi和bytecode的方式不同。之前的直接集合geth的环境中。之后的需要单独提出来进行处理。下面介绍的就是1.6版本后。abi和bytecode的获取。

    • 第一种方式。在编译网站进行编译,然后选中compile(编译按钮)->点击Details(详情按钮)->弹出的界面中下滑找到WEB3DEPLOY,得到内容。或者下滑找到BYTECODE,点击复制,然后在数据前加0x,找到INTERFACE - ABI,然后这就是abi。
      // web3.eth.contract()中括号中的内容就是abi
      // abi = [{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCount","outputs":[{"name":"a","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
      var browser_ballot_sol_simplestorageContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCount","outputs":[{"name":"a","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]);
      // 下面中data对应的内容就是bytecode
      // bytecode = '0x60606040526007600055341561001457600080fd5b60e9806100226000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063a87d942c146074575b600080fd5b3415605857600080fd5b605e609a565b6040518082815260200191505060405180910390f35b3415607e57600080fd5b608460a0565b6040518082815260200191505060405180910390f35b60005481565b600060ab60005460b0565b905090565b60006007820290509190505600a165627a7a72305820ce3994eccf8989c24603717c6996c128cbde4dff903c7b3f6cd101c3ac6c092c0029'
      var browser_ballot_sol_simplestorage = browser_ballot_sol_simplestorageContract.new(
         {
           from: web3.eth.accounts[0], 
           data: '0x60606040526007600055341561001457600080fd5b60e9806100226000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063a87d942c146074575b600080fd5b3415605857600080fd5b605e609a565b6040518082815260200191505060405180910390f35b3415607e57600080fd5b608460a0565b6040518082815260200191505060405180910390f35b60005481565b600060ab60005460b0565b905090565b60006007820290509190505600a165627a7a72305820ce3994eccf8989c24603717c6996c128cbde4dff903c7b3f6cd101c3ac6c092c0029', 
           gas: '4700000'
         }, function (e, contract){
          console.log(e, contract);
          if (typeof contract.address !== 'undefined') {
               console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
          }
       })
      
    • 第二种方式用安装Solidity,然后命令行进行编译
      soliditySource.sol就是把示例代码保存的一个文件,后缀是.sol
      // 生成bytecode,输出的内容最前加上 0x,也就是0和x
      solc --bin soliditySource.sol
      // 生成abi
      solc --abi soliditySource.sol
      
    • Solidity代码示例
      pragma solidity ^0.4.0;
      
      contract SimpleStorage {
          // 一个公开的变量
          uint256 public count = 7;
      
          // 一个私有的方法
          function multiply(uint256 a) internal pure returns (uint256 b) {
              return a * 7;
          }
          
          // 一个公开的方法
          function getCount() public constant returns (uint256 a) {
              return multiply(count);
          }
      }
      
  2. 部署

    • 进入geth环境。参考本地以太坊调用的测试
    • 进入配置如下:
      // 进入geth环境
      localhost:ethereum zsk$ ./start.sh 00
      // 确保你的用户存在且你本身有币(也就是你挖矿到一定数量的以太币)。不然如果没有币你在部署的时候会报错,具体错误不表
      // 用user变量接受用户地址
      > user = eth.accounts[0]
      // abi变量接受abi真实数据
      > abi = [{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCount","outputs":[{"name":"a","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
      // bytecode接受真实的bytecode数据
      bytecode = '0x60606040526007600055341561001457600080fd5b60e9806100226000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063a87d942c146074575b600080fd5b3415605857600080fd5b605e609a565b6040518082815260200191505060405180910390f35b3415607e57600080fd5b608460a0565b6040518082815260200191505060405180910390f35b60005481565b600060ab60005460b0565b905090565b60006007820290509190505600a165627a7a72305820ce3994eccf8989c24603717c6996c128cbde4dff903c7b3f6cd101c3ac6c092c0029'
      > contract = web3.eth.contract(abi)
      // 先解锁用户 abc123是创建用户的密码
      > personal.unlockAccount(user, 'abc123')
      // 发布合约 user就是用户地址,data就是bytecode字节,gas就是交易消耗的币,其他的暂时可以不管
      > contractObject = contract.new({from: user,data:bytecode,gas: 4700000}, function (e, contract){console.log(e, contract);if (typeof contract.address !== 'undefined') {console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);}})
      // 此时代表有一笔交易待确定
      > txpool.status
          {
            pending: 1,
            queued: 0
          }
      // 查看待确认交易的详细内容 from数据项就是我们发送交易的地址,input就是合约编译完成的字节码,这些内容均与我们之前的设定相同。而且,我们可以看到新的交易创建在第92区块中
      > eth.getBlock("pending",true).transactions
          [{
              blockHash: "0x619c95ad722b88fe301d59ef962b4fee52ab75184520ebe85f780230f6bed96e",
              blockNumber: 92,
              from: "0x4079a3f5ffeeb7a84a4a582e9fc5f25579c3bba0",
              gas: 4700000,
              gasPrice: 18000000000,
              hash: "0x6b02ebd337e7e48f858c387c24f1f1dbc2ead86027dd36b95a319fde4c1004e2",
              input: "0x60606040526007600055341561001457600080fd5b60e9806100226000396000f3006060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063a87d942c146074575b600080fd5b3415605857600080fd5b605e609a565b6040518082815260200191505060405180910390f35b3415607e57600080fd5b608460a0565b6040518082815260200191505060405180910390f35b60005481565b600060ab60005460b0565b905090565b60006007820290509190505600a165627a7a72305820ce3994eccf8989c24603717c6996c128cbde4dff903c7b3f6cd101c3ac6c092c0029",
              nonce: 10,
              r: "0x6db55d786e54d2f99befc78a28623548dac27e8b9b20b267a8681f9f79cec35a",
              s: "0x6ba72c168c000cbc7b8cc3c30eaa50b9afaf86fa90b259bc017042701dbe1090",
              to: null,
              transactionIndex: 0,
              v: "0x42",
              value: 0
          }]
      // 要进行挖矿,才能得到合约才能得到确认,本地测试网络必须是本节点挖矿,其他的节点挖矿不行。
      > miner.start()
      // 等到出现就代表着合约部署完成
      Contract mined! address: 0x59e9808ff1ca975193801a96552e4883ebbcb26f transactionHash: 0x95ac41354a8bf5907a2c68365331b3adad2a9313691b41b103b74c20aa047c58
      // 查看第92号区块的信息 发现hash值与transactions中的值保持一致,说明数据已经写进入块了
      > eth.getBlock(92)
          {
            difficulty: 189762,
            extraData: "0xd883010702846765746887676f312e392e328664617277696e",
            gasLimit: 3925747580,
            gasUsed: 134976,
            hash: "0xb1b0e57bc1ecb95822945c4360ebd937f7d78e5e41610ad6d5fb82bcfb30378c",
            logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            miner: "0x4079a3f5ffeeb7a84a4a582e9fc5f25579c3bba0",
            mixHash: "0x1b3e18f44b4e2c2aca124811bd2affe4d9295541016191c9083829e8d5506d34",
            nonce: "0x5d02db68ddcd3c03",
            number: 92,
            parentHash: "0xe035d79196ffc1864b30bd47685860132dd12c425c3d268cd6604d23afdb2061",
            receiptsRoot: "0x57fa38ab7e361c5b9fb23ec518e103ecce8e219303b65a5a9f871d1b37656bcb",
            sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
            size: 895,
            stateRoot: "0x6c6daa8481c9293e7ff9a701c6f957b719b3f43f1bccc644067e1a4b9a84c3b7",
            timestamp: 1510226672,
            totalDifficulty: 21191635,
            transactions: ["0x6b02ebd337e7e48f858c387c24f1f1dbc2ead86027dd36b95a319fde4c1004e2"],
            transactionsRoot: "0x1a5035077c1cfdf8b10900b7847df60138968857c19c16d11383a7a4977da158",
            uncles: []
          }
      // 获得合约的实例,输出的最下面count就是我们公开的变量,getCount就是我们公开的方法
      > myContractInstance = contract.at(contractObject.address)
          {
            abi: [{
                constant: true,
                inputs: [],
                name: "count",
                outputs: [{...}],
                payable: false,
                stateMutability: "view",
                type: "function"
            }, {
                constant: true,
                inputs: [],
                name: "getCount",
                outputs: [{...}],
                payable: false,
                stateMutability: "view",
                type: "function"
            }],
            address: "0x2f58bd410dc3494cf801aeb5907c6cd154360ad2",
            transactionHash: null,
            allEvents: function(),
            count: function(),
            getCount: function()
          }
      // 调用变量输出变量值
      > myContractInstance.count.call()
          7
      // 调用方法,输出返回的值
      > myContractInstance.getCount.call()
          49
      

参考资料
编译器官方代码solidity
solidity官方开发文档
浏览器端的编译网站
Ethereum 智能合约实战

geth1.6部署智能合约
Ethereum 智能合约实战
ethereum-learn学习笔记
stackexchange: How to compile Solidity contracts with Geth v1.6?
直接在1.6之后使用之前的代码执行会提醒eth_compileSolidity,官方讨论
老的版本介绍基础知识可以参考学习:以太坊智能合约编程之菜鸟教程
深入解析调用合约的三种方法

相关文章

网友评论

      本文标题:智能合约简单编程

      本文链接:https://www.haomeiwen.com/subject/iuzgeqtx.html