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

Majority funciona y tiene herramientas para comprobarlo.

parent c57e6963
No related branches found
No related tags found
No related merge requests found
...@@ -12,3 +12,5 @@ test2network*/bootnode ...@@ -12,3 +12,5 @@ test2network*/bootnode
test2network*/contracts/* test2network*/contracts/*
test2network/*.pid test2network/*.pid
node_modules node_modules
src/*/*.bin
src/*/*.abi
// Robert Martin-Legene <robert@nic.ar>
// vim:syntax:filetype=javascript:ai:sm
pragma solidity ^0.5;
// This contract is supposed to maintain a list of accounts authorized
// to control members of "the club" using a majority (n/1+1).
// For instance, could be useful for
// - a list of sealers
// - a board of directors
// - a local chess club
// - even outsourcing this kind of management from another smart contract.
contract Majority {
// 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?
bool promotion; // true=promotion, false=demotion
address[] voters; // List of voters.
}
address[] public voters;
Proposal[] public voterproposals;
event voteCast( address voter, address victim, bool promotionOrDemotion );
event adminChange( address admin, bool promotionOrDemotion );
constructor() public
{
// Don't want anyone to find a way to trigger the constructor again.
if ( voters.length == 0 )
voters.push( msg.sender );
}
// This function is used to know how many voters exist.
function votersLength() public view returns (uint)
{
return voters.length;
}
// This function is to be used to get the address from a specific position in the list.
// Remember first position is 0.
// Last position is voters.length-1.
function voterPosition( uint idx ) public view returns (address)
{
require( idx < voters.length, "There are not that many entries in the list." );
return voters[idx];
}
function isVoter( address subject ) public view returns (bool)
{
return ( _findAddressInList( voters, subject ) > 0 );
}
// Returns an index to the position of the needle inside haystack.
// Beware that:
// 0 = not found.
// 1 = first position in a list (so this is actually the real list position + 1).
function _findAddressInList( address[] memory haystack, address needle ) private pure 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
// front of the list.
uint max = voterproposals.length;
while ( ++idx < max )
voterproposals[idx-1] = voterproposals[idx];
// "pop" the end of the list, making the list shorter.
voterproposals.length--;
}
function _del_votes( address victim ) private
{
uint i_max = voterproposals.length;
uint i = i_max;
// check all proposals
while ( i-- > 0 )
{
// check all voters for every proposal
uint j_max = voterproposals[i].voters.length;
uint j = j_max;
while ( j-- > 0 )
if ( voterproposals[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 )
voterproposals[i].voters[k-1] = voterproposals[i].voters[k];
voterproposals[i].voters.length--;
j_max--;
if ( voterproposals[i].voters.length == 0 )
{
_remove_proposal( i );
i_max--;
}
}
}
}
function _remove_voter( 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 = voters.length;
uint i = max;
while ( i-- > 0 )
if ( voters[i] == victim )
{
// We could have recycled 'i' here, but for clarity, we don't.
uint j = i;
while ( ++j < max )
voters[j-1] = voters[j];
// "pop" the end of the list, making the list shorter.
voters.length--;
return;
}
}
// This function sees if any proposals have overstayed their welcome and thus
// needs to be removed. This is a bit like spring cleaning. We remove proposals
// that are over 30k blocks old.
function _trimProposals() private
{
uint i = voterproposals.length;
while ( i-- > 0 )
{
// If a proposal is more than 30K blocks old, then remove it from the list.
if ( voterproposals[i].votestart + 30000 <= block.number )
_remove_proposal( i );
}
}
// We run through the entire list of proposals, checking if they fulfill the
// requirements. Why the whole list? Because if a voter has been removed, whom has
// not yet voted for a proposal, that proposal may now have achieved majority.
function _promotedemote() private
{
uint prevlength = 0;
// Keep looping over the list until the number of proposals stops changing.
while ( prevlength != voterproposals.length )
{
uint i = voterproposals.length;
prevlength = i;
uint majority = voters.length / 2 + 1;
// Loop over all proposals
while ( i-- > 0 )
{
// If we have enough votes to perform the actual promotion/demotion
if ( voterproposals[i].voters.length >= majority )
{
// Is it a promotion or a demotion?
if ( voterproposals[i].promotion )
// Add victim to member list
voters.push( voterproposals[i].victim );
else
// Remove victim from member list
_remove_voter( voterproposals[i].victim );
// Send notification
emit adminChange( voterproposals[i].victim,
voterproposals[i].promotion );
// Remove the proposal because the voting is complete.
_remove_proposal( i );
}
}
}
}
// Returns an index to the position of the proposal inside matching the [victim,promotion] tuple
// Beware that:
// 0 = not found.
// 1 = first position.
function promotionIdx( address victim, bool promotion ) public view returns (uint)
{
uint i = voterproposals.length;
while ( i-- > 0)
if ( voterproposals[i].victim == victim && voterproposals[i].promotion == promotion )
return i+1;
return 0;
}
// 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 voter?
if ( !isVoter(voter) )
return false;
// Can't promote someone who is already a voter.
bool victimVoter = isVoter( victim );
if ( victimVoter && promotion )
return false;
// Can't demote someone who is not a member.
if ( !victimVoter && !promotion )
return false;
// See if the voter is already in the list of voters for this [victim,promotion] tuple
uint proppos = promotionIdx( victim, promotion );
if ( proppos > 0 && _findAddressInList( voterproposals[proppos-1].voters, voter ) > 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 member
// and false if you want to remove one.
function vote( address victim, bool promotion ) public
{
if ( ! mayVote(msg.sender, victim, promotion))
revert("That seems redundant or is otherwise not allowed.");
_trimProposals();
// Send notification of the vote
emit voteCast( msg.sender, victim, promotion );
uint proppos = promotionIdx( victim, promotion );
if ( proppos == 0 )
{
// This is a new proposal, so we will add it, so we can vote on it.
address[] memory emptyAddressList;
proppos = voterproposals.push( Proposal(victim, block.number, promotion, emptyAddressList ) );
}
proppos--;
// Add our vote
voterproposals[proppos].voters.push( msg.sender );
// See if we're ready to promote/demote anyone, based on the proposals.
_promotedemote();
// If we have no more voters, we have no reason to live.
if ( voters.length == 0 )
selfdestruct( msg.sender );
}
}
#!/usr/bin/node
"use strict"
const Libbfa = require( process.env.BFAHOME + '/bin/libbfa.js');
const BigInteger = require( 'big-integer' );
const fs = require( 'fs' );
var bfa = new Libbfa();
var web3 = bfa.newweb3();
// default
var gasprice = BigInteger(10).pow(9);
// globals
var accounts;
var thecontract;
function cat(filename)
{
try {
return fs.readFileSync( filename ).toString();
} catch (err) {
throw( 'Errors: ' + err.syscall + ' ' + err.path + ': ' + err.code);
}
}
function plural(num, one, many)
{
if (num == 1)
return one;
return many;
}
function isittrue( thebool, errortext )
{
return new Promise((resolve,reject) => {
if ( undefined == thebool )
reject( "thebool is undefined: " + errortext );
else
if ( thebool == true )
{
console.log( "Test OK: " + errortext );
resolve();
}
else
reject( errortext );
})
}
function echo( txt )
{
return new Promise((resolve,reject) => {
console.log( txt );
resolve();
})
}
function getgasprice()
{
return new Promise( (resolve, reject) => {
web3.eth.getGasPrice()
.then(
(sat) => {
gasprice = BigInteger(sat);
resolve();
},
reject
)
})
}
function unlockall()
{
return new Promise((resolve,reject) => {
var proms = new Array();
accounts.forEach(
(addr) => {
proms.push(
web3.eth.personal.unlockAccount( addr, '', 600 )
);
}
)
Promise.all( proms )
.then( resolve )
.catch( reject );
})
}
function gettestaccountnames()
{
return new Promise( (resolve, reject) => {
accounts = new Array();
web3.bfa.personal.listWallets(
( walletlist ) => {
walletlist.forEach(
( wallet ) => {
wallet.accounts.forEach(
( account ) => {
var addr = account.address;
if ( addr.startsWith('0x7e57') )
accounts.push( addr );
}
)
}
)
accounts.sort();
resolve();
}
);
})
}
function getaccountbalances()
{
return new Promise((resolve,reject) => {
if ( accounts.length < 4 )
throw( "Too few test accounts (found " + accounts.length + ", but need 4)." );
var proms = new Array();
var minimum = BigInteger(10).pow(9);
var failtxt;
accounts.forEach(
( acct ) => {
proms.push(
web3.eth.getBalance(acct)
.then(
( bal ) => {
var val = BigInteger( bal );
if ( val.lesser( minimum ) )
{
if ( undefined == failtxt )
failtxt +=
"The minimum balance on each test account must be at least "
+ minimum
+ " satoshi.\n"
failtxt +=
"The account balance of "
+ accounts[i]
+ " is "
+ val
+ " satoshi.\n"
}
}
)
)
}
);
Promise.all( proms )
.then(
() => {
if ( undefined == failtxt )
resolve();
else
reject(
failtxt +
"Tests can not be performed without balance on the accounts."
);
}
);
});
}
function councillistdetails()
{
return new Promise((resolve,reject) => {
thecontract.methods.councilLength.call()
.then(
(howmany) => {
console.log(
'The council has '
+ howmany
+ ' member'
+ plural(howmany,'','s')
+ '.');
return( howmany );
}
)
.then(
(howmany) => {
var proms = new Array();
for ( var i=0 ; i<howmany ; i++ )
proms.push( thecontract.methods.council(i).call() );
Promise.all( proms )
.then( (addrlist) => {
addrlist.forEach( (addr)=>{console.log("Council member: "+addr)} );
resolve( howmany );
});
}
);
})
}
function voteslistdetails()
{
return new Promise((resolve,reject) => {
thecontract.methods.votesLength.call()
.then(
(howmany) => {
console.log(
'There '
+ plural(howmany,'is ','are ')
+ howmany
+ ' vote'
+ plural(howmany,'','s')
+ ' registered.');
return( howmany );
}
)
.then(
(howmany) => {
var proms = new Array();
for ( var i=0 ; i<howmany ; i++ )
proms.push( thecontract.methods.votes(i).call() );
Promise.all( proms )
.then( (list) => {
list.forEach( (obj)=>{
console.log(
'Lodged vote: '
+ obj.voter
+ ' has voted to '
+ (obj.promotion?'promote':'demote')
+ ' '
+ obj.victim
);
} );
resolve( howmany );
});
}
);
})
}
function deploynew()
{
return new Promise((resolve, reject) => {
var abi = JSON.parse( cat('Majority.abi').trim() );
var bin = cat('Majority.bin').trim();
var cAddress;
var fetus = new web3.eth.Contract( abi );
console.log( "Deploying contract." );
var timeout = BigInteger( 86400 );
fetus.deploy(
{
data: '0x'+bin,
arguments: [ '0x'+timeout.toString(16) ]
}
)
.send(
{
from: accounts[0],
gas: 3000000,
gasPrice: '0x'+gasprice.toString(16),
}
)
.on( 'transactionHash', (hash) => {
console.log( "Deployed in txhash " + hash + "." );
})
.on( 'confirmation', (num,obj) => {
if ( undefined == cAddress )
{
cAddress = obj.contractAddress;
thecontract = new web3.eth.Contract( abi, cAddress );
console.log( "Contract is at " + cAddress );
resolve();
}
})
.on( 'error', reject );
});
}
function isCouncil( acctpos )
{
return new Promise((resolve,reject) => {
var acct = accounts[acctpos];
thecontract.methods.isCouncil(acct).call()
.then(
(yesno) => {
var not = 'not ';
if (yesno)
not = '';
console.log( acct + ' is ' + not + 'a council member.' );
resolve(yesno);
}
)
.catch( reject )
})
}
function vote( voterpos, victimpos, promotion )
{
return new Promise((resolve,reject) => {
var voter = accounts[voterpos];
var victim = accounts[victimpos];
var confirmed = false;
var demote = 'demote';
if (promotion)
demote = 'promote';
console.log( voter + " voting to " + demote + " " + victim );
thecontract.methods.vote( victim, promotion ).send({
from: voter,
gasPrice: "0x"+gasprice.toString(16),
gas: '0x'+BigInteger(10).pow(6).toString(16)
})
.on( 'transactionHash', (txhash) => {
console.log( ' - txhash ' + txhash );
})
.on( 'receipt', (rcpt) => {
console.log( ' - got a receipt' );
})
.on( 'confirmation', (num,obj) => {
if ( ! confirmed )
{
confirmed = true;
resolve();
}
})
.on( 'error', reject )
})
}
function mayVote(voterpos, victimpos, promotion)
{
return new Promise((resolve,reject) => {
var voter = accounts[voterpos];
var victim = accounts[victimpos];
var demote = 'demote';
if (promotion)
demote = 'promote';
thecontract.methods.mayVote( voter, victim, promotion ).call()
.then( (may) => {
var not = 'not ';
if ( may )
not = '';
console.log( voter + " may " + not + "vote to " + demote + " " + victim );
resolve( may );
},
reject
);
})
}
getgasprice()
.then( gettestaccountnames )
.then( getaccountbalances )
.then( unlockall )
.then( deploynew )
// initial conditions after deploying the contract
.then( councillistdetails )
.then( (n) => {return isittrue( n==1, "There should be 1 account in the council list." )})
.then( voteslistdetails )
.then( (n) => {return isittrue( n==0, "There should be no entries in the list of registered votes." )})
.then( () => {return isCouncil(0)} )
.then( (b) => {return isittrue( b, "Account should be a voter." )})
.then( () => {return isCouncil(1)} )
.then( (b) => {return isittrue( !b, "Account should not be a voter." )})
// Adding second account to the council - takes effect immediately, so votes.length == 0
.then( () => {return mayVote(0,1,true)} )
.then( (b) => {return isittrue( b, "Account should be allowed to vote for the approval of the new account." )})
.then( () => {return vote(0,1,true)} )
.then( voteslistdetails )
.then( (n) => {return isittrue( n==0, "There should be no entries in the list of registered votes." )})
.then( councillistdetails )
.then( (n) => {return isittrue( n==2, "There should be 2 accounts in the council list." )})
// Start voting to include third account
.then( () => {return mayVote(1,2,true)} )
.then( (b) => {return isittrue( b, "Account should be allowed to vote for the approval of the new account." )})
.then( () => {return vote(1,2,true)} )
.then( voteslistdetails )
.then( (n) => {return isittrue( n==1, "There should be 1 entry in the list of registered votes." )})
.then( councillistdetails )
.then( (n) => {return isittrue( n==2, "There should be 2 accounts in the council list." )})
// Start voting to remove second account (using second account)
.then( () => {return mayVote(1,1,false)} )
.then( (b) => {return isittrue( b, "Account should be allowed to vote for the removal of the account." )})
.then( () => {return vote(1,1,false)} )
.then( voteslistdetails )
.then( (n) => {return isittrue( n==2, "There should be 2 entries in the list of registered votes." )})
.then( councillistdetails )
.then( (n) => {return isittrue( n==2, "There should be 2 accounts in the council list." )})
// Finalizing vote to remove second account
.then( () => {return mayVote(0,1,false)} )
.then( (b) => {return isittrue( b, "Account should be allowed to vote for the removal of the account." )})
.then( () => {return vote(0,1,false)} )
.then( voteslistdetails )
.then( (n) => {return isittrue( n==0, "There should be no entries in the list of registered votes." )})
.then( councillistdetails )
.then( (n) => {return isittrue( n==1, "There should be 1 account in the council list." )})
// Vote to remove 3rd account.
.then( () => {return mayVote(0,2,true)} )
.then( (b) => {return isittrue( b, "Account should be allowed to vote for the approval of the new account." )})
.then( () => {return vote(0,2,true)} )
.then( voteslistdetails )
.then( (n) => {return isittrue( n==0, "There should be no entries in the list of registered votes." )})
.then( councillistdetails )
.then( (n) => {return isittrue( n==2, "There should be 1 account in the council list." )})
// this should self-destruct the contract
.then( () => {return vote(0,0,false)} )
.catch( (x) => {bfa.fatal("Test FAIL: " + x)})
.finally( () => {
console.log('** All tests completed successfully **');
process.exit();
});
// Robert Martin-Legene <robert@nic.ar>
// vim:syntax:filetype=javascript:ai:sm
pragma solidity ^0.5;
// This contract is supposed to maintain a list of accounts authorized
// to control members of "the club" using a majority (n/1+1). We call
// that group the "council".
// For instance, could be useful for
// - a list of sealers
// - a board of directors
// - a local chess club
// - even outsourcing this kind of management from another smart contract.
contract Majority {
// This struct contains a list of votes and who has voted for each victim/beneficiary.
struct Vote {
address voter; // Voter.
address victim; // Whom are we voting about.
uint voteStart; // When was the vote cast
bool promotion; // true=promotion, false=demotion
}
address[] public council;
Vote[] public votes;
uint public votetimeout = 604800; // default a week
event voteCast( address voter, address victim, bool promotion );
event adminChange( address admin, bool promotion );
constructor( uint timeout ) public
{
if ( timeout > 0 )
votetimeout = timeout;
council.push( address(msg.sender) );
}
function councilLength() public view returns (uint)
{
return council.length;
}
function votesLength() public view returns (uint)
{
return votes.length;
}
// True or false if the subject is a member of the council.
function isCouncil( address subject ) public view returns (bool)
{
uint i = council.length;
while ( i-- > 0 )
if ( subject == council[i] )
return true;
return false;
}
// Move all items in the list (after idx) one step closer to the
// front of the list.
function _remove_vote( uint idx ) private
{
uint max = votes.length;
while ( ++idx < max )
votes[idx-1] = votes[idx];
// "pop" the end of the list, making the list shorter.
votes.length--;
}
function _remove_council_member( address exmember ) private
{
// Remove votes that the exmember has already cast.
uint i = votes.length;
while ( i-- > 0 )
if ( votes[i].voter == exmember )
_remove_vote( i );
// Move all items in the council list (after match) one step closer to the
// front of the list.
i = council.length;
while ( i-- > 0 )
{
if ( council[i] == exmember )
{
uint idx = i;
uint max = council.length;
while ( ++idx < max )
council[idx-1] = council[idx];
// "pop" the end of the list, making the list shorter.
council.length--;
return;
}
}
}
// We run through the entire list of votes, checking if they fulfill the
// requirements.
function _promotedemote( address victim, bool promotion ) private
{
uint numvotes = 0;
uint majority = council.length / 2 + 1;
uint i = votes.length;
while ( i-- > 0 )
if (( votes[i].victim == victim )
&& ( votes[i].promotion == promotion )
)
numvotes++;
// If we don't have enough votes to perform the actual promotion/demotion
if ( numvotes < majority )
return;
// Is it a promotion or a demotion?
if ( promotion )
// Add victim to member list
council.push( victim );
else
// Remove victim from member list
_remove_council_member( victim );
// Send notification
emit adminChange( victim, promotion );
// Remove the vote because the voting is complete.
i = votes.length;
while ( i-- > 0 )
if (( votes[i].victim == victim )
&& ( votes[i].promotion == promotion )
)
_remove_vote( i );
}
// 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)
{
bool voterIsOnCouncil = isCouncil( voter );
bool victimIsOnCouncil = isCouncil( victim );
if ( ! voterIsOnCouncil )
return false;
// Can't promote someone who is already on the council
if ( victimIsOnCouncil && promotion )
return false;
// Can't demote someone who is not a council member.
if ( !victimIsOnCouncil && !promotion )
return false;
// See if he is trying to cast a vote already registered
uint ancient = block.timestamp - votetimeout;
uint i = votes.length;
while ( i-- > 0 )
{
if ( (votes[i].voter == voter)
&& (votes[i].victim == victim)
&& (votes[i].promotion == promotion)
&& (votes[i].voteStart > ancient)
)
return false;
}
return true;
}
// Calling this function will vote for adding an additional or
// removing an existing member of council.
// This requires n/2+1 votes (more than 50%).
// The boolean must be true if you want to add a member
// and false if you want to remove one.
function vote( address victim, bool promotion ) public
{
if ( ! mayVote(msg.sender, victim, promotion))
revert("That seems redundant or is otherwise not allowed.");
// A little house keeping - if a vote is too old, then remove it
uint ancient = block.timestamp - votetimeout;
uint i = votes.length;
while ( i-- > 0 )
if ( votes[i].voteStart < ancient )
_remove_vote( i );
// End of house keeping
// Store the vote
votes.push(
Vote(
msg.sender,
victim,
block.timestamp,
promotion
)
);
// Send notification of the vote
emit voteCast( address(msg.sender), victim, promotion );
// See if we're ready to promote/demote anyone, based on the votes.
_promotedemote( victim, promotion );
// If we have no more council members, then we have no reason to continue living.
if ( council.length == 0 )
selfdestruct( msg.sender );
}
}
../test/test-harness-v1.sh
\ No newline at end of file
Esta carpeta contiene llaves privadas.
Cuidado usar las llavas para algo importante (fuera de pruebas).
#!/bin/bash
true ${BFAHOME:=$( echo ~bfa/bfa )}
source ${BFAHOME}/bin/libbfa.sh || exit 1
function testfatal
{
test -n "$1" && echo $*
exit 1
}
function testcleanup
{
for filename in ${keyfiles}
do
test -f "${filename}"
rm "${filename}"
done
}
function writetestkeysto
{
local destinationdirectory=$1
for i in {1..4}
do
case $i in
1)
set 7e5705d6e4fd660ad6d2d6533f3b4b6647dbb0a2 ac6c3c3e7351f858a3ffd9db00dc70b72a16e5ab0723be0a3da6da228778ce29 717f2930a84107df56fcb3308c116cfe 64fc98daae4a96777b8c08396a92bc8dde1117d439c7eb0b9a016a11e512dc0a 89e869cae11f4a9b3d1f8d684119a64d6c1b25451152b5fb413c531813f83b0d 0643d804-b9df-4df9-8819-d38463480f15
;;
2)
set 7e57105001438399e318753387b061993753a545 3d3f422c4c227a37db5728e72c91e43cbd391f7e338fe6aaeb68b65416b33b48 676cf0e07562c52f6c933de714c0506f 8e9869dc6aab090ff389ecc84815d0abc108f437d11c1d56a91c83277c77acd5 87237d3a481ab6a1c50b9ef07b24c0118644e7bf3b27170766ec6b860300890d ee0c6421-b0f1-41db-934e-3cab0c419875
;;
3)
set 7e57215a8af47c70baca431c45ecf14199f4bd9a 84c5a655cdd6a402ef88ea1f64a4c427ce3cdaec88f352c0194254095b8b71c4 80e54ea9307624e2d4ec7179f2fcfa3c 9aaeba47fbb5e7ba8d327a1a544712184424021db8e4d238f60bdba81f02a4ca 7ef19ab55611ea649b65de754fb68d5f810550fe9ccfcfd2f067d3e56b4aee04 4b1c00d1-292f-4610-bbc0-2bb4d6489ea4
;;
4)
set 7e57348aec1b1fd574ef2c0702acaa197c46d613 2d6e3b21ab6c69ad789703acc967f93955690626333c667bc34e48650bf95d59 fc98dd18e1292cb5c6578ecbbc29cbb3 75cc35ea980da5b70aa146ac02fa9c3fd9d0015cdda8b6737ba17ba95f24cd8a fcb3ed29dfe7ec444c929e880ecc822af894ee497de7e29484ecccfcd7187b8b 05d45b22-185e-49d4-bc91-9ab684e8e75a
;;
*)
false
;;
esac
local address=$1
local ciphertext=$2
local iv=$3
local salt=$4
local mac=$5
local id=$6
local cipherparams="{\"iv\":\"${iv}\"}"
local kdfparams="{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"${salt}\"}"
local crypto="{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"${ciphertext}\",\"cipherparams\":${cipherparams},\"kdf\":\"scrypt\",\"kdfparams\":${kdfparams},\"mac\":\"${mac}\"}"
local thisfilename="${destinationdirectory}/UTC--2018-12-24T12-00-00.000000000Z--${address}"
echo "{\"address\":\"${address}\",\"crypto\":${crypto},\"id\":\"${id}\",\"version\":3}" > ${thisfilename}
keyfiles="${keyfiles} ${thisfilename}"
done
}
keyfiles=
trap testfatal ERR
trap testcleanup EXIT
contractname=$( ls -1 *.sol | head -1 | sed 's/\.sol$//' )
test -f ${contractname}.sol
test -r ${contractname}.sol
solc --combined-json abi,bin ${contractname}.sol > ${contractname}.json
jq -r ".contracts.\"${contractname}.sol:${contractname}\".abi" < ${contractname}.json > ${contractname}.abi
jq -r ".contracts.\"${contractname}.sol:${contractname}\".bin" < ${contractname}.json > ${contractname}.bin
rm ${contractname}.json
writetestkeysto ${BFANODEDIR}/keystore
for tester in ${contractname}-test*
do
if [ -n "${tester}" -a -x "${tester}" -a -r "${tester}" ]
then
./${tester}
fi
done
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