prysm-pulse/sharding/contracts/sharding_manager.sol
Fynn 7fa709bd40 sharding: collator functions
deregister_collator and release_collator implementation


Former-commit-id: 2c9a3ef1ee840209a65f9d6bd5d27f6efcad4ce0 [formerly f60bca0bc0a46f61dfa45fc62af9c37d75b6a749]
Former-commit-id: 3be99e546546fbf91ffb92586dd9e4448b4b563c
2018-04-04 07:57:06 +02:00

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];
}
}