Skip to content
Snippets Groups Projects
Commit 6fdf5e9e authored by Robert Martin-Legene's avatar Robert Martin-Legene
Browse files

Made Sealers.sol compile and deploy. Needs testing.

parent 223fcc24
No related branches found
No related tags found
No related merge requests found
pragma solidity ^0.4.22; // vim:syntax:filetype=javascript:ai:sm
pragma solidity ^0.4.24;
// This contract is supposed to maintain the list of authorized sealers. // This contract is supposed to maintain the list of authorized sealers.
// For this to work, a sealer must deploy the contract and then all sealers // For this to work, a sealer must deploy the contract and then all sealers
// must occasionally (every 5 minutes) run the related SealerSync.js // must, say, every 5 minutes, run the related SealerSync.js
contract Sealers { contract Sealers {
// This struct contains a list of votes and who has voted for each victim/beneficiary. // This struct contains a list of votes and who has voted for each victim/beneficiary.
// Votes taking longer than 30K blocks, will have to restart. // Votes taking longer than 30K blocks, will have to restart.
struct Proposal { struct Proposal {
address victim; // Whom are we voting about. address victim; // Whom are we voting about.
uint256 votestart; // In which block did this vote begin? uint votestart; // In which block did this vote begin?
bool promotion; // true=promotion, false=demotion bool promotion; // true=promotion, false=demotion
address[] voters; // List of voters. address[] voters; // List of voters.
} }
address[] public sealers; address[] public sealers;
Proposal[] public sealerproposals; Proposal[] public sealerproposals;
event vote( address voter, address victim, bool promotionOrDemotion ); event vote( address voter, address victim, bool promotionOrDemotion );
event adminChange( address admin, bool promotionOrDemotion ); event adminChange( address admin, bool promotionOrDemotion );
constructor() public { constructor() public
sealers[0] = msg.sender; {
sealers.push( msg.sender );
} }
// Public utility, works on any list needle and haystack given. // This function is used to know how many sealers are in the sealers list.
// function sealerLength() public view returns (uint)
// Returns an index to the position of the needle inside haystack. {
// 0 is first position. -1 means not found.
function findAddressInList( address[] haystack, address needle ) public pure returns (int256) {
uint256 i = haystack.length;
while ( i-- > 0 )
if ( needle == haystack[i] )
return int256(i & 0x7fffffffffffffffffffffffffffffff);
return -1;
}
function sealerIdx( address needle ) public view returns (int256) {
return findAddressInList( sealers, needle );
}
// This function is to be used to know how many sealers are in the sealers list.
function sealerLength() public view returns (uint256) {
return sealers.length; return sealers.length;
} }
// This function is to be used to get the address from a specific position in the sealers list. // This function is to be used to get the address from a specific position in the sealers list.
// Remember first position is 0. // Remember first position is 0.
// Last position is sealers.length-1. // Last position is sealers.length-1.
function sealerPosition( uint256 idx ) public view returns (address) { function sealerPosition( uint idx ) public view returns (address)
{
require( idx < sealers.length, "There are not that many sealers registered in the list." ); require( idx < sealers.length, "There are not that many sealers registered in the list." );
return sealers[idx]; return sealers[idx];
} }
function isSealer( address subject ) public view returns (bool) {
return ( sealerIdx(subject) > -1 ); function isSealer( address subject ) public view returns (bool)
{
return ( _findAddressInList( sealers, subject ) > 0 );
} }
function requireSealer( address subject ) public view {
function requireSealer( address subject ) public view
{
require( isSealer(subject), "Not sealer" ); require( isSealer(subject), "Not sealer" );
} }
function _remove_entry( uint256 idx, list alist ) private returns (list) { // Returns an index to the position of the needle inside haystack.
uint256 pos = idx; // Beware that:
// 0 = not found.
// 1 = first position.
function _findAddressInList( address[] haystack, address needle ) private view returns (uint)
{
uint i = haystack.length;
while ( i-- > 0 )
if ( needle == haystack[i] )
return i+1;
return 0;
}
function _remove_proposal( uint idx ) private
{
// Move all items in the list (after idx) one step closer to the // Move all items in the list (after idx) one step closer to the
// front of the list. // front of the list.
while ( ++pos < list.length ) uint max = sealerproposals.length;
alist[pos-1] = alist[pos]; while ( ++idx < max )
sealerproposals[idx-1] = sealerproposals[idx];
// "pop" the end of the list, making the list shorter. // "pop" the end of the list, making the list shorter.
alist.length--; sealerproposals.length--;
return alist; }
function _del_votes( address victim ) private
{
uint i_max = sealerproposals.length;
uint i = i_max;
// check all proposals
while ( i-- > 0 )
{
// check all voters for every proposal
uint j_max = sealerproposals[i].voters.length;
uint j = j_max;
while ( j-- > 0 )
if ( sealerproposals[i].voters[j] == victim )
{
// Found the victim as voter, but since he is about
// to be deleted, we will remove him from the list.
uint k = j;
while ( ++k < j_max )
sealerproposals[i].voters[k-1] = sealerproposals[i].voters[k];
sealerproposals[i].voters.length--;
j_max--;
if ( sealerproposals[i].voters.length == 0 )
{
_remove_proposal( i );
i_max--;
}
}
}
}
function _remove_sealer( address victim ) private
{
// Remove votes that the victim has already cast.
_del_votes( victim );
// Move all items in the list (after match) one step closer to the
// front of the list.
uint max = sealers.length;
uint i = max;
while ( i-- > 0 )
if ( sealers[i] == victim )
{
// We could have recycled 'i' here, but for clarity, we don't.
uint j = i;
while ( ++j < max )
sealers[j-1] = sealers[j];
// "pop" the end of the list, making the list shorter.
sealers.length--;
return;
}
} }
// This function sees if any proposals have overstayed their welcome and thus // This function sees if any proposals have overstayed their welcome and thus
// needs to be removed. // needs to be removed.
function _trimProposals() private { function _trimProposals() private
for ( uint256 i = sealerproposals.length-1; i>=0; i-- ) {
for ( uint i = sealerproposals.length-1; i>=0; i-- )
{ {
// If a proposal is more than 30K blocks old, then remove it from the list. // If a proposal is more than 30K blocks old, then remove it from the list.
if ( sealerproposals[i].votestart + 30000 <= block.number ) if ( sealerproposals[i].votestart + 30000 <= block.number )
sealerproposals = _remove_entry( i, sealerproposals ); _remove_proposal( i );
} }
} }
function promotionIdx( address victim, bool promotion ) public view return (int256) { // Returns an index to the position of the proposal inside matching the [victim,promotion] tuple
uint256 idx = sealerproposals.length; // Beware that:
while ( idx-- > 0) // 0 = not found.
if ( sealerproposals[idx].victim == victim && sealerproposals[idx].promotion == promotion ) // 1 = first position.
return idx; function promotionIdx( address victim, bool promotion ) public view returns (uint)
return -1; {
uint i = sealerproposals.length;
while ( i-- > 0)
if ( sealerproposals[i].victim == victim && sealerproposals[i].promotion == promotion )
return i+1;
return 0;
} }
// You can call this for free and know if your promote call // You can call this for free and know if your promote call
...@@ -104,9 +169,9 @@ contract Sealers { ...@@ -104,9 +169,9 @@ contract Sealers {
if ( !isSealer(victim) && !promotion ) if ( !isSealer(victim) && !promotion )
return false; return false;
// See if the voter is already in the list of voters for this [victim,promotion] tupple // See if the voter is already in the list of voters for this [victim,promotion] tuple
int256 proppos = promotionIdx( victim, promotion ); uint proppos = promotionIdx( victim, promotion );
if ( proppos > -1 && findAddressInList( sealerproposals[proppos].voters, voter ) > -1 ) if ( proppos > 0 && _findAddressInList( sealerproposals[proppos-1].voters, voter ) > 0 )
return false; return false;
return true; return true;
} }
...@@ -116,38 +181,33 @@ contract Sealers { ...@@ -116,38 +181,33 @@ contract Sealers {
// As per usual, this requires n/2+1 votes. // As per usual, this requires n/2+1 votes.
// The boolean must be true if you want to add a sealer // The boolean must be true if you want to add a sealer
// and false if you want to remove one. // and false if you want to remove one.
function promote( address victim, bool promotion ) public { function promote( address victim, bool promotion ) public
{
if ( ! mayVote(msg.sender, victim, promotion)) if ( ! mayVote(msg.sender, victim, promotion))
revert("That seems redundant."); revert("That seems redundant or is otherwise not allowed.");
_trimProposals(); _trimProposals();
// Send notification of the vote // Send notification of the vote
emit vote( msg.sender, victim, promotion ); emit vote( msg.sender, victim, promotion );
// signed as opposed to unsigned (int) uint proppos = promotionIdx( victim, promotion );
int256 signedretval = promotionIdx( victim, promotion ); if ( proppos == 0 )
uint proppos;
if ( signedretval == -1 )
{ {
// This is a new proposal, so we will add it, so we can vote on it. // This is a new proposal, so we will add it, so we can vote on it.
address[] memory emptyAddressList; address[] memory emptyAddressList;
proppos = sealerproposals.push( Proposal(victim, block.number, promotion, emptyAddressList ) ); proppos = sealerproposals.push( Proposal(victim, block.number, promotion, emptyAddressList ) );
} }
else proppos--;
proppos = uint256( signedretval & 0x7fffffffffffffffffffffffffffffff );
// Make things a bit more easy to read by using a shorter variable name
Proposal memory prop = sealerproposals[proppos];
// Add our vote // Add our vote
prop.voters.push( msg.sender ); sealerproposals[proppos].voters.push( msg.sender );
// Stop here if we do not have enough votes to perform the actual promotion/demotion // Stop here if we do not have enough votes to perform the actual promotion/demotion
if ( prop.voters.length < sealers.length/2+1 ) if ( sealerproposals[proppos].voters.length < sealers.length/2+1 )
return; return;
// Remove the proposal because the voting is complete. // Remove the proposal because the voting is complete.
sealerproposals = _remove_entry( proppos, sealerproposals ); _remove_proposal( proppos );
// Is it a promotion or a demotion? // Is it a promotion or a demotion?
if ( promotion ) if ( promotion )
...@@ -155,9 +215,10 @@ contract Sealers { ...@@ -155,9 +215,10 @@ contract Sealers {
sealers.push( victim ); sealers.push( victim );
else else
// Remove victim from sealer list // Remove victim from sealer list
sealers = _remove_entry( sealerIdx(victim), sealers ); _remove_sealer( victim );
// Send notification // Send notification
emit adminChange( victim, promotion ); emit adminChange( victim, promotion );
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment