Skip to content

Commit

Permalink
Merge pull request #1030 from HorizenOfficial/stakeV2
Browse files Browse the repository at this point in the history
Stake v2
  • Loading branch information
paolocappelletti authored May 20, 2024
2 parents 44d11e5 + e982ede commit 7711a14
Show file tree
Hide file tree
Showing 110 changed files with 11,152 additions and 601 deletions.
63 changes: 54 additions & 9 deletions qa/SidechainTestFramework/account/ac_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,12 @@ def eoa_transfer(node, sender, receiver, amount, call_method: CallMethod = CallM
return res


def contract_function_static_call(node, smart_contract_type, smart_contract_address, from_address, method, *args,
tag = 'latest', eip1898 = False, isBlockHash = False):
def contract_function_static_call(node, smart_contract_type, smart_contract_address, from_address, method, *args, value = 0,
tag='latest', eip1898=False, isBlockHash=False):
logging.info("Calling {}: using static call function".format(method))
res = smart_contract_type.static_call(node, method, *args, fromAddress=from_address,
toAddress=smart_contract_address, tag=tag, eip1898=eip1898, isBlockHash=isBlockHash)
toAddress=smart_contract_address, value=value, tag=tag, eip1898=eip1898,
isBlockHash=isBlockHash)
return res


