mirror of https://github.com/nucypher/nucypher.git
Added draft of the first challenge
parent
014a1094ab
commit
0e06d67252
|
@ -0,0 +1,103 @@
|
||||||
|
pragma solidity ^0.4.25;
|
||||||
|
|
||||||
|
|
||||||
|
import "./lib/SignatureVerifier.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Challenges for NuCypher net characters
|
||||||
|
* @dev TODO move or integrate with MinersEscrow
|
||||||
|
**/
|
||||||
|
contract ChallengeLibrary {
|
||||||
|
|
||||||
|
uint256 constant PENALTY = 100; // TODO
|
||||||
|
|
||||||
|
MinersEscrowStub public escrow;
|
||||||
|
SignatureVerifier.HashAlgorithm public hashAlgorithm;
|
||||||
|
mapping (bytes32 => bool) public challengedCFrags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param _escrow Escrow contract
|
||||||
|
* @param _hashAlgorithm Hashing algorithm
|
||||||
|
**/
|
||||||
|
constructor(
|
||||||
|
MinersEscrowStub _escrow,
|
||||||
|
SignatureVerifier.HashAlgorithm _hashAlgorithm
|
||||||
|
) public {
|
||||||
|
require(address(_escrow) != 0x0);
|
||||||
|
escrow = _escrow;
|
||||||
|
hashAlgorithm = _hashAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Submit proof that miner create wrong CFrag
|
||||||
|
* @param _capsuleBytes Serialized capsule
|
||||||
|
* @param _cFragBytes Serialized CFrag
|
||||||
|
* @param _signature Signature of Capsule and CFrag
|
||||||
|
* @param _minerPublicKey Miner's public key that was used to sign Capsule and CFrag
|
||||||
|
* @param _minerPublicKeySignature Signature of public key by miner's eth-key
|
||||||
|
**/
|
||||||
|
function challengeCFrag(
|
||||||
|
bytes _capsuleBytes,
|
||||||
|
bytes _cFragBytes,
|
||||||
|
bytes _signature,
|
||||||
|
bytes _minerPublicKey,
|
||||||
|
bytes _minerPublicKeySignature
|
||||||
|
) public {
|
||||||
|
require(_minerPublicKey.length == 65);
|
||||||
|
bytes memory signedData = abi.encodePacked(_capsuleBytes, _cFragBytes);
|
||||||
|
|
||||||
|
// copy public key except first byte
|
||||||
|
bytes memory preparedPublicKey = new bytes(64);
|
||||||
|
assembly {
|
||||||
|
let destination := add(mload(preparedPublicKey), 32)
|
||||||
|
let source := add(mload(_minerPublicKey), 33)
|
||||||
|
mstore(destination, mload(source))
|
||||||
|
mstore(add(destination, 32), mload(add(source, 32)))
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes32 dataHash = SignatureVerifier.hash(signedData, hashAlgorithm);
|
||||||
|
require(SignatureVerifier.toAddress(preparedPublicKey) ==
|
||||||
|
SignatureVerifier.recover(dataHash, _signature));
|
||||||
|
require(!challengedCFrags[dataHash]); // CFrag is not challenged yet
|
||||||
|
bytes32 publicKeyHash = SignatureVerifier.hash(_minerPublicKey, hashAlgorithm);
|
||||||
|
address miner = SignatureVerifier.recover(publicKeyHash, _minerPublicKeySignature);
|
||||||
|
|
||||||
|
require(escrow.getLockedTokens(miner) > 0); // TODO check that miner can be slashed
|
||||||
|
if (!check(_capsuleBytes, _cFragBytes)) {
|
||||||
|
escrow.slashMiner(miner, PENALTY);
|
||||||
|
}
|
||||||
|
challengedCFrags[dataHash] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO complete
|
||||||
|
function check(
|
||||||
|
bytes _capsuleBytes,
|
||||||
|
bytes _cFragBytes
|
||||||
|
) public returns (bool) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO move to tests
|
||||||
|
contract MinersEscrowStub {
|
||||||
|
|
||||||
|
mapping (address => uint256) public minerInfo;
|
||||||
|
|
||||||
|
function setMinerInfo(address _miner, uint256 _amount) public {
|
||||||
|
minerInfo[_miner] = _amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLockedTokens(address _miner)
|
||||||
|
public view returns (uint256)
|
||||||
|
{
|
||||||
|
return minerInfo[_miner];
|
||||||
|
}
|
||||||
|
|
||||||
|
function slashMiner(address _miner, uint256 _amount) public {
|
||||||
|
minerInfo[_miner] -= _amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -46,6 +46,25 @@ library SignatureVerifier {
|
||||||
return address(keccak256(_publicKey));
|
return address(keccak256(_publicKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Hash using one of pre built hashing algorithm
|
||||||
|
* @param _message Signed message
|
||||||
|
* @param _algorithm Hashing algorithm
|
||||||
|
**/
|
||||||
|
function hash(bytes _message, HashAlgorithm _algorithm)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes32 result)
|
||||||
|
{
|
||||||
|
if (_algorithm == HashAlgorithm.KECCAK256) {
|
||||||
|
result = keccak256(_message);
|
||||||
|
} else if (_algorithm == HashAlgorithm.SHA256) {
|
||||||
|
result = sha256(_message);
|
||||||
|
} else {
|
||||||
|
result = ripemd160(_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Verify ECDSA signature
|
* @notice Verify ECDSA signature
|
||||||
* @dev Uses one of pre built hashing algorithm
|
* @dev Uses one of pre built hashing algorithm
|
||||||
|
@ -59,15 +78,7 @@ library SignatureVerifier {
|
||||||
pure
|
pure
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
bytes32 hash;
|
return toAddress(_publicKey) == recover(hash(_message, _algorithm), _signature);
|
||||||
if (_algorithm == HashAlgorithm.KECCAK256) {
|
|
||||||
hash = keccak256(_message);
|
|
||||||
} else if (_algorithm == HashAlgorithm.SHA256) {
|
|
||||||
hash = sha256(_message);
|
|
||||||
} else {
|
|
||||||
hash = ripemd160(_message);
|
|
||||||
}
|
|
||||||
return toAddress(_publicKey) == recover(hash, _signature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -91,6 +91,19 @@ def test_address(testerchain, signature_verifier):
|
||||||
assert signer_address == to_normalized_address(result_address)
|
assert signer_address == to_normalized_address(result_address)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.slow
|
||||||
|
def test_hash(testerchain, signature_verifier):
|
||||||
|
message = os.urandom(100)
|
||||||
|
|
||||||
|
# Prepare message hash
|
||||||
|
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
|
||||||
|
hash_ctx.update(message)
|
||||||
|
message_hash = hash_ctx.finalize()
|
||||||
|
|
||||||
|
# Verify hash function
|
||||||
|
assert message_hash == signature_verifier.functions.hash(message, ALGORITHM_SHA256).call()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.slow
|
@pytest.mark.slow
|
||||||
def test_verify(testerchain, signature_verifier):
|
def test_verify(testerchain, signature_verifier):
|
||||||
message = os.urandom(100)
|
message = os.urandom(100)
|
||||||
|
|
|
@ -21,6 +21,14 @@ contract SignatureVerifierMock {
|
||||||
return SignatureVerifier.toAddress(_publicKey);
|
return SignatureVerifier.toAddress(_publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hash(bytes _message, SignatureVerifier.HashAlgorithm _algorithm)
|
||||||
|
public
|
||||||
|
pure
|
||||||
|
returns (bytes32 result)
|
||||||
|
{
|
||||||
|
return SignatureVerifier.hash(_message, _algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
function verify(bytes _message, bytes _signature, bytes _publicKey, SignatureVerifier.HashAlgorithm _algorithm)
|
function verify(bytes _message, bytes _signature, bytes _publicKey, SignatureVerifier.HashAlgorithm _algorithm)
|
||||||
public
|
public
|
||||||
pure
|
pure
|
||||||
|
|
Loading…
Reference in New Issue