mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
214 lines
6.2 KiB
Solidity
214 lines
6.2 KiB
Solidity
pragma solidity ^0.4.24;
|
|
|
|
/**
|
|
* @title Registrar
|
|
* @author Gary Rong<garyrong0905@gmail.com>
|
|
* @dev Implementation of the blockchain checkpoint information registrar.
|
|
*/
|
|
contract Registrar {
|
|
/*
|
|
Modifiers
|
|
*/
|
|
|
|
/**
|
|
* @dev Check whether the message sender is authorized.
|
|
*/
|
|
modifier OnlyAuthorized() {
|
|
require(admins[msg.sender] > 0);
|
|
_;
|
|
}
|
|
|
|
/*
|
|
Events
|
|
*/
|
|
|
|
// NewCheckpointEvent is emitted when new checkpoint is registered.
|
|
// Grantor indicates the people register the checkpoint.
|
|
// We use checkpoint hash instead of the full checkpoint to make the transaction cheaper.
|
|
event NewCheckpointEvent(uint indexed index, address grantor, bytes32 checkpointHash);
|
|
|
|
// AddAdminEvent is emitted when new address is accepted as admin.
|
|
// Grantor indicates who authorizes the add admin operation.
|
|
event AddAdminEvent(address addr, address grantor, string description);
|
|
|
|
// RemoveAdminEvent is emitted when an admin is removed.
|
|
// Grantor indicates who authorizes the remove admin operation.
|
|
event RemoveAdminEvent(address addr, address grantor, string reason);
|
|
|
|
/*
|
|
Public Functions
|
|
*/
|
|
constructor(address[] _adminlist) public {
|
|
// regard contract creator as a default admin.
|
|
admins[msg.sender] = 1;
|
|
adminList.push(msg.sender);
|
|
for (uint i = 0; i < _adminlist.length; i++) {
|
|
admins[_adminlist[i]] = 1;
|
|
adminList.push(_adminlist[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @dev Get latest stable checkpoint information.
|
|
* @return section index
|
|
* @return checkpoint hash
|
|
*/
|
|
function GetLatestCheckpoint()
|
|
view
|
|
public
|
|
returns(uint, bytes32) {
|
|
bytes32 hash = GetCheckpoint(latest);
|
|
return (latest, hash);
|
|
}
|
|
|
|
/**
|
|
* @dev Get a stable checkpoint information with specified section index.
|
|
* @param _sectionIndex section index
|
|
* @return checkpoint hash
|
|
*/
|
|
function GetCheckpoint(uint _sectionIndex)
|
|
view
|
|
public
|
|
returns(bytes32)
|
|
{
|
|
return checkpoints[_sectionIndex];
|
|
}
|
|
|
|
/**
|
|
* @dev Set stable checkpoint information.
|
|
* Checkpoint represents a set of post-processed trie roots (CHT and BloomTrie)
|
|
* associated with the appropriate section head hash.
|
|
*
|
|
* It is used to start light syncing from this checkpoint
|
|
* and avoid downloading the entire header chain while still being able to securely
|
|
* access old headers/logs.
|
|
*
|
|
* Note we trust the given information here provided by foundation,
|
|
* need a trust less version for future.
|
|
* @param _sectionIndex section index
|
|
* @param _sectionHead section header
|
|
* @param _chtRoot cht root hash
|
|
* @param _bloomTrieRoot bloom trie root hash
|
|
* @return indicator whether set checkpoint successfully
|
|
*/
|
|
function SetCheckpoint(
|
|
uint _sectionIndex,
|
|
bytes32 _sectionHead,
|
|
bytes32 _chtRoot,
|
|
bytes32 _bloomTrieRoot
|
|
)
|
|
OnlyAuthorized
|
|
public
|
|
returns(bool)
|
|
{
|
|
// Ensure the checkpoint information provided is strictly continuous with previous one.
|
|
// But the latest checkpoint modification is allowed.
|
|
if (_sectionIndex != latest && _sectionIndex != latest + 1 && latest != 0) {
|
|
return false;
|
|
}
|
|
// Ensure the checkpoint is stable enough to be registered.
|
|
if (block.number < (_sectionIndex+1)*sectionSize+confirmations) {
|
|
return false;
|
|
}
|
|
|
|
checkpoints[_sectionIndex] = keccak256(abi.encodePacked(_sectionHead, _chtRoot, _bloomTrieRoot));
|
|
latest = _sectionIndex;
|
|
|
|
emit NewCheckpointEvent(_sectionIndex, msg.sender, checkpoints[_sectionIndex]);
|
|
}
|
|
|
|
/**
|
|
* @dev Add a new address to admin list
|
|
* @param _addr specified new admin address.
|
|
* @return indicator whether add new admin successfully
|
|
*/
|
|
function AddAdmin(address _addr, string _description)
|
|
OnlyAuthorized
|
|
public
|
|
returns(bool)
|
|
{
|
|
// Ensure the specified address is not admin yet.
|
|
if (admins[_addr] > 0) {
|
|
return false;
|
|
}
|
|
admins[_addr] = 1;
|
|
adminList.push(_addr);
|
|
|
|
emit AddAdminEvent(_addr, msg.sender, _description);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Remove a admin from the list
|
|
* @param _addr specified admin address to remove.
|
|
* @return indicator whether remove admin successfully
|
|
*/
|
|
function RemoveAdmin(address _addr, string _reason)
|
|
OnlyAuthorized
|
|
public
|
|
returns(bool)
|
|
{
|
|
// Ensure the specified address is admin.
|
|
if (admins[_addr] == 0) {
|
|
return false;
|
|
}
|
|
delete admins[_addr];
|
|
for (uint i = 0; i < adminList.length; i++) {
|
|
if (adminList[i] == _addr) {
|
|
// Not leave a gap
|
|
for (uint idx = i; idx < adminList.length-1; idx++){
|
|
adminList[idx] = adminList[idx+1];
|
|
}
|
|
delete adminList[adminList.length-1];
|
|
adminList.length -= 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
emit RemoveAdminEvent(_addr, msg.sender, _reason);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* @dev Get all admin addresses
|
|
* @return address list
|
|
*/
|
|
function GetAllAdmin()
|
|
public
|
|
view
|
|
returns(address[])
|
|
{
|
|
address[] memory ret = new address[](adminList.length);
|
|
for (uint i = 0; i < adminList.length; i++) {
|
|
ret[i] = adminList[i];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
Fields
|
|
*/
|
|
|
|
// A map of admin users who have the permission to update CHT and bloom Trie root
|
|
mapping(address => uint) admins;
|
|
|
|
// A list of admin users so that we can obtain all admin users.
|
|
address[] adminList;
|
|
|
|
// Registered checkpoint information
|
|
mapping(uint => bytes32) checkpoints;
|
|
|
|
// Latest stored section id
|
|
// Note all registered checkpoint information should continuous with previous one.
|
|
uint latest;
|
|
|
|
// The frequency for creating a checkpoint
|
|
uint constant sectionSize = 32768;
|
|
|
|
// The number of confirmations needed before a checkpoint can be registered.
|
|
// We have to make sure the checkpoint registered will not be invalid due to
|
|
// chain reorg.
|
|
uint constant confirmations = 256;
|
|
}
|
|
|