智能合約源碼解析之Bridge Contract 原

 

源代碼

算法描述參見我的博客文章- 有效的在基於以太坊EVM的鏈之間跨鏈,下面主要分析智能合約代碼: 

Bridge.sol

數據結構

Validator的獎勵:

reward = base + a*n (n是Header中提議的塊數 = end-start)

struct Reward {
    uint256 base;
    uint256 a;
}

Reward reward;
uint256 public maxReward;

Epoch隨機數種子

bytes32 public epochSeed = keccak256(block.difficulty + block.number + now);

 籌碼/保證金(Stake)

struct Stake {           // Validator預付的保證金金額及validator的地址
    uint256 amount;
    address staker;
}
mapping(address => uint256) stakers;   // Validator Map
Stake[] stakes;                        // 保證金數組
uint256 public stakeSum;               // 保證金總額
address public stakeToken;             // 保證金的幣種

全局變量


// 連續塊頭的默克爾樹的根
mapping(address => bytes32[]) roots;

// 每一個橋接鏈的最後一塊的塊號
mapping(address => uint256) lastBlock;

// 只有Admin才能創建和建立側鏈和主鏈的映射
// fromChainId => (oldTokenAddr => newTokenAddr)
mapping(address => mapping(address => address)) tokens;Block


// 對一個給定的鏈,一個特定的EPOCH,記錄開始塊和終塊並提供Headerroot
event RootStorage(address indexed chain, uint256 indexed start,
    uint256 indexed end, bytes32 headerRoot, uint256 i, address proposer);
event Deposit(address indexed user, address indexed toChain,
    address indexed depositToken, address fromChain, uint256 amount);
event Withdraw(address indexed user, address indexed fromChain,
    address indexed withdrawToken, uint256 amount);
event TokenAdded(address indexed fromChain, address indexed origToken,
    address indexed newToken);
event TokenAssociated(address indexed toChain, address indexed fromToken,
    address indexed toToken);

提幣

  // Pending withdrawals. The user prepares a withdrawal with tx data and then
  // releases it with a withdraw. It can be overwritten by the user and gets wiped
  // upon withdrawal.
  struct Withdrawal {
    address withdrawToken;          // Token to withdraw (i.e. the one mapped to deposit)
    address fromChain;
    uint256 amount;         // Number of atomic units to withdraw
    bytes32 txRoot;         // Transactions root for the block housing this tx
    bytes32 txHash;         // Hash of this tx
    bytes32 receiptsRoot;   // Receipts root for the block housing this tx
  }
  mapping(address => Withdrawal) pendingWithdrawals;

 

主要函數

保證金/Stake

stake(uint256 amount)

以特定的幣種充值保證金。設置充值幣種,充值數額/總額,存入Validator數組

destake(uint256 amount)

撤銷保證金。調整充值數額/總額

function proposeRoot(bytes32 headerRoot, address chainId, uint256 end, bytes sigs)

將Headerroot存入roots數組

計算獎勵金額併發送

生成EpochSeed=keccak256(block.difficulty + block.number + now);

發送RootStorage Event

記錄本Epoch的Last Block

Helper函數

function toBytes(address a) constant returns (bytes b) 

function toBytes(uint256 x) returns (bytes b) 

function encodeAddress(address a) returns(bytes) 


function getStake(address a) public constant returns (uint256) 

function getStakeIndex(address a) public constant returns (uint256) 

function getLastBlock(address fromChain) public constant returns (uint256) 

// 挑選提議者。被挑中的概率取決於保證金額大小
function getProposer() public constant returns (address) 

function getTokenMapping(address chain, address token) public constant returns (address) 

// 取32 bytes強制類型轉換成byes32
function getBytes32(uint64 start, bytes data) pure returns (bytes32) 
// 取32 bytes強制類型轉換成uint256
function getUint256(uint64 start, bytes data) pure returns (uint256)

// 取8 bytes強制類型轉換成uint64
function getUint64(uint64 start, bytes data) pure returns (uint64) 

// 'proof' is a concatenated set of [right][hash], i.e. 33 byte chunks
function merkleProof(bytes32 leaf, bytes32 targetHash, bytes proof) private constant returns (bool) 


// Change the number of validators required to allow a passed header root
function updateValidatorThreshold(uint256 newThreshold) public onlyAdmin()

// The admin can update the reward at any time.
function updateReward(uint256 base, uint256 a, uint256 max) public onlyAdmin() 

// 保證金幣種只能在實例初始化的時候設定
function Bridge(address token) 

modifier onlyAdmin() 

 

部署

參考 這個源代碼

client --add http://localhost:7545,0x27fa13e74d1aff21d18119053fbbe1b7e10ba0d0,http://localhost:8545,0xb85cae815b3f05b0c8c8f277312dba1f747d3171
  1. 將2個一模一樣的Bridge合約部署到兩個基於EVM的鏈上。(一個稱爲主鏈,一個爲側鏈)
  2. 參與者通過調用Bridge.stake()預繳保證金(stake),進入Proposer候補池
  3. 每當數據送到了Bridge contract,就依據保證金大小,選擇一個新的Proposer
  4. 這個Proposer聆聽側鏈的消息,收集塊頭。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章