Skip to content

Commit

Permalink
[R4F]Gov/Validator/Slash modification for refactor of cross chain mec…
Browse files Browse the repository at this point in the history
…hanism (#14)

* update bsc validator set

* update for encode/decode of gov/validator/slash

* update template

* update testcase

* update testcase

* fix cases

* update testcase

* update

* update
  • Loading branch information
unclezoro authored and HaoyangLiu committed Jul 3, 2020
1 parent 5682e6f commit 28190d7
Show file tree
Hide file tree
Showing 27 changed files with 744 additions and 831 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
239 changes: 138 additions & 101 deletions contracts/BSCValidatorSet.sol

Large diffs are not rendered by default.

239 changes: 138 additions & 101 deletions contracts/BSCValidatorSet.template

Large diffs are not rendered by default.

45 changes: 18 additions & 27 deletions contracts/CrossChain.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{
uint8 constant public ACK_PACKAGE = 0x01;
uint8 constant public FAIL_ACK_PACKAGE = 0x02;

uint16 constant bscChainID = 0x0060;
uint256 constant crossChainKeyPrefix = 0x0000000000000000000000000000000000000000000000000000000001006000; // last 6 bytes

mapping(uint8 => address) public channelHandlerContractMap;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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]<sequence, "can't retreat sequence");
channelReceiveSequenceMap[channelId] = sequence;
} else {
address handlerContract;
assembly {
handlerContract := mload(add(localValue, 20))
}
require(isContract(handlerContract), "address is not a contract");
channelHandlerContractMap[channelId]=handlerContract;
registeredContractMap[handlerContract] = true;
emit addChannel(channelId, handlerContract);
uint8 channelId = uint8(localKey[0]);
bool fromSystem = uint8(localKey[1]) == 0x00;

address handlerContract;
assembly {
handlerContract := mload(add(localValue, 20))
}
require(isContract(handlerContract), "address is not a contract");
channelHandlerContractMap[channelId]=handlerContract;
registeredContractMap[handlerContract] = true;
isRelayRewardFromSystemReward[channelId] = fromSystem;
emit addChannel(channelId, handlerContract);
emit paramChange(key, value);
}
}
45 changes: 18 additions & 27 deletions contracts/CrossChain.template
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{
uint8 constant public ACK_PACKAGE = 0x01;
uint8 constant public FAIL_ACK_PACKAGE = 0x02;

uint16 constant bscChainID = 0x{{bscChainId}};
uint256 constant crossChainKeyPrefix = 0x0000000000000000000000000000000000000000000000000000000001{{bscChainId}}00; // last 6 bytes

mapping(uint8 => address) public channelHandlerContractMap;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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]<sequence, "can't retreat sequence");
channelReceiveSequenceMap[channelId] = sequence;
} else {
address handlerContract;
assembly {
handlerContract := mload(add(localValue, 20))
}
require(isContract(handlerContract), "address is not a contract");
channelHandlerContractMap[channelId]=handlerContract;
registeredContractMap[handlerContract] = true;
emit addChannel(channelId, handlerContract);
uint8 channelId = uint8(localKey[0]);
bool fromSystem = uint8(localKey[1]) == 0x00;

address handlerContract;
assembly {
handlerContract := mload(add(localValue, 20))
}
require(isContract(handlerContract), "address is not a contract");
channelHandlerContractMap[channelId]=handlerContract;
registeredContractMap[handlerContract] = true;
isRelayRewardFromSystemReward[channelId] = fromSystem;
emit addChannel(channelId, handlerContract);
emit paramChange(key, value);
}
}
115 changes: 55 additions & 60 deletions contracts/GovHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,83 @@ import "./Seriality/Memory.sol";
import "./Seriality/BytesLib.sol";
import "./interface/IParamSubscriber.sol";
import "./interface/IApplication.sol";
import "./rlp/RLPDecode.sol";
import "./rlp/CmnPkg.sol";


contract GovHub is System, IApplication{
using RLPDecode for *;

uint8 public constant PARAM_UPDATE_MESSAGE_TYPE = 0;

uint32 public constant CODE_OK = 0;
uint32 public constant ERROR_TARGET_NOT_CONTRACT = 101;
uint32 public constant ERROR_TARGET_CONTRACT_FAIL = 102;

event failReasonWithStr(string message);
event failReasonWithBytes(bytes message);
event paramChange(string key, bytes value);

function init() external onlyNotInit{
alreadyInit = true;
struct ParamChangePackage {
string key;
bytes value;
address target;
}

function handleSyncPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){
uint8 msgType = getMsgType(msgBytes);
if(msgType == PARAM_UPDATE_MESSAGE_TYPE){
notifyUpdates(msgBytes);
}else{
emit failReasonWithStr("unknown message type");
}
return new bytes(0);
function handleSynPackage(uint8, bytes calldata msgBytes) onlyCrossChainContract external override returns(bytes memory responsePayload){
(ParamChangePackage memory proposal, bool success) = decodeSynPackage(msgBytes);
require(success, "fail to parse cross chain package");
uint32 resCode = notifyUpdates(proposal);
return CmnPkg.encodeCommonAckPackage(resCode);
}

function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external override {
return;
// should not happen
function handleAckPackage(uint8, bytes calldata) external override {
require(false, "receive unexpected ack package");
}

function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external override {
return;
// should not happen
function handleFailAckPackage(uint8, bytes calldata) external override {
require(false, "receive unexpected fail ack package");
}

//| Proposal type | key length | bytes of key | value length | value | target addr |
//| 1 byte | 1 byte | N bytes | 1 byte | M bytes| 20 byte |
function notifyUpdates(ParamChangePackage memory proposal) internal returns(uint32) {

function notifyUpdates(bytes memory proposalBytes) internal {
uint msgLength = proposalBytes.length;
// the minimum length is 25
if(msgLength <25){
emit failReasonWithStr("msg length less than 25");
return;
}
uint8 keyLength = BytesToTypes.bytesToUint8(2, proposalBytes);
if(keyLength == 0||msgLength<24+uint16(keyLength)){
emit failReasonWithStr("keyLength mismatch");
return;
if (!isContract(proposal.target)){
emit failReasonWithStr("the target is not a contract");
return ERROR_TARGET_NOT_CONTRACT;
}
string memory key = string(BytesLib.slice(proposalBytes, 2, keyLength));
uint8 valueLength = BytesToTypes.bytesToUint8(3+uint16(keyLength), proposalBytes);
if(valueLength == 0||msgLength!=23+uint16(keyLength)+uint16(valueLength)){
emit failReasonWithStr("valueLength mismatch");
return;
}
bytes memory value = BytesLib.slice(proposalBytes, 3+uint16(keyLength), uint16(valueLength));
address target = BytesToTypes.bytesToAddress(msgLength, proposalBytes);
if (target == address(this)){
updateParam(key, value);
}else{
if (!isContract(target)){
emit failReasonWithStr("the target is not a contract");
return;
}
try IParamSubscriber(target).updateParam(key, value){
}catch Error(string memory reason) {
emit failReasonWithStr(reason);
} catch (bytes memory lowLevelData) {
emit failReasonWithBytes(lowLevelData);
}
try IParamSubscriber(proposal.target).updateParam(proposal.key, proposal.value){
}catch Error(string memory reason) {
emit failReasonWithStr(reason);
return ERROR_TARGET_CONTRACT_FAIL;
} catch (bytes memory lowLevelData) {
emit failReasonWithBytes(lowLevelData);
return ERROR_TARGET_CONTRACT_FAIL;
}
return;
return CODE_OK;
}

function getMsgType(bytes memory msgBytes) internal pure returns(uint8){
uint8 msgType = 0xff;
assembly {
msgType := mload(add(msgBytes, 1))
}
return msgType;
}

/*********************** Param update ********************************/
function updateParam(string memory key, bytes memory value) internal{
//rlp encode & decode function
function decodeSynPackage(bytes memory msgBytes) internal pure returns (ParamChangePackage memory, bool) {
ParamChangePackage memory pkg;

RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator();
bool success = false;
uint256 idx=0;
while(iter.hasNext()) {
if ( idx == 0 ) {
pkg.key = string(iter.next().toBytes());
}else if (idx == 1) {
pkg.value = iter.next().toBytes();
}else if (idx == 2){
pkg.target = iter.next().toAddress();
success = true;
} else {
break;
}
idx++;
}
return (pkg, success);
}
}
}
92 changes: 0 additions & 92 deletions contracts/GovHub.template

This file was deleted.

Loading

0 comments on commit 28190d7

Please sign in to comment.