Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
nucleo
Manage
Activity
Members
Labels
Plan
Issues
4
Issue boards
Milestones
Wiki
Code
Merge requests
1
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
blockchain
nucleo
Commits
223fcc24
Commit
223fcc24
authored
6 years ago
by
Robert Martin-Legene
Browse files
Options
Downloads
Patches
Plain Diff
Major rewrite of the Sealers contract. Bugs weeded out, and more public functions.
parent
113e0725
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/contract.Sealers.solc
+119
-81
119 additions, 81 deletions
src/contract.Sealers.solc
with
119 additions
and
81 deletions
src/contract.Sealers.solc
+
119
−
81
View file @
223fcc24
pragma solidity ^0.4.22;
pragma solidity ^0.4.22;
// 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
// must occasionally (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.
// 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.
uint
votestart; // In which block did this vote begin?
uint
256
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.
}
}
Proposal[] public adminproposals;
address[] public sealers;
address[] public sealers;
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 );
...
@@ -18,107 +24,139 @@ contract Sealers {
...
@@ -18,107 +24,139 @@ contract Sealers {
sealers[0] = msg.sender;
sealers[0] = msg.sender;
}
}
function isSealer( address subj ) public view returns (bool) {
// Public utility, works on any list needle and haystack given.
for (uint i=sealers.length; i>0; i--)
//
{
// Returns an index to the position of the needle inside haystack.
if (subj == sealers[i-1])
// 0 is first position. -1 means not found.
return true;
function findAddressInList( address[] haystack, address needle ) public pure returns (int256) {
}
uint256 i = haystack.length;
return false;
while ( i-- > 0 )
}
if ( needle == haystack[i] )
modifier onlySealersTX {
return int256(i & 0x7fffffffffffffffffffffffffffffff);
require( isSealer( tx.origin ), "tx.origin is not a known sealer and can not call this function." );
return -1;
_;
}
}
modifier onlySealers {
function sealerIdx( address needle ) public view returns (int256) {
require( isSealer( msg.sender ), "msg.sender is not a known sealer and can not call this function." );
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 (uint) {
function sealerLength() public view returns (uint
256
) {
return sealers.length;
return sealers.length;
}
}
// This function is to be used to get the address from a specific position in the sealers list.
function sealerPosition( uint idx ) public view returns (address) {
// Remember first position is 0.
require( idx <= sealers.length, "There are not that many sealers registered in the list." );
// Last position is sealers.length-1.
function sealerPosition( uint256 idx ) public view returns (address) {
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 requireSealer( address subject ) public view {
require( isSealer(subject), "Not sealer" );
}
function _remove_entry( uint256 idx, list alist ) private returns (list) {
uint256 pos = idx;
// Move all items in the list (after idx) one step closer to the
// front of the list.
while ( ++pos < list.length )
alist[pos-1] = alist[pos];
// "pop" the end of the list, making the list shorter.
alist.length--;
return alist;
}
// This function sees if any proposals have overstayed their welcome and thus
// needs to be removed.
function _trimProposals() private {
function _trimProposals() private {
uint i = adminproposals.length;
for ( uint256 i = sealerproposals.length-1; i>=0; i-- )
while ( i-- > 0 )
{
{
if ( adminproposals[i].votestart < block.number+30000 )
// If a proposal is more than 30K blocks old, then remove it from the list.
{
if ( sealerproposals[i].votestart + 30000 <= block.number )
while ( i < adminproposals.length )
sealerproposals = _remove_entry( i, sealerproposals );
{
adminproposals[i] = adminproposals[i+1];
i--;
}
adminproposals.length--;
}
}
}
}
}
function admin_promote( address victim, bool promotion ) public onlySealersTX {
function promotionIdx( address victim, bool promotion ) public view return (int256) {
// Janitor
uint256 idx = sealerproposals.length;
_trimProposals();
while ( idx-- > 0)
bool isS = isSealer(victim);
if ( sealerproposals[idx].victim == victim && sealerproposals[idx].promotion == promotion )
return idx;
return -1;
}
// You can call this for free and know if your promote call
// will get accepted. Save the network, call this first.
function mayVote( address voter, address victim, bool promotion ) public view returns (bool)
{
// Is caller a sealer?
if ( !isSealer(voter) )
return false;
// Is already Sealer and want to promote him?
// Is already Sealer and want to promote him?
if ( isS && promotion )
// Can't promote someone who is already a sealer.
revert("You can't promote someone who is already a sealer.");
if ( isSealer(victim) && promotion )
return false;
// Is not Sealer and want to demote him?
// Is not Sealer and want to demote him?
if ( !isS && !promotion )
// Can't demote someone who is not a sealer.
revert("You can't demote someone who is not a sealer.");
if ( !isSealer(victim) && !promotion )
// First see if we can find the index of an already running proposal for this victim,promotion tupple.
return false;
uint proppos = adminproposals.length;
while ( proppos>0 && adminproposals[proppos-1].victim != victim && adminproposals[proppos-1].promotion != promotion)
// See if the voter is already in the list of voters for this [victim,promotion] tupple
proppos--;
int256 proppos = promotionIdx( victim, promotion );
// If we found no matching proposals, we will add it, so we can now vote on it.
if ( proppos > -1 && findAddressInList( sealerproposals[proppos].voters, voter ) > -1 )
if (proppos == 0)
return false;
return true;
}
// Calling this function will vote for adding an additional or
// removing an existing member of "the inner circle".
// As per usual, this requires n/2+1 votes.
// The boolean must be true if you want to add a sealer
// and false if you want to remove one.
function promote( address victim, bool promotion ) public {
if ( ! mayVote(msg.sender, victim, promotion))
revert("That seems redundant.");
_trimProposals();
// Send notification of the vote
emit vote( msg.sender, victim, promotion );
// signed as opposed to unsigned (int)
int256 signedretval = promotionIdx( victim, promotion );
uint proppos;
if ( signedretval == -1 )
{
{
address[] memory sillycompiler;
// This is a new proposal, so we will add it, so we can vote on it.
proppos = adminproposals.push( Proposal(victim, block.number, promotion, sillycompiler ) );
address[] memory emptyAddressList;
proppos = sealerproposals.push( Proposal(victim, block.number, promotion, emptyAddressList ) );
}
}
// substract one, to make proppos actually reflect the position in the index.
else
proppos--;
proppos = uint256( signedretval & 0x7fffffffffffffffffffffffffffffff );
// Make things a bit more easy to read by using a shorter variable name
// Make things a bit more easy to read by using a shorter variable name
Proposal memory prop = adminproposals[proppos];
Proposal memory prop = sealerproposals[proppos];
// Now look through the proposal and see if this sender already voted.
uint voterpos = prop.voters.length;
// Add our vote
while ( voterpos>0 && prop.voters[voterpos-1] != msg.sender )
prop.voters.push( msg.sender );
voterpos--;
// Return if sender already voted
// Stop here if we do not have enough votes to perform the actual promotion/demotion
if ( voterpos > 0 )
revert("You can not vote twice.");
// Send notification of the valid vote
emit vote( msg.sender, victim, promotion );
// Do we have enough votes to perform the operation?
if ( prop.voters.length < sealers.length/2+1 )
if ( prop.voters.length < sealers.length/2+1 )
return;
return;
//
// Remove the proposal because the voting is complete.
sealerproposals = _remove_entry( proppos, sealerproposals );
// Is it a promotion or a demotion?
// Is it a promotion or a demotion?
if (
prop.
promotion )
if ( promotion )
{
// Add victim to sealer list
sealers.push( victim );
sealers.push( victim );
}
else
else
{
// Remove victim from sealer list
uint i = sealers.length;
sealers = _remove_entry( sealerIdx(victim), sealers );
// Delete all occurences of the victim from the sealer list (should be just a single occurence)
while ( i-- > 0 ) {
if (sealers[i] == victim )
{
for (uint j=i; j<sealers.length-1; j--)
sealers[j] = sealers[j+1];
sealers.length--;
}
}
}
// Remove the proposal, as the voting is complete.
for (i=proppos; i<adminproposals.length-1; i--)
adminproposals[i] = adminproposals[i+1];
adminproposals.length--;
// Send notification
// Send notification
emit adminChange( victim, promotion );
emit adminChange( victim, promotion );
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment