您正在查看: Ethereum-开源推荐 分类下的文章

基于DPOS协议Eth侧链的去中心化IBC方案

背景

为了实现已以太坊为资金链,另一个高TPS的链做应用链,之前已经计划做EOS2.0链的深度定制,以满足eth地址体系。由于为了尽快接入Eth生态,所以最近基于Eth做了共识方面定制,修改为DPOS共识。
目前一期先已以太坊侧链做应用链,后期根据生态需要,计划会继续之前的基于EOS做侧链,由于生态,账户体系,资源模型问题,暂时延后,后面考虑再做一层转换。
目前的侧链百花齐放,但侧链与以太坊之前的代币划转,都是通过中心化服务,保存eth公链与侧链两个锁定地址的私钥,然后进行双向转账的。这样由于私钥保存以及项目方等问题就影响了资金池的安全。

去中心化IBC方案

Eth公链到Eth侧链

Eth公链部署一个IBC合约A,此合约地址接收用户跨链转账。
此IBC合约中维护着当前Eth侧链的21个正在出块BP地址,如果Eth侧链BP地址有变更,及时会更新此合约。
Eth侧链也部署着另一个IBC合约B。
Eth侧链21个正在出块的BP节点监测Eth公链上此IBC合约A的转入交易,当交易不可逆时,提交此交易并投票到Eth侧链IBC合约B中,当此交易投票达到 2/3+1 时,此交易达到执行条件,会从当前侧链IBC合约地址B中转出相应的代币到Eth侧链用户同样的账户地址中。

Eth侧链到Eth公链

用户在Eth侧链中将对应的代币转到Eth侧链IBC合约B中,Eth侧链各BP节点监测此交易到达不可逆时,分别向Eth公链IBC合约A中发起转账请求,当达到2/3+1 时,此交易达到执行条件,会从当前Eth公链IBC合约A中转出相应的代币到Eth公链用户同样的账户地址中。

去中心化分析

对于eth公链和侧链的两个账户接收地址,都是需要侧链当前出块BP总数的2/3+1授权才能转移资金的,所以实现了去中心化,保证了资金池的安全

使用web3.js监听以太坊智能合约event

var Web3 = require("web3")

var web3;

if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    web3 = new Web3(new Web3.providers.WebsocketProvider("ws://172.17.116.158:8546"));
}

var contractAbi = [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogCreateProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogPassProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogRejectProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"val","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogSetUnpassed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"bool","name":"auth","type":"bool"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LogVote","type":"event"},{"inputs":[],"name":"MaxValidators","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MinimalStakingCoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSAL_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ProposalAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PunishContractAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"StakingLockPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ValidatorContractAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WithdrawProfitPeriod","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pass","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalLastingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"proposals","outputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"string","name":"details","type":"string"},{"internalType":"uint256","name":"createTime","type":"uint256"},{"internalType":"uint16","name":"agree","type":"uint16"},{"internalType":"uint16","name":"reject","type":"uint16"},{"internalType":"bool","name":"resultExist","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"val","type":"address"},{"internalType":"address","name":"punish","type":"address"},{"internalType":"address","name":"proposal","type":"address"}],"name":"setContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"miner_","type":"address"}],"name":"setMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"votes","outputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256","name":"voteTime","type":"uint256"},{"internalType":"bool","name":"auth","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"vals","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"string","name":"details","type":"string"}],"name":"createProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bool","name":"auth","type":"bool"}],"name":"voteProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"val","type":"address"}],"name":"setUnpassed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}];

var contractaAddress = "0x000000000000000000000000000000000000F002";

MyContract = new web3.eth.Contract(contractAbi, contractaAddress);
                //console.log(MyContract.events.orderlog);

var myEvent = MyContract.events.LogCreateProposal({
        filter:{},
        fromBlock: 0
}, function(error, event){})
        .on('data', function(event){
        console.log(event); // same results as the optional callback above
})
        .on('changed', function(event){
                    // remove event from local database
        })        
    .on('error', console.error);

运行

npm init -y
npm install web3 --save
node map_event.js

测试数据

