diff --git a/src/contract.Sealers.solc b/src/contract.Sealers.solc
index 03804744d7b7758a192b1e2c1f34a38271955344..47ae489fe24a48ddaea4b76ad6316d1e142cac45 100644
--- a/src/contract.Sealers.solc
+++ b/src/contract.Sealers.solc
@@ -1,15 +1,21 @@
 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 {
 
+    // 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 {
 	address         victim;     // Whom are we voting about.
-        uint            votestart;  // In which block did this vote begin?
+        uint256         votestart;  // In which block did this vote begin?
 	bool		promotion;  // true=promotion, false=demotion
 	address[]	voters;     // List of voters.
     }
-    Proposal[]          public	adminproposals;
     address[]           public  sealers;
+    Proposal[]          public	sealerproposals;
 
     event               vote( address voter, address victim, bool promotionOrDemotion );
     event               adminChange( address admin, bool promotionOrDemotion );
@@ -18,107 +24,139 @@ contract Sealers {
         sealers[0] = msg.sender;
     }
 
-    function isSealer( address subj ) public view returns (bool) {
-        for (uint i=sealers.length; i>0; i--)
-        {
-            if (subj == sealers[i-1])
-                return true;
-        }
-        return false;
-    }
-    modifier onlySealersTX {
-        require( isSealer( tx.origin ), "tx.origin is not a known sealer and can not call this function." );
-        _;
+    // Public utility, works on any list needle and haystack given.
+    //
+    // 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;
     }
-    modifier onlySealers {
-        require( isSealer( msg.sender ), "msg.sender is not a known sealer and can not call this function." );
-        _;
+    function sealerIdx( address needle ) public view returns (int256) {
+        return findAddressInList( sealers, needle );
     }
-
-    function sealerLength() public view returns (uint) {
+    // 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;
     }
-
-    function sealerPosition( uint idx ) public view returns (address) {
-        require( idx <= sealers.length, "There are not that many sealers registered in the list." );
+    // This function is to be used to get the address from a specific position in the sealers list.
+    // Remember first position is 0.
+    // 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];
     }
+    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 {
-        uint    i   =   adminproposals.length;
-        while ( i-- > 0 )
+        for ( uint256 i = sealerproposals.length-1; i>=0; i-- )
         {
-            if ( adminproposals[i].votestart < block.number+30000 )
-            {
-                while ( i < adminproposals.length )
-                {
-                    adminproposals[i] = adminproposals[i+1];
-                    i--;
-                }
-                adminproposals.length--;
-            }
+            // If a proposal is more than 30K blocks old, then remove it from the list.
+            if ( sealerproposals[i].votestart + 30000 <= block.number )
+                sealerproposals = _remove_entry( i, sealerproposals );
         }
     }
 
-    function admin_promote( address victim, bool promotion ) public onlySealersTX {
-        // Janitor
-        _trimProposals();
-        bool    isS =   isSealer(victim);
+    function    promotionIdx( address victim, bool promotion ) public view return (int256) {
+	uint256	idx     =   sealerproposals.length;
+	while ( idx-- > 0)
+            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?
-        if ( isS && promotion )
-            revert("You can't promote someone who is already a sealer.");
+        // Can't promote someone who is already a sealer.
+        if ( isSealer(victim) && promotion )
+            return false;
+
         // Is not Sealer and want to demote him?
-        if ( !isS && !promotion )
-            revert("You can't demote someone who is not a sealer.");
-        // First see if we can find the index of an already running proposal for this victim,promotion tupple.
-	uint	proppos =   adminproposals.length;
-	while ( proppos>0 && adminproposals[proppos-1].victim != victim && adminproposals[proppos-1].promotion != promotion)
-		proppos--;
-        // If we found no matching proposals, we will add it, so we can now vote on it.
-	if (proppos == 0)
+        // Can't demote someone who is not a sealer.
+        if ( !isSealer(victim) && !promotion )
+            return false;
+
+        // See if the voter is already in the list of voters for this [victim,promotion] tupple
+        int256  proppos     =   promotionIdx( victim, promotion );
+        if ( proppos > -1 && findAddressInList( sealerproposals[proppos].voters, voter ) > -1 )
+            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;
-	    proppos = adminproposals.push( Proposal(victim, block.number, promotion, sillycompiler ) );
+            // This is a new proposal, so we will add it, so we can vote on it.
+            address[] memory emptyAddressList;
+	    proppos = sealerproposals.push( Proposal(victim, block.number, promotion, emptyAddressList ) );
         }
-        // substract one, to make proppos actually reflect the position in the index.
-        proppos--;
+        else
+            proppos = uint256( signedretval & 0x7fffffffffffffffffffffffffffffff );
+
         // Make things a bit more easy to read by using a shorter variable name
-        Proposal memory prop = adminproposals[proppos];
-        // Now look through the proposal and see if this sender already voted.
-        uint    voterpos   =  prop.voters.length;
-        while ( voterpos>0 && prop.voters[voterpos-1] != msg.sender )
-            voterpos--;
-        // Return if sender already voted
-        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?
+        Proposal memory prop = sealerproposals[proppos];
+
+        // Add our vote
+        prop.voters.push( msg.sender );
+
+        // Stop here if we do not have enough votes to perform the actual promotion/demotion
         if ( prop.voters.length < sealers.length/2+1 )
             return;
-        //
+
+        // Remove the proposal because the voting is complete.
+        sealerproposals =   _remove_entry( proppos, sealerproposals );
+
         // Is it a promotion or a demotion?
-        if ( prop.promotion )
-        {
+        if ( promotion )
+            // Add victim to sealer list
             sealers.push( victim );
-        }
         else
-        {
-            uint    i = sealers.length;
-            // 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--;
+            // Remove victim from sealer list
+            sealers     =   _remove_entry( sealerIdx(victim), sealers );
+
         // Send notification
         emit adminChange( victim, promotion );
     }