zoukankan      html  css  js  c++  java
  • 以太坊私有链部署合约

    以太坊私有链部署合约

    1.建立私有链

    [root@greg02 ~]#mkdir mychain
    [root@greg02 ~]#cd mychain
    [root@greg02 mychain]#geth --networkid 123 --dev --datadir data1 --rpc --rpcaddr 192.168.179.130 --rpcport 8989 --port 3000
    
    #运行后产生如下文件
    [root@greg02 mychain]#ls
    data1
    [root@greg02 mychain]#ls data1/
    geth  geth.ipc  keystore
    

    各项含义:

    --identity:指定节点 ID;
    --rpc:表示开启 HTTP-RPC 服务;
    --rpcaddr:HTTP-RPC 服务ip地址;
    --rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545);
    --datadir:指定区块链数据的存储位置;
    --port:指定和其他节点连接所用的端口号(默认为 30303);
    --nodiscover:关闭节点发现机制,防止加入有同样初始配置的陌生节点。
    

    保持节点的运行,不要关闭终端,重新打开一个终端,使用geth attach连接节点,并且打开geth console

    [root@greg02 mychain]#geth attach ipc:/root/mychain/data1/geth.ipc
    Welcome to the Geth JavaScript console!
    
    instance: Geth/v1.8.3-unstable-746392cf/linux-amd64/go1.9.2
    coinbase: 0x804bf1ee046894d6425a8bed1abe553f776ae0df
    at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
     datadir: /root/mychain/data1
     modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0
    
    > 
    

    这是一个交互式的 JavaScript 执行环境,在这里面可以执行 JavaScript 代码,其中 > 是命令提示符。在这个环境里也内置了一些用来操作以太坊的 JavaScript 对象,可以直接使用这些对象。这些对象主要包括:

    eth:包含一些跟操作区块链相关的方法;
    net:包含一些查看p2p网络状态的方法;
    admin:包含一些与管理节点相关的方法;
    miner:包含启动&停止挖矿的一些方法;
    personal:主要包含一些管理账户的方法;
    txpool:包含一些查看交易内存池的方法;
    web3:包含了以上对象,还包含一些单位换算的方法。
    

    2.创建账户

    > personal.newAccount('grego') 
    "0x88d6725760f34a91059485e396759d422441e427"
    > personal.listAccounts
    ["0x804bf1ee046894d6425a8bed1abe553f776ae0df"
    > web3.eth.coinbase 
    "0x804bf1ee046894d6425a8bed1abe553f776ae0df"
    

    3.编写只能合约

    pragma solidity ^0.4.0;
    contract Ballot {
    
        struct Voter {
            uint weight;
            bool voted;
            uint8 vote;
            address delegate;
        }
        struct Proposal {
            uint voteCount;
        }
    
        address chairperson;
        mapping(address => Voter) voters;
        Proposal[] proposals;
    
        /// Create a new ballot with $(_numProposals) different proposals.
        function Ballot(uint8 _numProposals) public {
            chairperson = msg.sender;
            voters[chairperson].weight = 1;
            proposals.length = _numProposals;
        }
    
        /// Give $(toVoter) the right to vote on this ballot.
        /// May only be called by $(chairperson).
        function giveRightToVote(address toVoter) public {
            if (msg.sender != chairperson || voters[toVoter].voted) return;
            voters[toVoter].weight = 1;
        }
    
        /// Delegate your vote to the voter $(to).
        function delegate(address to) public {
            Voter storage sender = voters[msg.sender]; // assigns reference
            if (sender.voted) return;
            while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
                to = voters[to].delegate;
            if (to == msg.sender) return;
            sender.voted = true;
            sender.delegate = to;
            Voter storage delegateTo = voters[to];
            if (delegateTo.voted)
                proposals[delegateTo.vote].voteCount += sender.weight;
            else
                delegateTo.weight += sender.weight;
        }
    
        /// Give a single vote to proposal $(toProposal).
        function vote(uint8 toProposal) public {
            Voter storage sender = voters[msg.sender];
            if (sender.voted || toProposal >= proposals.length) return;
            sender.voted = true;
            sender.vote = toProposal;
            proposals[toProposal].voteCount += sender.weight;
        }
    
        function winningProposal() public constant returns (uint8 _winningProposal) {
            uint256 winningVoteCount = 0;
            for (uint8 prop = 0; prop < proposals.length; prop++)
                if (proposals[prop].voteCount > winningVoteCount) {
                    winningVoteCount = proposals[prop].voteCount;
                    _winningProposal = prop;
                }
        }
    }
    

    BYTECODE:

    
    

    ABI:

    [
    	{
    		"constant": false,
    		"inputs": [
    			{
    				"name": "to",
    				"type": "address"
    			}
    		],
    		"name": "delegate",
    		"outputs": [],
    		"payable": false,
    		"stateMutability": "nonpayable",
    		"type": "function"
    	},
    	{
    		"constant": true,
    		"inputs": [],
    		"name": "winningProposal",
    		"outputs": [
    			{
    				"name": "_winningProposal",
    				"type": "uint8"
    			}
    		],
    		"payable": false,
    		"stateMutability": "view",
    		"type": "function"
    	},
    	{
    		"constant": false,
    		"inputs": [
    			{
    				"name": "toVoter",
    				"type": "address"
    			}
    		],
    		"name": "giveRightToVote",
    		"outputs": [],
    		"payable": false,
    		"stateMutability": "nonpayable",
    		"type": "function"
    	},
    	{
    		"constant": false,
    		"inputs": [
    			{
    				"name": "toProposal",
    				"type": "uint8"
    			}
    		],
    		"name": "vote",
    		"outputs": [],
    		"payable": false,
    		"stateMutability": "nonpayable",
    		"type": "function"
    	},
    	{
    		"inputs": [
    			{
    				"name": "_numProposals",
    				"type": "uint8"
    			}
    		],
    		"payable": false,
    		"stateMutability": "nonpayable",
    		"type": "constructor"
    	}
    ]
    

    ABI删除空格并转义

    [{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"_winningProposal","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"toVoter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"toProposal","type":"uint8"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_numProposals","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
    

    在console里创建ABI合约对象

    > var abi=JSON.parse('[{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"_winningProposal","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"toVoter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"toProposal","type":"uint8"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_numProposals","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]')
    undefined
    > myContract=web3.eth.contract(abi)
    {
      abi: [{
          constant: false,
          inputs: [{...}],
          name: "delegate",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          constant: true,
          inputs: [],
          name: "winningProposal",
          outputs: [{...}],
          payable: false,
          stateMutability: "view",
          type: "function"
      }, {
          constant: false,
          inputs: [{...}],
          name: "giveRightToVote",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          constant: false,
          inputs: [{...}],
          name: "vote",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          inputs: [{...}],
          payable: false,
          stateMutability: "nonpayable",
          type: "constructor"
      }],
      eth: {
        accounts: ["0x804bf1ee046894d6425a8bed1abe553f776ae0df", "0x88d6725760f34a91059485e396759d422441e427", "0x44d18ce9e2e54c93cf382e0a1e571e5e16173156"],
        blockNumber: 0,
        coinbase: "0x804bf1ee046894d6425a8bed1abe553f776ae0df",
        compile: {
          lll: function(),
          serpent: function(),
          solidity: function()
        },
        defaultAccount: undefined,
        defaultBlock: "latest",
        gasPrice: 1,
        hashrate: 0,
        mining: true,
        pendingTransactions: [],
        protocolVersion: "0x3f",
        syncing: false,
        call: function(),
        contract: function(abi),
        estimateGas: function(),
        filter: function(options, callback, filterCreationErrorCallback),
        getAccounts: function(callback),
        getBalance: function(),
        getBlock: function(),
        getBlockNumber: function(callback),
        getBlockTransactionCount: function(),
        getBlockUncleCount: function(),
        getCode: function(),
        getCoinbase: function(callback),
        getCompilers: function(),
        getGasPrice: function(callback),
        getHashrate: function(callback),
        getMining: function(callback),
        getPendingTransactions: function(callback),
        getProtocolVersion: function(callback),
        getRawTransaction: function(),
        getRawTransactionFromBlock: function(),
        getStorageAt: function(),
        getSyncing: function(callback),
        getTransaction: function(),
        getTransactionCount: function(),
        getTransactionFromBlock: function(),
        getTransactionReceipt: function(),
        getUncle: function(),
        getWork: function(),
        iban: function(iban),
        icapNamereg: function(),
        isSyncing: function(callback),
        namereg: function(),
        resend: function(),
        sendIBANTransaction: function(),
        sendRawTransaction: function(),
        sendTransaction: function(),
        sign: function(),
        signTransaction: function(),
        submitTransaction: function(),
        submitWork: function()
      },
      at: function(address, callback),
      getData: function(),
      new: function()
    }
    

    检查coinbase账号余额

    > account1=web3.eth.coinbase
    "0x804bf1ee046894d6425a8bed1abe553f776ae0df"
    > web3.eth.getBalance(account1)
    1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+77
    

    解锁coinbase账号

    > web3.eth.coinbase 
    "0x804bf1ee046894d6425a8bed1abe553f776ae0df"
    > personal.unlockAccount(account1, '')
    true
    

    BYTECODE预估费用

    > web3.eth.estimateGas({data:bytecode})
    597031
    

    字节码前面需要添加0x。手续费大概为597031``gas

    部署合约

    > contractInstance = myContract.new({data: bytecode gas: 1000000, from: account1}, function(e, contract){
    ......   if(!e){
    .........     if(!contract.address){
    ............       console.log("Contract transaction send: Transaction Hash: "+contract.transactionHash+" waiting to be mined...");
    ............     }else{
    ............       console.log("Contract mined! Address: "+contract.address);
    ............       console.log(contract);
    ............     }
    .........   }else{
    .........     console.log(e)
    .........   }
    ...... })
    Contract transaction send: Transaction Hash: 0xca1561453f4cc9541ec84dd4ef3a25cbb61ef4d1e9bf1f829fef5107f9017266 waiting to be mined...
    {
      abi: [{
          constant: false,
          inputs: [{...}],
          name: "delegate",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          constant: true,
          inputs: [],
          name: "winningProposal",
          outputs: [{...}],
          payable: false,
          stateMutability: "view",
          type: "function"
      }, {
          constant: false,
          inputs: [{...}],
          name: "giveRightToVote",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          constant: false,
          inputs: [{...}],
          name: "vote",
          outputs: [],
          payable: false,
          stateMutability: "nonpayable",
          type: "function"
      }, {
          inputs: [{...}],
          payable: false,
          stateMutability: "nonpayable",
          type: "constructor"
      }],
      address: undefined,
      transactionHash: "0xca1561453f4cc9541ec84dd4ef3a25cbb61ef4d1e9bf1f829fef5107f9017266"
    }
    

    合约等待挖矿

    > miner.start()
    null
    > miner.stop()
    true
    
  • 相关阅读:
    AutoCAD.Net/C#.Net QQ群:193522571 resultbuffer 中的typedvalue
    AutoCAD.Net/C#.Net QQ群:193522571 32位进程无法访问64位进程模块,解决getprocesses方法对32位无效的问题
    AutoCAD.Net/C#.Net QQ群:193522571 随机数
    AutoCAD.Net/C#.Net QQ群:193522571:取得当前方法名、父方法名
    每次打开office2007都会弹出安装autocad2007,如何解决?
    在自定义控件中,定义枚举类型需要使其首项默认值为0
    VS整死了,属性惹的祸
    委托的使用,排序
    为C#自定义控件添加自定义事件
    C#获取字符串宽度像素
  • 原文地址:https://www.cnblogs.com/ningxin18/p/8647115.html
Copyright © 2011-2022 走看看