{
  address: '0x000000000000000000000000000000000000F002',
  blockNumber: 64274,
  transactionHash: '0x950203bc5d391a6b8180c5be6d290403f39fe81a8666e40b74cc3b9b094ce1a6',
  transactionIndex: 0,
  blockHash: '0x9abb16d015c49268c04909bcea414994d9bc0867dc8648b5e3dd33071d86daf5',
  logIndex: 0,
  removed: false,
  id: 'log_14a4176e',
  returnValues: Result {
    '0': '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
    '1': '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    '2': '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    '3': '1614340623',
    id: '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
    proposer: '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    dst: '0xc65dD4299C682f335d6e15e2B5774D015E01E479',
    time: '1614340623'
  },
  event: 'LogCreateProposal',
  signature: '0xc10f2f4d53a0e342536c6af3cce9c6ee25c32dbb323521ce0e1d4494a3e362e8',
  raw: {
    data: '0x000000000000000000000000000000000000000000000000000000006038e20f',
    topics: [
      '0xc10f2f4d53a0e342536c6af3cce9c6ee25c32dbb323521ce0e1d4494a3e362e8',
      '0x88437e94b8ffc61e30087ba66182c8f291e4af36d289ae299f676f014fdba411',
      '0x000000000000000000000000c65dd4299c682f335d6e15e2b5774d015e01e479',
      '0x000000000000000000000000c65dd4299c682f335d6e15e2b5774d015e01e479'
    ]
  }

参考

https://www.cnblogs.com/tokenpai/p/10334952.html

基于以太坊支持数据隐私

官网:https://consensys.net/
开源地址: https://github.com/ConsenSys/quorum

详细介绍:https://rdc.hundsun.com/portal/article/892.html

Quorum是一个基于以太坊的分布式账本协议,具有交易/合同隐私和新的共识机制。

Quorum是go-ethereum的一个分支,并根据go-ethereum发行版进行了更新。

以太坊的主要增强功能:

  • 隐私-Quorum通过公共/私有状态分离来支持私有交易和私有合同,并利用对等加密消息交换(请参阅Constellation和Tessera)将私有数据定向传输到网络参与者

  • 替代共识机制-Quorum不需要在许可的网络中使用POW / POS,而是提供了多个更适合联盟链的共识机制:

    • 基于筏的共识-一种共识模型,可加快区块时间,完成交易并按需创建区块
    • Istanbul BFT-由AMIS启发,具有PBFT的交易最终性的共识算法。
    • Clique POA共识-与Go Ethereum捆绑在一起的默认POA共识算法。
  • 对等权限-节点/对等权限,确保只有已知方才能加入网络

  • 帐户管理-Quorum引入了帐户插件,该插件使Quorum或clef可以通过包括外部库在内的其他帐户管理方法进行扩展。

  • 可插拔架构-允许将其他功能作为插件添加到核心geth,从而提供可扩展性,灵活性和Quorum功能的独特隔离。

  • 更高的性能-Quorum提供的性能吞吐量比公共场所高得多

IBFT共识概述: https://docs.goquorum.consensys.net/en/stable/Concepts/Consensus/IBFT/
https://www.jianshu.com/p/43354a82e176

Heco系统合约分析

官方文档:https://docs.hecochain.com/#/consensus?id=%e7%b3%bb%e7%bb%9f%e5%90%88%e7%ba%a6
合约源代码:https://github.com/HuobiGroup/huobi-eco-contracts

系统合约

目前验证人的管理,均由系统合约完成,目前的系统合约有:

  • Proposal 负责管理验证人的准入资格,管理验证人提案和投票;
  • Validators 负责对验证人进行排名管理、质押和解质押操作、分发区块奖励等;
  • Punish 负责对不正常工作的活跃验证人进行惩罚操作;

区块链调用系统合约

  • 每个块结束的时候,会调用Validators合约,将区块中所有交易的手续费分发给active validator;
  • 发现validator没有正常工作的时候,会调用Punish合约,对validator进行惩罚;
  • 每个epoch结束的时候,会调用Validators合约,根据排名,更新active validator;

质押

任何账户,都可以对validator进行任意数量的质押操作,每个validator的最小质押量是32HT。 如果想取回已质押的HT,需要按照如下操作进行:

  1. 发送调用Validators合约,发送针对某一个validator的解质押(unstake)的声明交易;
  2. 等待86400个块之后,调用Validators合约,发送提取质押(withdrawStaking)的交易,将所有在此validator的质押取回;

惩罚措施

每当发现验证人没有按照预先设定进行出块的时候,就会在这个块结束时,自动调用Punish合约,对验证人进行计数。当计数达到24时,罚没验证人的所有收入。当计数达到48时,将验证人移除出活跃验证人列表,同时取消验证人资格。

合约初始化

系统合约会在第一区块时被全部初始化
(github code)
(github code2)

// Initialize all system contracts at block 1.
if header.Number.Cmp(common.Big1) == 0 {
    if err := c.initializeSystemContracts(chain, header, state); err != nil { // 在此初始化三个系统合约
        log.Error("Initialize system contracts failed", "err", err)
        return err
    }
}

取消验证验证者资格

当前验证者至少需要保留一个
https://github.com/HuobiGroup/huobi-eco-contracts/blob/d01906925c8ea017334df2e725134de0c22a17a2/contracts/Validators.sol#L757

function tryRemoveValidatorInHighestSet(address val) private {
        for (
            uint256 i = 0;
            // ensure at least one validator exist
            i < highestValidatorsSet.length && highestValidatorsSet.length > 1; // 当前验证者至少保留一个
            i++
        ) 
  1. 当前所在投票数落后于 最大验证者数(排名大于MaxValidators 21)
    https://github.com/HuobiGroup/huobi-eco-contracts/blob/d01906925c8ea017334df2e725134de0c22a17a2/contracts/Validators.sol#L611
  2. 到达惩罚条件
    https://github.com/HuobiGroup/huobi-eco-contracts/blob/d01906925c8ea017334df2e725134de0c22a17a2/contracts/Punish.sol#L68
  3. 投票数小于MinimalStakingCoin
    https://github.com/HuobiGroup/huobi-eco-contracts/blob/d01906925c8ea017334df2e725134de0c22a17a2/contracts/Validators.sol#L336

编译合约

修改solc的依赖版本

 // Configure your compilers
  compilers: {
    solc: {
      version: "^0.6.1", // 修改为该版本以上,不然会报找不到对应的版本,此时会下载0.6.12版本

编译合约

truffle compile

此时会在./build/contracts下生成各个合约对应的abi json文件

参考

https://ethereum.stackexchange.com/questions/234/what-is-an-abi-and-why-is-it-needed-to-interact-with-contracts
https://ethereum.stackexchange.com/questions/1437/do-i-need-a-compiled-contract-just-to-get-the-abi-definition
https://zhuanlan.zhihu.com/p/26089385