mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-31 23:41:22 +00:00
7fa709bd40
deregister_collator and release_collator implementation Former-commit-id: 2c9a3ef1ee840209a65f9d6bd5d27f6efcad4ce0 [formerly f60bca0bc0a46f61dfa45fc62af9c37d75b6a749] Former-commit-id: 3be99e546546fbf91ffb92586dd9e4448b4b563c
283 lines
9.8 KiB
Solidity
283 lines
9.8 KiB
Solidity
pragma solidity ^0.4.19;
|
|
|
|
contract SMC {
|
|
event HeaderAdded(uint indexed shard_id, bytes32 parent_hash,
|
|
bytes32 chunk_root, int128 period, int128 height,
|
|
address proposer_address, uint proposer_bid,
|
|
bytes proposer_signature);
|
|
event CollatorRegistered(address collator, uint pool_index);
|
|
event CollatorDeregistered(uint pool_index);
|
|
event CollatorReleased(uint pool_index);
|
|
event ProposerRegistered(uint pool_index);
|
|
event ProposerDeregistered(uint index);
|
|
event ProposerReleased(uint index);
|
|
|
|
// Entry in collator_registry
|
|
struct Collator {
|
|
// When collator asked for unregistration
|
|
uint deregistered;
|
|
// The collator's pool index
|
|
uint pool_index;
|
|
// False if collator has not deposited, true otherwise
|
|
bool deposited;
|
|
}
|
|
|
|
// Entry in proposer_registry
|
|
struct Proposer {
|
|
// Shard id of the deposit
|
|
uint shardId;
|
|
// Deposit in ether in each shard
|
|
uint[] deposit;
|
|
}
|
|
|
|
struct CollationHeader {
|
|
uint256 shard_id; // pointer to shard
|
|
bytes32 parent_hash; // pointer to parent header
|
|
bytes32 chunk_root; // pointer to collation body
|
|
int128 period; // Period which header should be included
|
|
int128 height; // Collation's height
|
|
address proposer_address; // Proposer's address
|
|
uint256 proposer_bid; // Proposer's bid
|
|
bytes proposer_signature; // Proposer's signature
|
|
}
|
|
|
|
// Packed variables to be used in addHeader
|
|
struct HeaderVars {
|
|
bytes32 entireHeaderHash;
|
|
int score;
|
|
address collatorAddr;
|
|
bool isNewHead;
|
|
}
|
|
|
|
// collatorId => Collators
|
|
// mapping (int => Collator) public collators;
|
|
address[] public collator_pool;
|
|
// proposerId => Proposer
|
|
// mapping (int => Proposer) public proposers;
|
|
Proposer[] public proposer_pool;
|
|
|
|
// Collator registry (deregistered is 0 for not yet deregistered collators)
|
|
mapping (address => Collator) public collator_registry;
|
|
mapping (address => Proposer) public proposer_registry;
|
|
// shard_id => (header_hash => tree root)
|
|
mapping (uint => mapping (bytes32 => bytes32)) public collation_trees;
|
|
// shardId => (headerHash => CollationHeader)
|
|
mapping (int => mapping (bytes32 => CollationHeader)) public collationHeaders;
|
|
// shardId => headerHash
|
|
mapping (int => bytes32) shardead;
|
|
|
|
// Number of collators
|
|
uint public collator_pool_len;
|
|
// Indexes of empty slots caused by the function `withdraw`
|
|
uint[] empty_slots_stack;
|
|
// The top index of the stack in empty_slots_stack
|
|
uint empty_slots_stack_top;
|
|
|
|
// Constant values
|
|
uint constant PERIOD_LENGTH = 5;
|
|
// Exact collation body size (1mb)
|
|
uint constant COLLATION_SIZE = 2 ** 20;
|
|
// Subsidy in vEth
|
|
uint constant COLLATOR_SUBSIDY = 0.001 ether;
|
|
// Number of shards
|
|
uint constant SHARD_COUNT = 100;
|
|
// The minimum deposit size for a collator
|
|
uint constant COLLATOR_DEPOSIT = 1000 ether;
|
|
// The minimum deposit size for a proposer
|
|
uint constant PROPOSER_DEPOSIT = 1 ether;
|
|
// The minimum balance of a proposer (for collators)
|
|
uint constant MIN_PROPOSER_BALANCE = 0.1 ether;
|
|
// Time the ether is locked by collators
|
|
uint constant COLLATOR_LOCKUP_LENGTH = 16128;
|
|
// Time the ether is locked by proposers
|
|
uint constant PROPOSER_LOCKUP_LENGTH = 48;
|
|
// Number of periods ahead of current period, which the contract
|
|
// is able to return the collator of that period
|
|
uint constant LOOKAHEAD_LENGTH = 4;
|
|
|
|
// Log the latest period number of the shard
|
|
mapping (int => int) public period_head;
|
|
|
|
function SMC() public {
|
|
}
|
|
|
|
// Uses a block hash as a seed to pseudorandomly select a signer from the collator pool.
|
|
// [TODO] Chance of being selected should be proportional to the collator's deposit.
|
|
// Should be able to return a value for the current period or any future period up to.
|
|
function get_eligible_collator(uint256 shard_id, uint256 period) public view returns(address) {
|
|
require(period >= LOOKAHEAD_LENGTH);
|
|
require((period - LOOKAHEAD_LENGTH) * PERIOD_LENGTH < block.number);
|
|
require(collator_pool_len > 0);
|
|
// [TODO] Should check further if this safe or not
|
|
return collator_pool[
|
|
uint(
|
|
keccak256(
|
|
uint(block.blockhash((period - LOOKAHEAD_LENGTH) * PERIOD_LENGTH)),
|
|
shard_id
|
|
)
|
|
) %
|
|
collator_pool_len
|
|
];
|
|
}
|
|
|
|
function compute_header_hash(uint256 shard_id,
|
|
bytes32 parent_hash,
|
|
bytes32 chunk_root,
|
|
uint256 period,
|
|
address proposer_address,
|
|
uint256 proposer_bid) public returns(bytes32){
|
|
|
|
}
|
|
|
|
function register_collator() public payable returns(bool) {
|
|
address collator_address = msg.sender;
|
|
require(!collator_registry[collator_address].deposited);
|
|
require(msg.value == COLLATOR_DEPOSIT);
|
|
|
|
uint index;
|
|
if (!empty_stack()) {
|
|
index = stack_pop();
|
|
collator_pool[index] = collator_address;
|
|
}
|
|
else {
|
|
index = collator_pool_len;
|
|
collator_pool.push(collator_address);
|
|
}
|
|
++collator_pool_len;
|
|
|
|
collator_registry[collator_address] = Collator({
|
|
deregistered: 0,
|
|
pool_index: index,
|
|
deposited: true
|
|
});
|
|
CollatorRegistered(collator_address, index);
|
|
return true;
|
|
}
|
|
|
|
// Removes the collator from the collator pool and sets deregistered period
|
|
function deregister_collator() public {
|
|
address collator_address = msg.sender;
|
|
uint index = collator_registry[collator_address].pool_index;
|
|
// Check if collator deposited
|
|
require(collator_registry[collator_address].deposited);
|
|
require(collator_pool[index] == collator_address);
|
|
|
|
// Deregistered period
|
|
collator_registry[collator_address].deregistered = block.number / PERIOD_LENGTH;
|
|
|
|
stack_push(index);
|
|
--collator_pool_len;
|
|
CollatorDeregistered(index);
|
|
}
|
|
|
|
function release_collator() public {
|
|
address collator_address = msg.sender;
|
|
require(collator_registry[collator_address].deposited == true);
|
|
// Deregistered
|
|
require(collator_registry[collator_address].deregistered != 0);
|
|
// Locked up period
|
|
require((block.number / PERIOD_LENGTH) > (collator_registry[collator_address].deregistered + COLLATOR_LOCKUP_LENGTH));
|
|
|
|
delete collator_registry[collator_address];
|
|
collator_address.transfer(COLLATOR_DEPOSIT);
|
|
}
|
|
|
|
function register_proposer() public payable returns(int) {
|
|
|
|
}
|
|
|
|
function deregister_proposer() public {
|
|
|
|
}
|
|
|
|
function release_proposer() public {
|
|
|
|
}
|
|
|
|
function proposer_add_balance(uint shard_id) payable public {
|
|
|
|
}
|
|
|
|
function proposer_withdraw_balance(uint shard_id) public {
|
|
|
|
}
|
|
|
|
// Attempts to process a collation header, returns true on success, reverts on failure.
|
|
function addHeader(uint _shardId, uint period, bytes32 height,
|
|
bytes32 _parent_hash, bytes32 chunk_root,
|
|
address proposer_address, uint proposer_bid,
|
|
bytes proposer_signature) public returns(bool) {
|
|
// HeaderVars memory headerVars;
|
|
|
|
// // Check if the header is valid
|
|
// require((_shardId >= 0) && (_shardId < shardCount));
|
|
// require(block.number >= periodLength);
|
|
// require(_expectedPeriodNumber == block.number / periodLength);
|
|
// require(_periodStartPrevHash == block.blockhash(_expectedPeriodNumber * periodLength - 1));
|
|
|
|
// // Check if this header already exists
|
|
// headerVars.entireHeaderHash = keccak256(_shardId, _expectedPeriodNumber, _periodStartPrevHash,
|
|
// _parentHash, _transactionRoot, bytes32(_coinbase),
|
|
// _stateRoot, _receiptRoot, _number);
|
|
// assert(collationHeaders[_shardId][headerVars.entireHeaderHash].score == 0);
|
|
// // Check whether the parent exists.
|
|
// // if (parent_collation_hash == 0), i.e., is the genesis,
|
|
// // then there is no need to check.
|
|
// if (_parentHash != 0x0)
|
|
// assert(collationHeaders[_shardId][_parentHash].score > 0);
|
|
// // Check if only one collation in one period
|
|
// assert(periodHead[_shardId] < int(_expectedPeriodNumber));
|
|
|
|
// // Check the signature with validation_code_addr
|
|
// headerVars.collatorAddr = getEligibleCollator(_shardId, block.number/periodLength);
|
|
// require(headerVars.collatorAddr != 0x0);
|
|
// require(msg.sender == headerVars.collatorAddr);
|
|
|
|
// // Check score == collationNumber
|
|
// headerVars.score = collationHeaders[_shardId][_parentHash].score + 1;
|
|
// require(_number == headerVars.score);
|
|
|
|
// // Add the header
|
|
// collationHeaders[_shardId][headerVars.entireHeaderHash] = CollationHeader({
|
|
// parentHash: _parentHash,
|
|
// score: headerVars.score
|
|
// });
|
|
|
|
// // Update the latest period number
|
|
// periodHead[_shardId] = int(_expectedPeriodNumber);
|
|
|
|
// // Determine the head
|
|
// if (headerVars.score > collationHeaders[_shardId][shardHead[_shardId]].score) {
|
|
// shardHead[_shardId] = headerVars.entireHeaderHash;
|
|
// headerVars.isNewHead = true;
|
|
// }
|
|
|
|
// CollationAdded(_shardId, _expectedPeriodNumber, _periodStartPrevHash,
|
|
// _parentHash, _transactionRoot, _coinbase, _stateRoot,
|
|
// _receiptRoot, _number, headerVars.isNewHead, headerVars.score);
|
|
|
|
// return true;
|
|
}
|
|
|
|
|
|
function empty_stack() internal view returns(bool) {
|
|
return empty_slots_stack_top == 0;
|
|
}
|
|
|
|
function stack_push(uint index) internal {
|
|
if (empty_slots_stack.length == empty_slots_stack_top)
|
|
empty_slots_stack.push(index);
|
|
else
|
|
empty_slots_stack[empty_slots_stack_top] = index;
|
|
|
|
++empty_slots_stack_top;
|
|
}
|
|
// Pop element from stack
|
|
// Caller should check if stack is empty
|
|
function stack_pop() internal returns(uint) {
|
|
require(empty_slots_stack_top > 1);
|
|
--empty_slots_stack_top;
|
|
return empty_slots_stack[empty_slots_stack_top];
|
|
}
|
|
}
|