-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
unsafe ed25519 delegation & ballot details aux contracts (#12)
* added ed25519 delegation contract * updated .gitignore * updated gitignore again * added ballot box aux contract * removed package-lock and yarn-error * Rename and slightly refactor Ed25519 self dlgtion * Update w/ init tests for self-delegation * fix sv-lib in bb test + implement revert checks * Add final tests for delegation * Refactor / reformat BallotDetailsAux a little (ABI CHANGES) * Fix up ed25519Delegation tests to work * Rename BallotDetailsAux to match contract * Implement bbFarmAux2 test section in index - also fix ganache * Add some extraData to dDeployBallot in ix init tests * Update tests - fix ganache so it should work on travis * add mkdir db to doTests.sh (and hopefully fix github-getting-stuck-on-checks-that-have-actually-already-passed issue) * Update truffle.js with logging
- Loading branch information
Showing
14 changed files
with
949 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,7 @@ scTopics | |
deploy*.log | ||
tmp* | ||
_solDist | ||
_distEns | ||
.DS_Store | ||
yarn-error.log | ||
db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
pragma solidity 0.4.24; | ||
|
||
interface IndexInterface { | ||
function getBBFarm(uint8) external view returns (BBFarmInterface); | ||
function getBBFarmID(bytes4) external view returns (uint8); | ||
function getBackend() external view returns (BackendInterface); | ||
} | ||
|
||
interface BackendInterface { | ||
function getDBallotID(bytes32, uint) external view returns (uint256); | ||
} | ||
|
||
interface BBFarmInterface { | ||
function getDetails(uint, address) external view returns | ||
( bool hasVoted | ||
, uint nVotesCast | ||
, bytes32 secKey | ||
, uint16 submissionBits | ||
, uint64 startTime | ||
, uint64 endTime | ||
, bytes32 specHash | ||
, bool deprecated | ||
, address ballotOwner | ||
, bytes16 extraData | ||
); | ||
} | ||
|
||
|
||
contract BBFarmAux2 { | ||
function _ballotIdToNamespace(uint ballotId) internal pure returns (bytes4) { | ||
return bytes4(ballotId >> 224); | ||
} | ||
|
||
function getBBFarmAddressFromBallotId(IndexInterface ix, uint256 ballotId) internal view returns (address) { | ||
return ix.getBBFarm(ix.getBBFarmID(_ballotIdToNamespace(ballotId))); | ||
} | ||
|
||
function getBallotId(BackendInterface ixBackend, bytes32 democHash, uint ballotN) internal view returns (uint ballotId) { | ||
ballotId = ixBackend.getDBallotID(democHash, ballotN); | ||
} | ||
|
||
function getBBFarmAddressAndBallotId( | ||
IndexInterface ix, | ||
bytes32 democHash, | ||
uint ballotN | ||
) external view returns (address bbFarmAddress, uint256 ballotId) { | ||
ballotId = getBallotId(ix.getBackend(), democHash, ballotN); | ||
bbFarmAddress = getBBFarmAddressFromBallotId(ix, ballotId); | ||
} | ||
|
||
function getBallotDetails(BBFarmInterface bbFarm, uint ballotId, address voterAddress) external view returns | ||
( bool hasVoted | ||
, uint nVotesCast | ||
, bytes32 secKey | ||
, uint16 submissionBits | ||
, uint64 startTime | ||
, uint64 endTime | ||
, bytes32 specHash | ||
, bool deprecated | ||
, address ballotOwner | ||
, bytes16 extraData | ||
) | ||
{ | ||
return bbFarm.getDetails(ballotId, voterAddress); | ||
} | ||
|
||
function ballotIdToDetails(IndexInterface ix, uint ballotId) external view returns | ||
( uint nVotesCast | ||
, bytes32 secKey | ||
, uint16 submissionBits | ||
, uint64 startTime | ||
, uint64 endTime | ||
, bytes32 specHash | ||
, bool deprecated | ||
) | ||
{ | ||
BBFarmInterface bbFarm = ix.getBBFarm(ix.getBBFarmID(_ballotIdToNamespace(ballotId))); | ||
(, nVotesCast, secKey, submissionBits, startTime, endTime, specHash, deprecated,,) = bbFarm.getDetails(ballotId, address(0)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
pragma solidity 0.4.24; | ||
|
||
import {MemArrApp as M} from "../libs/MemArrApp.sol"; | ||
|
||
contract UnsafeEd25519SelfDelegation { | ||
|
||
event DelegationCreated(bytes32 dlgtRequest, bytes32 pubKey, bytes32[2] signature); | ||
|
||
struct Delegation { | ||
bytes32 dlgtRequest; | ||
bytes32 sig1; | ||
bytes32 sig2; | ||
uint recordedTs; | ||
} | ||
|
||
// Maps a public key to delegation | ||
// We need a list here because we can't validate delegations on-chain, | ||
// so we store all delegaitons such that we can find the most recent valid delegation | ||
mapping (bytes32 => Delegation[]) public delegations; | ||
// allows us to loop through all pubkeys for which delegations have been made | ||
bytes32[] public delegationsLog; | ||
|
||
// Log addresses ppl are delegating _to_ | ||
mapping (address => bool) public seenAddress; | ||
// allows us to loop through all eth addresses which have been made delegates | ||
// (note: based on unverified delegations) | ||
address[] public addressLog; | ||
|
||
// Log delegation requests we haven't seen before - prevent replay attacks | ||
mapping (bytes32 => bool) public dlgtReqsSeen; | ||
|
||
// Constructor | ||
constructor() public {} | ||
|
||
// Adding a delegation - the single write operation in this contract | ||
function addUntrustedSelfDelegation(bytes32 dlgtRequest, bytes32 pubKey, bytes32[2] signature) external { | ||
// note: dlgtRequest is split into 9, 3, and 20 bytes; the former is a unique tag to ensure signatures from | ||
// ED25519 keys can't be reused for transactions or other networks, the 3 bytes are used as a nonce, and | ||
// the final 20 bytes is the ethereum address we're delegating too. | ||
|
||
// take first 9 bytes of dlgtRequest | ||
require(bytes9(dlgtRequest) == bytes9(0x53562d45442d455448), "dlgtReq header != SV-ED-ETH"); | ||
|
||
// // make sure we haven't seen this delegation request before with this pubkey and sig | ||
bytes32 dlgtReqAllHash = keccak256(abi.encodePacked(dlgtRequest, pubKey, signature[0], signature[1])); | ||
require(dlgtReqsSeen[dlgtReqAllHash] == false, "replay"); | ||
dlgtReqsSeen[dlgtReqAllHash] = true; | ||
|
||
// log the pubkey if we haven't seen it before | ||
if (delegations[pubKey].length == 0) | ||
delegationsLog.push(pubKey); | ||
|
||
delegations[pubKey].push(Delegation(dlgtRequest, signature[0], signature[1], now)); | ||
emit DelegationCreated(dlgtRequest, pubKey, signature); | ||
|
||
// take last 20 bytes and convert to address | ||
address dlgtTo = address(uint160(dlgtRequest)); | ||
|
||
if (!seenAddress[dlgtTo]) { | ||
seenAddress[dlgtTo] = true; | ||
addressLog.push(dlgtTo); | ||
} | ||
} | ||
|
||
// Simple getters for list lengths | ||
function dLogN() external view returns (uint) { | ||
return delegationsLog.length; | ||
} | ||
|
||
function nDelegations(bytes32 pubKey) external view returns (uint) { | ||
return delegations[pubKey].length; | ||
} | ||
|
||
function nAddressLog() external view returns (uint) { | ||
return addressLog.length; | ||
} | ||
|
||
// Complex Getters | ||
|
||
// Get all delegations recorded for a particular public key | ||
function getAllForPubKey(bytes32 pubKey) external view returns ( | ||
bytes32[] memory dlgtRequests, | ||
bytes32[] memory sigs1, | ||
bytes32[] memory sigs2, | ||
uint[] recordedTs | ||
) { | ||
return getAllForPubKeyBetween(pubKey, 0, 2**64-1); | ||
} | ||
|
||
function _delegationInRange(Delegation storage d, uint start, uint end) internal view returns (bool) { | ||
return d.recordedTs >= start && d.recordedTs <= end; | ||
} | ||
|
||
// Get all recorded delegations between a start date and end date | ||
function getAllForPubKeyBetween(bytes32 pubKey, uint startDate, uint endDate) public view returns ( | ||
bytes32[] memory dlgtRequests, | ||
bytes32[] memory sig1s, | ||
bytes32[] memory sig2s, | ||
uint[] timestamps | ||
) { | ||
for (uint i = 0; i < delegations[pubKey].length; i++) { | ||
if (_delegationInRange(delegations[pubKey][i], startDate, endDate)) { | ||
dlgtRequests = M.appendBytes32(dlgtRequests, delegations[pubKey][i].dlgtRequest); | ||
sig1s = M.appendBytes32(sig1s, delegations[pubKey][i].sig1); | ||
sig2s = M.appendBytes32(sig2s, delegations[pubKey][i].sig2); | ||
timestamps = M.appendUint256(timestamps, delegations[pubKey][i].recordedTs); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Exit script as soon as a command fails. | ||
set -o errexit | ||
|
||
# check for coverage which will specify new port for ethereum client | ||
if [ "$SOLIDITY_COVERAGE" = true ]; then | ||
GETH_PORT=8555 | ||
else | ||
GETH_PORT=8545 | ||
fi | ||
|
||
PARITY_VERSION=v1.8.0 | ||
GETH_VERSION=v1.7.3-instantseal | ||
|
||
client_running() { | ||
nc -z localhost "$GETH_PORT" | ||
} | ||
|
||
start_testrpc() { | ||
if [ "$SOLIDITY_COVERAGE" = true ]; then | ||
node_modules/.bin/testrpc-sc -i 16 --gasLimit 0xfffffffffff --port "$GETH_PORT" > /dev/null & | ||
else | ||
node_modules/.bin/ganache-cli -i 15 --gasLimit 50000000 > /dev/null & | ||
fi | ||
|
||
rpc_pid=$! | ||
} | ||
|
||
check_docker() { | ||
# check that docker exists before attempting to pull/run images | ||
if ! [ -x "$(command -v docker)" ]; then | ||
echo 'Error: docker is not installed' >&2 | ||
exit 1 | ||
fi | ||
} | ||
|
||
start_parity() { | ||
check_docker | ||
# pull the most stable release of parity | ||
docker pull purta/parity-instantseal:$PARITY_VERSION | ||
# run the container in detached mode | ||
docker run -d -p 8545:8545 purta/parity-instantseal:$PARITY_VERSION | ||
|
||
sleep 5 | ||
} | ||
|
||
start_geth() { | ||
check_docker | ||
# pull the latest image using the dev test network | ||
docker pull purta/geth-devnet:$GETH_VERSION | ||
# run the geth dev network container | ||
docker run -d -p 8545:8545 purta/geth-devnet:$GETH_VERSION | ||
|
||
echo "Letting client warmup for 5 seconds..." | ||
sleep 5 | ||
} | ||
|
||
if client_running; then | ||
echo "Using existing geth instance at port $GETH_PORT" | ||
else | ||
echo "Starting our own ethereum client at port $GETH_PORT" | ||
case $GETH_CLIENT in | ||
geth ) | ||
start_geth | ||
;; | ||
parity ) | ||
start_parity | ||
;; | ||
* ) | ||
echo "No ethereum client specified, using testrpc..." | ||
start_testrpc | ||
;; | ||
esac | ||
fi | ||
|
||
sleep 5 |
Oops, something went wrong.