Expand Down Expand Up @@ -270,17 +271,58 @@ def estimate_gas(node, from_address=None, to_address=None, data='0x', value='0x0


def ac_makeForgerStake(sc_node, owner_address, blockSignPubKey, vrf_public_key, amount, nonce=None):
forgerStakes = {"forgerStakeInfo": {
"ownerAddress": owner_address,
"blockSignPublicKey": blockSignPubKey,
"vrfPubKey": vrf_public_key,
"value": amount # in Satoshi
},
forgerStakes = {"forgerStakeInfo":
{
"ownerAddress": owner_address,
"blockSignPublicKey": blockSignPubKey,
"vrfPubKey": vrf_public_key,
"value": amount # in Satoshi
},
"nonce": nonce
}

return sc_node.transaction_makeForgerStake(json.dumps(forgerStakes))

def ac_registerForger(sc_node, block_sign_pub_key, vrf_public_key, staked_amount, reward_address=None, reward_share=None,
nonce=None):
parameters = {
"blockSignPubKey": block_sign_pub_key,
"vrfPubKey": vrf_public_key,
"stakedAmount": staked_amount, # in Satoshi
"rewardShare": reward_share,
"rewardAddress": reward_address,
"nonce": nonce
}
return sc_node.transaction_registerForger(json.dumps(parameters))

def ac_updateForger(sc_node, block_sign_pub_key, vrf_public_key, reward_address, reward_share, nonce=None):
parameters = {
"blockSignPubKey": block_sign_pub_key,
"vrfPubKey": vrf_public_key,
"rewardShare": reward_share,
"rewardAddress": reward_address,
"nonce": nonce
}
return sc_node.transaction_updateForger(json.dumps(parameters))

def ac_pagedForgersStakesByForger(sc_node, block_sign_pub_key, vrf_public_key, start_pos=0, size=10):
parameters = {
"blockSignPubKey": block_sign_pub_key,
"vrfPubKey": vrf_public_key,
"startPos": start_pos,
"size": size
}
return sc_node.transaction_pagedForgersStakesByForger(json.dumps(parameters))


def ac_pagedForgersStakesByDelegator(sc_node, delegator_address, start_pos=0, size=10):
parameters = {
"delegatorAddress": delegator_address,
"startPos": start_pos,
"size": size
}
return sc_node.transaction_pagedForgersStakesByDelegator(json.dumps(parameters))


def ac_invokeProxy(sc_node, contract_address, data, nonce=None, static=False):
params = {
Expand All @@ -296,4 +338,7 @@ def ac_invokeProxy(sc_node, contract_address, data, nonce=None, static=False):
else:
return sc_node.transaction_invokeProxyCall(json.dumps(params))

def rpc_get_balance(sc_node, address):
return int(
sc_node.rpc_eth_getBalance(format_evm(address), 'latest')['result'], 16)

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface ForgerStakes {
event WithdrawForgerStake(address indexed owner, bytes32 stakeId);
event StakeUpgrade(uint32 oldVersion, uint32 newVersion);
event OpenForgerList(uint32 indexed forgerIndex, address sender, bytes32 blockSignProposition);
event DisableStakeV1();

function getAllForgersStakes() external view returns (StakeInfo[] memory);

Expand All @@ -38,4 +39,7 @@ interface ForgerStakes {
function upgrade() external returns (uint32);

function getPagedForgersStakes(int32 startIndex, int32 pageSize) external view returns (int32, StakeInfo[] memory);

// disableAndMigrate can be called only after fork point 1.4 and only by the ForgerStakesV2 smart contract
function disableAndMigrate() external returns (StakeInfo[] memory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/*
Native Contract managing forgers stakes - Version 2 (activated from EON version 1.4)
contract address: 0x0000000000000000000022222222222222222333
*/
interface ForgerStakesV2 {

// Event declaration
// Up to 3 parameters can be indexed.
// Indexed parameters help you filter the logs by the indexed parameter
event RegisterForger(address indexed sender, bytes32 signPubKey, bytes32 indexed vrf1, bytes1 indexed vrf2, uint256 value, uint32 rewardShare, address reward_address);
event UpdateForger(address indexed sender, bytes32 signPubKey, bytes32 indexed vrf1, bytes1 indexed vrf2, uint32 rewardShare, address reward_address);
event DelegateForgerStake(address indexed sender, bytes32 signPubKey, bytes32 indexed vrf1, bytes1 indexed vrf2, uint256 value);
event WithdrawForgerStake(address indexed sender, bytes32 signPubKey, bytes32 indexed vrf1, bytes1 indexed vrf2, uint256 value);
event ActivateStakeV2();


//Data structures
struct ForgerInfo {
bytes32 signPubKey;
bytes32 vrf1;
bytes1 vrf2;
uint32 rewardShare;
address reward_address;
}

struct StakeDataDelegator {
address delegator;
uint256 stakedAmount;
}

struct StakeDataForger {
bytes32 signPubKey;
bytes32 vrf1;
bytes1 vrf2;
uint256 stakedAmount;
}

//read-write methods

/*
Register a new forger.
rewardShare can range in [0..1000] and can be 0 if and only if rewardAddress == 0x000..00.
Vrf key and signatures are split in two or more separate parameters, being longer than 32 bytes.
sign1_x are the 25519 signature chunks and sign2_x are the Vfr signature chunks.
The message to sign is the first 31 bytes of Keccak256 hash of a string formed by the concatenation
of signPubKey+vrfKey+rewardShare+rewardAddress. rewardAddress is represented in the Eip55
checksum format and hex strings are lowercase with no prefix.
The method accepts WEI value: the sent value will be converted to the initial stake assigned to the forger.
The initial stake amount must be >= min threshold (10 Zen)
*/
function registerForger(bytes32 signPubKey, bytes32 vrfKey1, bytes1 vrfKey2, uint32 rewardShare,
address rewardAddress, bytes32 sign1_1, bytes32 sign1_2,
bytes32 sign2_1, bytes32 sign2_2, bytes32 sign2_3, bytes1 sign2_4) external payable;

/*
Updates an existing forger.
A forger can be updated just once and only if rewardAddress == 0x000..00 and rewardShare == 0.
See above the registerForger command for the parameters meaning.
*/
function updateForger(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, uint32 rewardShare,
address rewardAddress, bytes32 sign1_1, bytes32 sign1_2,
bytes32 sign2_1, bytes32 sign2_2, bytes32 sign2_3, bytes1 sign2_4) external;

/*
Delegate a stake to a previously registered forger.
Vrf key is split in two separate parameters, being longer than 32 bytes.
*/
function delegate(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2) external payable;

/*
Withdraw (unstake) a previously assigned stake.
Vrf key is split in two separate parameters, being longer than 32 bytes.
*/
function withdraw(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, uint256 amount) external;

//read only methods

/*
Returns the total stake amount, at the end of one or more consensus epochs, assigned to a specific forger.
vrf, signKey and delegator are optional: if all are null, the total stake amount will be returned. If only
delegator is null, all the stakes assigned to the forger will be summed.
If vrf and signKey are null, but delegator is defined, the method will fail.
consensusEpochStart and maxNumOfEpoch are optional: if both null, the data at the current consensus epoch is returned.
Be aware that following convention apply when we talk about 'null' values: for bytes parameters, as addresses of key etc., a byte array of the expected length with all 0 values is interpreted as null, eg "0x0000000000000000000000000000000000000000" for addresses.
For consensusEpochStart and maxNumOfEpoch, it is 0.
Returned array contains also elements with 0 value. Returned values are ordered by epoch, and the array length may
be < maxNumOfEpoch if the current consensus epoch is < (consensusEpochStart + maxNumOfEpoch).
*/
function stakeTotal(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, address delegator, uint32 consensusEpochStart, uint32 maxNumOfEpoch) external view returns (uint256[] memory listOfStakes);

/*
Return total sum paid to the forger reward_address at the end of one or more consensus epochs.
Returned array contains also elements with 0 value. Returned values are ordered by epoch, and the array length may
be < maxNumOfEpoch if the current consensus epoch is < (consensusEpochStart + maxNumOfEpoch).
*/
function rewardsReceived(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, uint32 consensusEpochStart, uint32 maxNumOfEpoch) external view returns (uint256[] memory listOfRewards);

/*
Returns the first consensus epoch when a stake is present for a specific delegator.
signPubKey, vrf1, vrf2 and delegator parameters are mandatory.
If no stake has been found (the delegator never staked anything to this forger) the method returns -1
*/
function stakeStart(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, address delegator) external view returns (int32 consensusEpochStart);

/*
Returns the info of a specific registered forger.
*/
function getForger(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2) external view returns (ForgerInfo memory forgerInfo);

/*
Returns the paginated list of all the registered forgers.
Each element of the list is the detail of a specific forger.
nextIndex will contain the index of the next element not returned yet. If no element is still present, next will be -1.
*/
function getPagedForgers(int32 startIndex, int32 pageSize) external view returns (int32 nextIndex, ForgerInfo[] memory listOfForgerInfo);

/*
Returns the paginated list of stakes delegated to a specific forger, grouped by delegator address.
Each element of the list is the total amount delegated by a specific address.
nextIndex will contain the index of the next element not returned yet. If no element is still present, next will be -1.
The returned array length may be less than pageSize even if there are still additional elements because stakes with 0 amount are filtered out.
*/
function getPagedForgersStakesByForger(bytes32 signPubKey, bytes32 vrf1, bytes1 vrf2, int32 startIndex, int32 pageSize) external view returns (int32 nextIndex, StakeDataDelegator[] memory listOfDelegatorStakes);

/*
Returns the paginated list of stakes delegated by a specific address, grouped by forger.
Each element of the list is the total amount delegated to a specific forger.
nextIndex will contain the index of the next element not returned yet. If no element is still present, next will be -1.
The returned array length may be less than pageSize even if there are still additional elements because stakes with 0 amount are filtered out.
*/
function getPagedForgersStakesByDelegator(address delegator, int32 startIndex, int32 pageSize) external view returns (int32 nextIndex, StakeDataForger[] memory listOfForgerStakes);

/*
/ Returns the current consensus epoch.
*/
function getCurrentConsensusEpoch() external view returns (uint32 epoch);

function activate() external;
}
3 changes: 2 additions & 1 deletion qa/SidechainTestFramework/account/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def convertZenniesToZen(valueInZennies):
CERTIFICATE_KEY_ROTATION_SMART_CONTRACT_ADDRESS = "0000000000000000000044444444444444444444"
MC_ADDR_OWNERSHIP_SMART_CONTRACT_ADDRESS = "0000000000000000000088888888888888888888"
PROXY_SMART_CONTRACT_ADDRESS = "00000000000000000000AAAAAAAAAAAAAAAAAAAA"
FORGER_STAKE_V2_SMART_CONTRACT_ADDRESS = "0000000000000000000022222222222222222333"
# address used for burning coins
NULL_ADDRESS = "0000000000000000000000000000000000000000"

Expand All @@ -53,7 +54,7 @@ def convertZenniesToZen(valueInZennies):
VERSION_1_2_FORK_EPOCH = 60
# The activation epoch for features released in v1.3 (e.g. SHANGHAI EVM), as coded in the sdk
VERSION_1_3_FORK_EPOCH = 70
# The activation epoch for features released in v1.4
# The activation epoch for features released in v1.4, as coded in the sdk
VERSION_1_4_FORK_EPOCH = 80

# Block gas limit
Expand Down
2 changes: 2 additions & 0 deletions qa/run_sc_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ testScriptsEvm=(
'sc_evm_shanghai.py'
'sc_evm_pause_forging.py'
'sc_evm_forger_reward_address.py'
'sc_evm_native_forger_v2.py'
'sc_evm_forger_v2_register.py'
);

testScriptsUtxo=(
Expand Down
Loading

0 comments on commit 7711a14

Please sign in to comment.