Updated contracts to support signature collection in side chain
This commit is contained in:
parent
642ea4e9a5
commit
6606fbab35
|
@ -54,6 +54,7 @@ contract Bridge {
|
|||
mapping(bytes32 => uint) public votesCount;
|
||||
mapping(bytes32 => bool) public votes;
|
||||
mapping(bytes32 => bool) public usedRange;
|
||||
mapping(bytes32 => bool) public handledTx;
|
||||
|
||||
Status public status;
|
||||
|
||||
|
@ -146,9 +147,59 @@ contract Bridge {
|
|||
emit ExchangeRequest(value, getNonce());
|
||||
}
|
||||
|
||||
function transfer(bytes32 hash, address to, uint value) public readyOrClosing currentValidator {
|
||||
if (tryVote(Vote.TRANSFER, hash, to, value)) {
|
||||
tokenContract.transfer(to, value);
|
||||
function transfer(bytes memory message, bytes memory signatures) public {
|
||||
require(message.length == 116, "Incorrect message length");
|
||||
require(signatures.length % 65 == 0, "Incorrect signatures length");
|
||||
|
||||
uint msgEpoch;
|
||||
bytes32 msgId;
|
||||
address msgTo;
|
||||
uint msgValue;
|
||||
|
||||
assembly {
|
||||
msgEpoch := mload(add(message, 32))
|
||||
msgId := mload(add(message, 64))
|
||||
msgTo := mload(add(message, 84))
|
||||
msgValue := mload(add(message, 116))
|
||||
}
|
||||
|
||||
require(msgEpoch <= epoch, "Invalid epoch number");
|
||||
require(!handledTx[msgId], "Tx was already handled");
|
||||
handledTx[msgId] = true;
|
||||
|
||||
address[] memory msgValidators = getValidatorsInEpoch(msgEpoch);
|
||||
|
||||
require(signatures.length / 65 >= getThreshold(msgEpoch), "Not enough signatures");
|
||||
|
||||
bytes32 msgHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n116", message));
|
||||
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
for (uint i = 0; i < signatures.length / 65; i++) {
|
||||
uint offset = i * 65;
|
||||
|
||||
assembly {
|
||||
r := mload(add(add(signatures,32),offset))
|
||||
s := mload(add(add(signatures,64),offset))
|
||||
v := byte(0, mload(add(add(signatures,96),offset)))
|
||||
}
|
||||
|
||||
address signer = ecrecover(msgHash, v, r, s);
|
||||
uint j;
|
||||
for (j = 0; j < msgValidators.length; j++) {
|
||||
if (msgValidators[j] == signer) {
|
||||
delete msgValidators[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(j != msgValidators.length);
|
||||
}
|
||||
if (tokenContract.balanceOf(address(this)) >= msgValue) {
|
||||
tokenContract.transfer(msgTo, msgValue);
|
||||
} else {
|
||||
tokenContract.approve(msgTo, msgValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,11 +333,15 @@ contract Bridge {
|
|||
}
|
||||
|
||||
function getValidators() view public returns (address[] memory) {
|
||||
return states[epoch].validators;
|
||||
return getValidatorsInEpoch(epoch);
|
||||
}
|
||||
|
||||
function getNextValidators() view public returns (address[] memory) {
|
||||
return states[nextEpoch].validators;
|
||||
return getValidatorsInEpoch(nextEpoch);
|
||||
}
|
||||
|
||||
function getValidatorsInEpoch(uint _epoch) view public returns (address[] memory) {
|
||||
return states[_epoch].validators;
|
||||
}
|
||||
|
||||
function startVoting() public readyOrVoting currentValidator {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
contract KeyValueStorage {
|
||||
mapping(bytes32 => bytes) public db;
|
||||
|
||||
function setData(bytes32 id, bytes32 key, bytes memory data) public {
|
||||
db[encodeKey(msg.sender, id, key)] = data;
|
||||
}
|
||||
|
||||
function getData(address from, bytes32 id, bytes32 key) view public returns (bytes memory) {
|
||||
return db[encodeKey(from, id, key)];
|
||||
}
|
||||
|
||||
function encodeKey(address sender, bytes32 id, bytes32 key) private pure returns (bytes32 hash) {
|
||||
return keccak256(abi.encodePacked(sender, id, key));
|
||||
}
|
||||
}
|
|
@ -1,42 +1,7 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
contract SharedDB {
|
||||
mapping(bytes32 => bytes) public db;
|
||||
mapping(bytes32 => uint) public signupsCount;
|
||||
mapping(bytes32 => uint) public dbSignups;
|
||||
import "./KeyValueStorage.sol";
|
||||
import "./SignedMessageStorage.sol";
|
||||
import "./SignupStorage.sol";
|
||||
|
||||
function signupSign(bytes32 hash) public {
|
||||
require(dbSignups[keccak256(abi.encodePacked(msg.sender, hash))] == 0, "Already signuped");
|
||||
|
||||
dbSignups[keccak256(abi.encodePacked(msg.sender, hash))] = ++signupsCount[hash];
|
||||
}
|
||||
|
||||
function getSignupNumber(bytes32 hash, address[] memory validators, address validator) view public returns (uint) {
|
||||
if (dbSignups[keccak256(abi.encodePacked(validator, hash))] == 0)
|
||||
return 0;
|
||||
uint id = 1;
|
||||
for (uint i = 0; i < validators.length; i++) {
|
||||
uint vid = dbSignups[keccak256(abi.encodePacked(validators[i], hash))];
|
||||
if (vid > 0 && vid < dbSignups[keccak256(abi.encodePacked(validator, hash))])
|
||||
id++;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function getSignupAddress(bytes32 hash, address[] memory validators, uint signupNumber) view public returns (address) {
|
||||
for (uint i = 0; i < validators.length; i++) {
|
||||
if (getSignupNumber(hash, validators, validators[i]) == signupNumber) {
|
||||
return validators[i];
|
||||
}
|
||||
}
|
||||
return address(0);
|
||||
}
|
||||
|
||||
function setData(bytes32 hash, bytes32 key, bytes memory data) public {
|
||||
db[keccak256(abi.encodePacked(msg.sender, hash, key))] = data;
|
||||
}
|
||||
|
||||
function getData(address from, bytes32 hash, bytes32 key) view public returns (bytes memory) {
|
||||
return db[keccak256(abi.encodePacked(from, hash, key))];
|
||||
}
|
||||
}
|
||||
contract SharedDB is KeyValueStorage, SignedMessageStorage, SignupStorage {}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
contract SignedMessageStorage {
|
||||
struct SignedMessage {
|
||||
bytes message;
|
||||
mapping(address => bytes) signatures;
|
||||
}
|
||||
|
||||
mapping(bytes32 => SignedMessage) signedMessages;
|
||||
|
||||
function addSignature(bytes memory message, bytes memory rsv) public {
|
||||
require(message.length == 116, "Incorrect message length");
|
||||
require(rsv.length == 65, "Incorrect signature length");
|
||||
|
||||
bytes32 msgHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n116", message));
|
||||
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
assembly {
|
||||
r := mload(add(rsv, 32))
|
||||
s := mload(add(rsv, 64))
|
||||
v := byte(0, mload(add(rsv, 96)))
|
||||
}
|
||||
|
||||
require(ecrecover(msgHash, v, r, s) == msg.sender);
|
||||
|
||||
if (signedMessages[msgHash].message.length == 0) {
|
||||
signedMessages[msgHash].message = message;
|
||||
}
|
||||
signedMessages[msgHash].signatures[msg.sender] = rsv;
|
||||
}
|
||||
|
||||
function getSignatures(bytes32 msgHash, address[] memory validators) public view returns (bytes memory) {
|
||||
bytes memory result;
|
||||
for (uint i = 0; i < validators.length; i++) {
|
||||
result = abi.encodePacked(result, signedMessages[msgHash].signatures[validators[i]]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
contract SignupStorage {
|
||||
mapping(bytes32 => uint) public signupsCount;
|
||||
mapping(bytes32 => mapping(address => uint)) public signups;
|
||||
|
||||
function signup(bytes32 hash) public {
|
||||
require(signups[hash][msg.sender] == 0, "Already signuped");
|
||||
|
||||
signups[hash][msg.sender] = ++signupsCount[hash];
|
||||
}
|
||||
|
||||
function getSignupNumber(bytes32 hash, address[] memory validators, address validator) view public returns (uint) {
|
||||
if (signups[hash][validator] == 0)
|
||||
return 0;
|
||||
uint id = 1;
|
||||
for (uint i = 0; i < validators.length; i++) {
|
||||
uint vid = signups[hash][validators[i]];
|
||||
if (vid > 0 && vid < signups[hash][validator])
|
||||
id++;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function getSignupAddress(bytes32 hash, address[] memory validators, uint signupNumber) view public returns (address) {
|
||||
for (uint i = 0; i < validators.length; i++) {
|
||||
if (getSignupNumber(hash, validators, validators[i]) == signupNumber) {
|
||||
return validators[i];
|
||||
}
|
||||
}
|
||||
return address(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue