diff --git a/README.md b/README.md index a8393852c..4fe22a6da 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ node generate-systemReward.js --mock true node generate-validatorset.js --mock true node generate-system.js --mock true node generate-crosschain.js --mock true -node generate-govhub.js --mock true node generate-tokenhub.js --mock true node generate-tendermintlightclient.js --mock true node generate-relayerincentivizecontract.js --roundSize 30 --maximumWeight 3 --mock true diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index f40f44a71..c057d1170 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -1,9 +1,7 @@ pragma solidity 0.6.4; import "./System.sol"; -import "./Seriality/TypesToBytes.sol"; import "./Seriality/BytesToTypes.sol"; -import "./Seriality/BytesLib.sol"; import "./Seriality/Memory.sol"; import "./interface/ILightClient.sol"; import "./interface/ISlashIndicator.sol"; @@ -13,34 +11,42 @@ import "./interface/IParamSubscriber.sol"; import "./interface/IBSCValidatorSet.sol"; import "./interface/IApplication.sol"; import "./lib/SafeMath.sol"; +import "./rlp/RLPDecode.sol"; +import "./rlp/CmnPkg.sol"; contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplication { using SafeMath for uint256; - // {20 bytes consensusAddress} + {20 bytes feeAddress} + {20 bytes BBCFeeAddress} + {8 bytes voting power} - uint constant VALIDATOR_BYTES_LENGTH = 68; + using RLPDecode for *; + // will not transfer value less than 0.1 BNB for validators uint256 constant public DUSTY_INCOMING = 1e17; uint8 public constant JAIL_MESSAGE_TYPE = 1; uint8 public constant VALIDATORS_UPDATE_MESSAGE_TYPE = 0; - uint8 public constant CHANNEL_ID = 0x08; // the precision of cross chain value transfer. uint256 constant PRECISION = 1e10; uint256 constant EXPIRE_TIME_SECOND_GAP = 1000; - bytes public constant INIT_VALIDATORSET_BYTES = hex"009fb29aac15b9a4b7f17c3385939b007540f4d7919fb29aac15b9a4b7f17c3385939b007540f4d7919fb29aac15b9a4b7f17c3385939b007540f4d7910000000000000064"; + bytes public constant INIT_VALIDATORSET_BYTES = hex"f84580f842f840949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164"; + + uint32 public constant CODE_OK = 0; + uint32 public constant ERROR_FAIL_DECODE = 101; + uint32 public constant ERROR_UNKNOWN_PACKAGE_TYPE = 102; + uint32 public constant ERROR_FAIL_CHECK_VALIDATORS = 103; + uint32 public constant ERROR_LEN_OF_VAL_MISMATCH = 104; + uint32 public constant ERROR_RELAYFEE_TOO_LARGE = 105; + - // state of this contract + /*********************** state of the contract **************************/ Validator[] public currentValidatorSet; - uint64 public sequence; - uint64 public felonySequence; - uint256 public totalInComing; uint256 public expireTimeSecondGap; uint64 public previousDepositHeight; + uint256 public totalInComing; + // key is the `consensusAddress` of `Validator`, // value is the index of the element in `currentValidatorSet`. mapping(address =>uint256) currentValidatorSetMap; @@ -50,21 +56,19 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica address payable feeAddress; address BBCFeeAddress; uint64 votingPower; + + // only in state bool jailed; uint256 incoming; } - modifier sequenceInOrder(uint64 _sequence) { - require(_sequence == sequence, "sequence not in order"); - _; - sequence ++; - } - - modifier enoughInComing() { - require(address(this).balance>=totalInComing, "panic: no enough incoming to distribute"); - _; + /*********************** cross chain package **************************/ + struct IbcValidatorSetPackage { + uint8 packageType; + Validator[] validatorSet; } + /*********************** modifiers **************************/ modifier noEmptyDeposit() { require(msg.value > 0, "deposit value is zero"); _; @@ -76,6 +80,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica previousDepositHeight = uint64(block.number); } + /*********************** events **************************/ event validatorSetUpdated(); event validatorJailed(address indexed validator); event validatorEmptyJailed(address indexed validator); @@ -88,23 +93,48 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event deprecatedDeposit(address indexed validator, uint256 amount); event validatorDeposit(address indexed validator, uint256 amount); event validatorMisdemeanor(address indexed validator, uint256 amount); - event validatorFelony(uint64 indexed sequence, address indexed validator, uint256 amount); + event validatorFelony(address indexed validator, uint256 amount); event failReasonWithStr(string message); event paramChange(string key, bytes value); + /*********************** init **************************/ function init() external onlyNotInit{ - (Validator[] memory validatorSet, bool valid, string memory errMsg)= parseValidatorSet(INIT_VALIDATORSET_BYTES); - require(valid, errMsg); - for(uint i = 0;i= DUSTY_INCOMING){ crossSize ++; }else if (currentValidatorSet[i].incoming > 0){ directSize ++; } } + //cross transfer address[] memory crossAddrs = new address[](crossSize); uint256[] memory crossAmounts = new uint256[](crossSize); @@ -211,14 +214,18 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica delete directSize; Validator[] memory validatorSetTemp = validatorSet; // fix error: stack too deep, try removing local variables (uint256 syncRelayFee, uint256 ackRelayFee) = ITokenHub(TOKEN_HUB_ADDR).getRelayFee(); - for(uint i = 0;i DUSTY_INCOMING){ + emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); + return ERROR_RELAYFEE_TOO_LARGE; + } + for(uint i = 0;i= DUSTY_INCOMING){ crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; crossAmounts[crossSize] = value.sub(syncRelayFee).sub(ackRelayFee); crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; crossIndexes[crossSize] = i; - crossTotal += value; + crossTotal = crossTotal.add(value); crossSize ++; }else if (currentValidatorSet[i].incoming > 0){ directAddrs[directSize] = currentValidatorSet[i].feeAddress; @@ -230,7 +237,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica //step 2: do cross chain transfer bool failCross = false; if(crossTotal > 0){ - uint256 relayFee = crossAddrs.length*(syncRelayFee.add(ackRelayFee)); try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value:crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { if (success) { emit batchTransfer(crossTotal); @@ -258,7 +264,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - + // step 3: direct transfer if(directAddrs.length>0){ for(uint i = 0;i0){ emit systemTransfer(address(this).balance); - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(address(this).balance); + address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance); } + // step 5: do update validator set state totalInComing = 0; - // do update state if(validatorSetTemp.length>0){ doUpdateState(validatorSetTemp); } - // do claim reward, will reward to account rather than smart contract. + // step 6: clean slash contract ISlashIndicator(SLASH_CONTRACT_ADDR).clean(); emit validatorSetUpdated(); + return CODE_OK; } function getValidators()external view returns(address[] memory) { @@ -315,7 +321,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** For slash **************************/ - function misdemeanor(address validator)external onlySlash override{ uint256 index = currentValidatorSetMap[validator]; if(index <= 0){ @@ -357,8 +362,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica currentValidatorSet[index].incoming = 0; return; } - emit validatorFelony(felonySequence,validator,income); - felonySequence ++; + emit validatorFelony(validator,income); delete currentValidatorSetMap[validator]; // It is ok that the validatorSet is not in order. if (index != currentValidatorSet.length-1){ @@ -374,6 +378,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. } + /*********************** Param update ********************************/ function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov{ if (Memory.compareStrings(key, "expireTimeSecondGap")){ @@ -389,35 +394,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica /*********************** Internal Functions **************************/ - function getMsgType(bytes memory msgBytes) internal pure returns(uint8){ - uint8 msgType = 0xff; - assembly { - msgType := mload(add(msgBytes, 1)) - } - return msgType; - } - - function parseValidatorSet(bytes memory validatorSetBytes) private pure returns(Validator[] memory, bool, string memory){ - uint length = validatorSetBytes.length-1; - if(length % VALIDATOR_BYTES_LENGTH != 0){ - return (new Validator[](0), false, "the length of validatorSetBytes should be times of 68"); - } - uint n = length/VALIDATOR_BYTES_LENGTH; - Validator[] memory validatorSet = new Validator[](n); - for(uint i = 0;iuint256) currentValidatorSetMap; @@ -50,21 +56,19 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica address payable feeAddress; address BBCFeeAddress; uint64 votingPower; + + // only in state bool jailed; uint256 incoming; } - modifier sequenceInOrder(uint64 _sequence) { - require(_sequence == sequence, "sequence not in order"); - _; - sequence ++; - } - - modifier enoughInComing() { - require(address(this).balance>=totalInComing, "panic: no enough incoming to distribute"); - _; + /*********************** cross chain package **************************/ + struct IbcValidatorSetPackage { + uint8 packageType; + Validator[] validatorSet; } + /*********************** modifiers **************************/ modifier noEmptyDeposit() { require(msg.value > 0, "deposit value is zero"); _; @@ -76,6 +80,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica previousDepositHeight = uint64(block.number); } + /*********************** events **************************/ event validatorSetUpdated(); event validatorJailed(address indexed validator); event validatorEmptyJailed(address indexed validator); @@ -88,23 +93,48 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event deprecatedDeposit(address indexed validator, uint256 amount); event validatorDeposit(address indexed validator, uint256 amount); event validatorMisdemeanor(address indexed validator, uint256 amount); - event validatorFelony(uint64 indexed sequence, address indexed validator, uint256 amount); + event validatorFelony(address indexed validator, uint256 amount); event failReasonWithStr(string message); event paramChange(string key, bytes value); + /*********************** init **************************/ function init() external onlyNotInit{ - (Validator[] memory validatorSet, bool valid, string memory errMsg)= parseValidatorSet(INIT_VALIDATORSET_BYTES); - require(valid, errMsg); - for(uint i = 0;i= DUSTY_INCOMING){ crossSize ++; }else if (currentValidatorSet[i].incoming > 0){ directSize ++; } } + //cross transfer address[] memory crossAddrs = new address[](crossSize); uint256[] memory crossAmounts = new uint256[](crossSize); @@ -211,14 +214,18 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica delete directSize; Validator[] memory validatorSetTemp = validatorSet; // fix error: stack too deep, try removing local variables (uint256 syncRelayFee, uint256 ackRelayFee) = ITokenHub(TOKEN_HUB_ADDR).getRelayFee(); - for(uint i = 0;i DUSTY_INCOMING){ + emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); + return ERROR_RELAYFEE_TOO_LARGE; + } + for(uint i = 0;i= DUSTY_INCOMING){ crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; crossAmounts[crossSize] = value.sub(syncRelayFee).sub(ackRelayFee); crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; crossIndexes[crossSize] = i; - crossTotal += value; + crossTotal = crossTotal.add(value); crossSize ++; }else if (currentValidatorSet[i].incoming > 0){ directAddrs[directSize] = currentValidatorSet[i].feeAddress; @@ -230,7 +237,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica //step 2: do cross chain transfer bool failCross = false; if(crossTotal > 0){ - uint256 relayFee = crossAddrs.length*(syncRelayFee.add(ackRelayFee)); try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value:crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { if (success) { emit batchTransfer(crossTotal); @@ -258,7 +264,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - + // step 3: direct transfer if(directAddrs.length>0){ for(uint i = 0;i0){ emit systemTransfer(address(this).balance); - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(address(this).balance); + address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance); } + // step 5: do update validator set state totalInComing = 0; - // do update state if(validatorSetTemp.length>0){ doUpdateState(validatorSetTemp); } - // do claim reward, will reward to account rather than smart contract. + // step 6: clean slash contract ISlashIndicator(SLASH_CONTRACT_ADDR).clean(); emit validatorSetUpdated(); + return CODE_OK; } function getValidators()external view returns(address[] memory) { @@ -314,7 +320,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } return true; } - {% endif %} + {% endif %} function getIncoming(address validator)external view returns(uint256) { uint256 index = currentValidatorSetMap[validator]; if (index<=0){ @@ -324,7 +330,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** For slash **************************/ - function misdemeanor(address validator)external onlySlash override{ uint256 index = currentValidatorSetMap[validator]; if(index <= 0){ @@ -366,8 +371,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica currentValidatorSet[index].incoming = 0; return; } - emit validatorFelony(felonySequence,validator,income); - felonySequence ++; + emit validatorFelony(validator,income); delete currentValidatorSetMap[validator]; // It is ok that the validatorSet is not in order. if (index != currentValidatorSet.length-1){ @@ -383,6 +387,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. } + /*********************** Param update ********************************/ function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov{ if (Memory.compareStrings(key, "expireTimeSecondGap")){ @@ -398,35 +403,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica /*********************** Internal Functions **************************/ - function getMsgType(bytes memory msgBytes) internal pure returns(uint8){ - uint8 msgType = 0xff; - assembly { - msgType := mload(add(msgBytes, 1)) - } - return msgType; - } - - function parseValidatorSet(bytes memory validatorSetBytes) private pure returns(Validator[] memory, bool, string memory){ - uint length = validatorSetBytes.length-1; - if(length % VALIDATOR_BYTES_LENGTH != 0){ - return (new Validator[](0), false, "the length of validatorSetBytes should be times of 68"); - } - uint n = length/VALIDATOR_BYTES_LENGTH; - Validator[] memory validatorSet = new Validator[](n); - for(uint i = 0;i address) public channelHandlerContractMap; @@ -102,6 +101,10 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ isRelayRewardFromSystemReward[GOV_CHANNELID] = true; registeredContractMap[GOV_HUB_ADDR] = true; + channelHandlerContractMap[SLASH_CHANNELID] = SLASH_CONTRACT_ADDR; + isRelayRewardFromSystemReward[SLASH_CHANNELID] = true; + registeredContractMap[SLASH_CONTRACT_ADDR] = true; + alreadyInit=true; } @@ -194,7 +197,7 @@ function encodePayload(uint8 packageType, uint256 syncRelayFee, uint256 ackRelay if (packageType == SYNC_PACKAGE) { IRelayerIncentivize(INCENTIVIZE_ADDR).addReward(headerRelayer, msg.sender, syncRelayFee, isRelayRewardFromSystemReward[channelIdLocal]); address handlerContract = channelHandlerContractMap[channelIdLocal]; - try IApplication(handlerContract).handleSyncPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { + try IApplication(handlerContract).handleSynPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { emit crossChainPackage(bscChainID, channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(ACK_PACKAGE, 0, ackRelayFee, responsePayload)); } catch Error(string memory reason) { emit crossChainPackage(bscChainID, channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(FAIL_ACK_PACKAGE, 0, ackRelayFee, msgBytes)); @@ -236,35 +239,23 @@ function encodePayload(uint8 packageType, uint256 syncRelayFee, uint256 ackRelay function updateParam(string calldata key, bytes calldata value) onlyGov external override { bytes memory localKey = bytes(key); bytes memory localValue = value; - require(localKey.length == 1, "expected key length is 1"); - // length is 8, used to skip receive sequence + // first byte is channel Id, second byte is relayRewardFromSystemReward + require(localKey.length == 2, "expected key length is 2"); // length is 20, used to add or delete channel - require(localValue.length == 8 || localValue.length == 20, "expected value length is 8 or 20"); + require(localValue.length == 20, "expected value length is 20"); - uint256 bytes32Key; - assembly { - bytes32Key := mload(add(localKey, 1)) - } - uint8 channelId = uint8(bytes32Key); - - if (localValue.length == 8) { - uint64 sequence; - assembly { - sequence := mload(add(localValue, 8)) - } - require(channelReceiveSequenceMap[channelId] address) public channelHandlerContractMap; @@ -103,6 +102,10 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ isRelayRewardFromSystemReward[GOV_CHANNELID] = true; registeredContractMap[GOV_HUB_ADDR] = true; + channelHandlerContractMap[SLASH_CHANNELID] = SLASH_CONTRACT_ADDR; + isRelayRewardFromSystemReward[SLASH_CHANNELID] = true; + registeredContractMap[SLASH_CONTRACT_ADDR] = true; + alreadyInit=true; } @@ -195,7 +198,7 @@ function encodePayload(uint8 packageType, uint256 syncRelayFee, uint256 ackRelay if (packageType == SYNC_PACKAGE) { IRelayerIncentivize(INCENTIVIZE_ADDR).addReward(headerRelayer, msg.sender, syncRelayFee, isRelayRewardFromSystemReward[channelIdLocal]); address handlerContract = channelHandlerContractMap[channelIdLocal]; - try IApplication(handlerContract).handleSyncPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { + try IApplication(handlerContract).handleSynPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { emit crossChainPackage(bscChainID, channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(ACK_PACKAGE, 0, ackRelayFee, responsePayload)); } catch Error(string memory reason) { emit crossChainPackage(bscChainID, channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(FAIL_ACK_PACKAGE, 0, ackRelayFee, msgBytes)); @@ -237,35 +240,23 @@ function encodePayload(uint8 packageType, uint256 syncRelayFee, uint256 ackRelay function updateParam(string calldata key, bytes calldata value) onlyGov external override { bytes memory localKey = bytes(key); bytes memory localValue = value; - require(localKey.length == 1, "expected key length is 1"); - // length is 8, used to skip receive sequence + // first byte is channel Id, second byte is relayRewardFromSystemReward + require(localKey.length == 2, "expected key length is 2"); // length is 20, used to add or delete channel - require(localValue.length == 8 || localValue.length == 20, "expected value length is 8 or 20"); + require(localValue.length == 20, "expected value length is 20"); - uint256 bytes32Key; - assembly { - bytes32Key := mload(add(localKey, 1)) - } - uint8 channelId = uint8(bytes32Key); - - if (localValue.length == 8) { - uint64 sequence; - assembly { - sequence := mload(add(localValue, 8)) - } - require(channelReceiveSequenceMap[channelId]20 && newFelonyThreshold <= 1000, "the felonyThreshold out of range"); felonyThreshold = newFelonyThreshold; + }else if(Memory.compareStrings(key,"bscRelayerReward")){ + require(value.length == 32, "length of bscRelayerReward mismatch"); + uint256 newBscRelayerReward = BytesToTypes.bytesToUint256(32, value); + require(newBscRelayerReward > 1e18, "the bscRelayerReward out of range"); + bscRelayerReward = newBscRelayerReward; }else{ require(false, "unknown param"); } @@ -91,4 +132,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber{ Indicator memory indicator = indicators[validator]; return (indicator.height, indicator.count); } + + function encodeSlashPackage(address valAddr) internal view returns (bytes memory) { + bytes[] memory elements = new bytes[](4); + elements[0] = valAddr.encodeAddress(); + elements[1] = uint256(block.number).encodeUint(); + elements[2] = uint256(bscChainID).encodeUint(); + elements[3] = uint256(block.timestamp).encodeUint(); + return elements.encodeList(); + } } \ No newline at end of file diff --git a/contracts/System.sol b/contracts/System.sol index 7969251bb..6a1939fb2 100644 --- a/contracts/System.sol +++ b/contracts/System.sol @@ -13,6 +13,8 @@ contract System { uint8 constant public TRANSFER_OUT_CHANNELID = 0x03; uint8 constant public STAKING_CHANNELID = 0x08; uint8 constant public GOV_CHANNELID = 0x09; + uint8 constant public SLASH_CHANNELID = 0x0b; + uint16 constant bscChainID = 0x0060; address public constant VALIDATOR_CONTRACT_ADDR = 0x0000000000000000000000000000000000001000; address public constant SLASH_CONTRACT_ADDR = 0x0000000000000000000000000000000000001001; diff --git a/contracts/System.template b/contracts/System.template index 2109c5a9f..82abea037 100644 --- a/contracts/System.template +++ b/contracts/System.template @@ -13,6 +13,8 @@ contract System { uint8 constant public TRANSFER_OUT_CHANNELID = 0x03; uint8 constant public STAKING_CHANNELID = 0x08; uint8 constant public GOV_CHANNELID = 0x09; + uint8 constant public SLASH_CHANNELID = 0x0b; + uint16 constant bscChainID = 0x{{bscChainId}}; {% if mock %} address public VALIDATOR_CONTRACT_ADDR; address public SLASH_CONTRACT_ADDR; diff --git a/contracts/TokenHub.sol b/contracts/TokenHub.sol index dff6a189c..24089010b 100644 --- a/contracts/TokenHub.sol +++ b/contracts/TokenHub.sol @@ -148,7 +148,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return (syncRelayFee, ackRelayFee); } - function handleSyncPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ if (channelId == BIND_CHANNELID) { return handleBindSyncPackage(msgBytes); } else if (channelId == TRANSFER_IN_CHANNELID) { diff --git a/contracts/TokenHub.template b/contracts/TokenHub.template index b190a0d72..86b9359bc 100644 --- a/contracts/TokenHub.template +++ b/contracts/TokenHub.template @@ -154,7 +154,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return (syncRelayFee, ackRelayFee); } - function handleSyncPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ if (channelId == BIND_CHANNELID) { return handleBindSyncPackage(msgBytes); } else if (channelId == TRANSFER_IN_CHANNELID) { diff --git a/contracts/interface/IApplication.sol b/contracts/interface/IApplication.sol index 0120b3a04..e06e06f43 100644 --- a/contracts/interface/IApplication.sol +++ b/contracts/interface/IApplication.sol @@ -4,7 +4,7 @@ interface IApplication { /** * @dev Handle sync package */ - function handleSyncPackage(uint8 channelId, bytes calldata msgBytes) external returns(bytes memory responsePayload); + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) external returns(bytes memory responsePayload); /** * @dev Handle ack package diff --git a/contracts/rlp/CmnPkg.sol b/contracts/rlp/CmnPkg.sol new file mode 100644 index 000000000..821d587dd --- /dev/null +++ b/contracts/rlp/CmnPkg.sol @@ -0,0 +1,39 @@ +pragma solidity 0.6.4; + +import "./RLPEncode.sol"; +import "./RLPDecode.sol"; + +library CmnPkg { + + using RLPEncode for *; + using RLPDecode for *; + + + struct CommonAckPackage { + uint32 code; + } + + function encodeCommonAckPackage(uint32 code) internal pure returns (bytes memory) { + bytes[] memory elements = new bytes[](1); + elements[0] = uint256(code).encodeUint(); + return elements.encodeList(); + } + + function decodeCommonAckPackage(bytes memory msgBytes) internal pure returns (CommonAckPackage memory, bool) { + CommonAckPackage memory ackPkg; + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + + bool success = false; + uint256 idx=0; + while(iter.hasNext()) { + if ( idx == 0 ) { + ackPkg.code = uint32(iter.next().toUint()); + success = true; + }else { + break; + } + idx++; + } + return (ackPkg, success); + } +} \ No newline at end of file diff --git a/contracts/tool/BSCValidatorSetTool.sol b/contracts/tool/BSCValidatorSetTool.sol index 95c73ca76..7514d9fbc 100644 --- a/contracts/tool/BSCValidatorSetTool.sol +++ b/contracts/tool/BSCValidatorSetTool.sol @@ -1,23 +1,14 @@ pragma solidity 0.6.4; -import "../Seriality/TypesToBytes.sol"; -import "../Seriality/BytesToTypes.sol"; -import "../Seriality/BytesLib.sol"; +import "../rlp/RLPDecode.sol"; contract BSCValidatorSetTool { - // keep consistent with the channel id in BBC; - uint8 public constant CHANNEL_ID = 8; - // {20 bytes consensusAddress} + {20 bytes feeAddress} + {20 bytes BBCFeeAddress} + {8 bytes voting power} - uint constant VALIDATOR_BYTES_LENGTH = 68; - uint256 constant crossChainKeyPrefix = 0x0000000000000000000000000000000000000000000000000000000001000200; // last 6 bytes - uint16 public constant FROM_CHAIN_ID = 0x0001; - uint16 public constant TO_CHAIN_ID = 0x0002; + bytes public constant INIT_VALIDATORSET_BYTES = hex"f84580f842f840949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164"; - Validator[] public currentValidatorSet; - bytes public expectedKey; + using RLPDecode for *; struct Validator{ address consensusAddress; @@ -26,60 +17,64 @@ contract BSCValidatorSetTool { uint64 votingPower; } - - - function verify(bytes calldata key, bytes calldata msgBytes, uint64 packageSequence) external{ - // verify key value against light client; - bytes memory expect = generateKey(packageSequence,CHANNEL_ID); - expectedKey = key; - require(BytesLib.equal(expect,key), string(expectedKey)); - parseValidatorSet(msgBytes); + struct IbcValidatorSetPackage { + uint8 packageType; + Validator[] validatorSet; } - /*********************** Internal Functions **************************/ + function init() external { + bool valid= decodeValidatorSetSyncPackage(INIT_VALIDATORSET_BYTES); + require(valid, "failed to init"); + } - function parseValidatorSet(bytes memory validatorSetBytes) internal{ - uint length = validatorSetBytes.length-1; - require(length > 0, "the validatorSetBytes should not be empty"); - require(length % VALIDATOR_BYTES_LENGTH == 0, "the length of validatorSetBytes should be times of 68"); - uint m = currentValidatorSet.length; - for(uint i = 0;i", - "bsc chain id", - "0060"); - program.option("--mock ", "if use mock", false); @@ -27,7 +23,6 @@ program.option("--mock ", program.parse(process.argv); const data = { - bscChainId: program.bscChainId, mock: program.mock, }; const templateString = fs.readFileSync(program.template).toString(); diff --git a/generate-genesis.js b/generate-genesis.js index 5472febd9..8daa42802 100644 --- a/generate-genesis.js +++ b/generate-genesis.js @@ -9,7 +9,6 @@ const init_holders = require("./init_holders") require("./generate-system"); require("./generate-systemReward"); -require("./generate-govhub"); require("./generate-validatorset"); require("./generate-tokenhub"); require("./generate-tendermintlightclient"); diff --git a/generate-govhub.js b/generate-govhub.js deleted file mode 100644 index 86eec283d..000000000 --- a/generate-govhub.js +++ /dev/null @@ -1,31 +0,0 @@ -const program = require("commander"); -const fs = require("fs"); -const nunjucks = require("nunjucks"); - - -program.version("0.0.1"); -program.option( - "-t, --template