Adapt tests to latest changes in MiningAdjudicator

pull/947/head
David Núñez 2019-05-03 09:55:24 +02:00
parent 4baa92c8fc
commit b51cb74a4d
5 changed files with 232 additions and 290 deletions

View File

@ -177,7 +177,8 @@ class SlashingEconomics:
reward_coefficient = 2 reward_coefficient = 2
@property @property
def deployment_parameters(self): def deployment_parameters(self) -> Tuple[int, ...]:
"""Cast coefficient attributes to uint256 compatible type for solidity+EVM"""
deployment_parameters = [ deployment_parameters = [
self.algorithm_sha256, self.algorithm_sha256,
@ -187,4 +188,4 @@ class SlashingEconomics:
self.reward_coefficient self.reward_coefficient
] ]
return deployment_parameters return tuple(map(int, deployment_parameters))

View File

@ -18,21 +18,21 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import os import os
import coincurve
import pytest import pytest
from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives import hashes
from eth_tester.exceptions import TransactionFailed from eth_tester.exceptions import TransactionFailed
from eth_utils import to_canonical_address from eth_utils import to_canonical_address
from web3.contract import Contract from web3.contract import Contract
from nucypher.blockchain.eth.token import NU
from nucypher.policy.models import IndisputableEvidence
from umbral import pre from umbral import pre
from umbral.curvebn import CurveBN from umbral.curvebn import CurveBN
from umbral.keys import UmbralPrivateKey from umbral.keys import UmbralPrivateKey
from umbral.signing import Signer, Signature from umbral.signing import Signer
from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives import hashes from nucypher.blockchain.eth.token import NU
from nucypher.crypto.utils import get_signature_recovery_value
from nucypher.policy.models import IndisputableEvidence
VALUE_FIELD = 0 VALUE_FIELD = 0
@ -46,12 +46,6 @@ policy_manager_secret = os.urandom(SECRET_LENGTH)
user_escrow_secret = os.urandom(SECRET_LENGTH) user_escrow_secret = os.urandom(SECRET_LENGTH)
adjudicator_secret = os.urandom(SECRET_LENGTH) adjudicator_secret = os.urandom(SECRET_LENGTH)
ALGORITHM_SHA256 = 1
BASE_PENALTY = 300
PENALTY_HISTORY_COEFFICIENT = 10
PERCENTAGE_PENALTY_COEFFICIENT = 2
REWARD_COEFFICIENT = 2
@pytest.fixture() @pytest.fixture()
def token(testerchain): def token(testerchain):
@ -109,7 +103,7 @@ def policy_manager(testerchain, escrow):
@pytest.fixture() @pytest.fixture()
def adjudicator(testerchain, escrow): def adjudicator(testerchain, escrow, slashing_economics):
escrow, _ = escrow escrow, _ = escrow
creator = testerchain.interface.w3.eth.accounts[0] creator = testerchain.interface.w3.eth.accounts[0]
@ -119,11 +113,8 @@ def adjudicator(testerchain, escrow):
contract, _ = testerchain.interface.deploy_contract( contract, _ = testerchain.interface.deploy_contract(
'MiningAdjudicator', 'MiningAdjudicator',
escrow.address, escrow.address,
ALGORITHM_SHA256, *slashing_economics.deployment_parameters)
BASE_PENALTY,
PENALTY_HISTORY_COEFFICIENT,
PERCENTAGE_PENALTY_COEFFICIENT,
REWARD_COEFFICIENT)
dispatcher, _ = testerchain.interface.deploy_contract('Dispatcher', contract.address, secret_hash) dispatcher, _ = testerchain.interface.deploy_contract('Dispatcher', contract.address, secret_hash)
# Wrap dispatcher contract # Wrap dispatcher contract
@ -140,26 +131,8 @@ def adjudicator(testerchain, escrow):
# TODO: Obtain real re-encryption metadata. Maybe constructing a WorkOrder and obtaining a response. # TODO: Obtain real re-encryption metadata. Maybe constructing a WorkOrder and obtaining a response.
# TODO organize support functions # TODO organize support functions
# TODO: Repeated method in estimate_gas
def generate_args_for_slashing(testerchain, miner): def generate_args_for_slashing(testerchain, miner):
def sign_data(data, umbral_privkey):
umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
# Prepare hash of the data
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(data)
data_hash = hash_ctx.finalize()
# Sign data and calculate recoverable signature
cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
signature_der_bytes = cryptography_priv_key.sign(data, ec.ECDSA(hashes.SHA256()))
signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)
recoverable_signature = bytes(signature) + bytes([0])
pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, data_hash, hasher=None) \
.format(compressed=False)
if pubkey_bytes != umbral_pubkey_bytes:
recoverable_signature = bytes(signature) + bytes([1])
return recoverable_signature
delegating_privkey = UmbralPrivateKey.gen_key() delegating_privkey = UmbralPrivateKey.gen_key()
_symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
signing_privkey = UmbralPrivateKey.gen_key() signing_privkey = UmbralPrivateKey.gen_key()
@ -174,19 +147,34 @@ def generate_args_for_slashing(testerchain, miner):
sign_delegating_key=False, sign_delegating_key=False,
sign_receiving_key=False) sign_receiving_key=False)
capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey()) capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey())
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=os.urandom(34))
capsule_bytes = capsule.to_bytes()
# Corrupt proof
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_bytes = cfrag.to_bytes()
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
requester_umbral_private_key = UmbralPrivateKey.gen_key()
requester_umbral_public_key_bytes = requester_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
miner_umbral_private_key = UmbralPrivateKey.gen_key() miner_umbral_private_key = UmbralPrivateKey.gen_key()
miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False) ursula_pubkey = miner_umbral_private_key.get_pubkey()
ursula_pubkey_bytes = ursula_pubkey.to_bytes(is_compressed=False)[1:]
specification = bytes(capsule) + ursula_pubkey_bytes + bytes(20) + bytes(32)
ursulas_signer = Signer(miner_umbral_private_key)
bobs_signer = Signer(priv_key_bob)
task_signature = bytes(bobs_signer(specification))
metadata = bytes(ursulas_signer(task_signature))
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_signature = bytes(ursulas_signer(bytes(cfrag)))
bob_pubkey_bytes = pub_key_bob.to_bytes(is_compressed=False)[1:]
cfrag_signature_v = get_signature_recovery_value(message=bytes(cfrag),
signature=cfrag_signature,
public_key=ursula_pubkey)
task_signature_v = get_signature_recovery_value(message=task_signature,
signature=metadata,
public_key=ursula_pubkey)
recovery_values = cfrag_signature_v + task_signature_v
miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)[1:]
# Sign Umbral public key using eth-key # Sign Umbral public key using eth-key
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(miner_umbral_public_key_bytes) hash_ctx.update(miner_umbral_public_key_bytes)
@ -195,16 +183,19 @@ def generate_args_for_slashing(testerchain, miner):
sig_key = testerchain.interface.provider.ethereum_tester.backend._key_lookup[address] sig_key = testerchain.interface.provider.ethereum_tester.backend._key_lookup[address]
signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash)) signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash))
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
return data_hash, (capsule_bytes,
capsule_signature_by_requester, hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
capsule_signature_by_requester_and_miner, hash_ctx.update(bytes(capsule) + bytes(cfrag))
cfrag_bytes, data_hash = hash_ctx.finalize()
cfrag_signature_by_miner,
requester_umbral_public_key_bytes, return data_hash, (bytes(capsule),
bytes(cfrag),
cfrag_signature,
task_signature,
recovery_values,
bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data) evidence_data)
@ -272,7 +263,7 @@ def execute_multisig_transaction(testerchain, multisig, accounts, tx):
@pytest.mark.slow @pytest.mark.slow
def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escrow_proxy, multisig): def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escrow_proxy, multisig, slashing_economics):
# Travel to the start of the next period to prevent problems with unexpected overflow first period # Travel to the start of the next period to prevent problems with unexpected overflow first period
testerchain.time_travel(hours=1) testerchain.time_travel(hours=1)
@ -780,19 +771,22 @@ def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escro
total_lock = escrow.functions.lockedPerPeriod(period).call() total_lock = escrow.functions.lockedPerPeriod(period).call()
alice1_balance = token.functions.balanceOf(alice1).call() alice1_balance = token.functions.balanceOf(alice1).call()
algorithm_sha256, base_penalty, *coefficients = slashing_economics.deployment_parameters
penalty_history_coefficient, percentage_penalty_coefficient, reward_coefficient = coefficients
data_hash, slashing_args = generate_args_for_slashing(testerchain, ursula1) data_hash, slashing_args = generate_args_for_slashing(testerchain, ursula1)
assert not adjudicator.functions.evaluatedCFrags(data_hash).call() assert not adjudicator.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice1})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
assert adjudicator.functions.evaluatedCFrags(data_hash).call() assert adjudicator.functions.evaluatedCFrags(data_hash).call()
assert tokens_amount - BASE_PENALTY == escrow.functions.minerInfo(ursula1).call()[VALUE_FIELD] assert tokens_amount - base_penalty == escrow.functions.minerInfo(ursula1).call()[VALUE_FIELD]
assert previous_lock == escrow.functions.getLockedTokensInPast(ursula1, 1).call() assert previous_lock == escrow.functions.getLockedTokensInPast(ursula1, 1).call()
assert lock == escrow.functions.getLockedTokens(ursula1).call() assert lock == escrow.functions.getLockedTokens(ursula1).call()
assert next_lock == escrow.functions.getLockedTokens(ursula1, 1).call() assert next_lock == escrow.functions.getLockedTokens(ursula1, 1).call()
assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call() assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call()
assert total_lock == escrow.functions.lockedPerPeriod(period).call() assert total_lock == escrow.functions.lockedPerPeriod(period).call()
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call() assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
assert alice1_balance + BASE_PENALTY / REWARD_COEFFICIENT == token.functions.balanceOf(alice1).call() assert alice1_balance + base_penalty / reward_coefficient == token.functions.balanceOf(alice1).call()
# Slash part of the one sub stake # Slash part of the one sub stake
tokens_amount = escrow.functions.minerInfo(ursula2).call()[VALUE_FIELD] tokens_amount = escrow.functions.minerInfo(ursula2).call()[VALUE_FIELD]
@ -807,14 +801,14 @@ def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escro
tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice1}) tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice1})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
assert adjudicator.functions.evaluatedCFrags(data_hash).call() assert adjudicator.functions.evaluatedCFrags(data_hash).call()
assert lock - BASE_PENALTY == escrow.functions.minerInfo(ursula2).call()[VALUE_FIELD] assert lock - base_penalty == escrow.functions.minerInfo(ursula2).call()[VALUE_FIELD]
assert previous_lock == escrow.functions.getLockedTokensInPast(ursula2, 1).call() assert previous_lock == escrow.functions.getLockedTokensInPast(ursula2, 1).call()
assert lock - BASE_PENALTY == escrow.functions.getLockedTokens(ursula2).call() assert lock - base_penalty == escrow.functions.getLockedTokens(ursula2).call()
assert next_lock - BASE_PENALTY == escrow.functions.getLockedTokens(ursula2, 1).call() assert next_lock - base_penalty == escrow.functions.getLockedTokens(ursula2, 1).call()
assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call() assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call()
assert total_lock - BASE_PENALTY == escrow.functions.lockedPerPeriod(period).call() assert total_lock - base_penalty == escrow.functions.lockedPerPeriod(period).call()
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call() assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
assert alice1_balance + BASE_PENALTY == token.functions.balanceOf(alice1).call() assert alice1_balance + base_penalty == token.functions.balanceOf(alice1).call()
# Upgrade the adjudicator # Upgrade the adjudicator
# Deploy the same contract as the second version # Deploy the same contract as the second version
@ -822,11 +816,7 @@ def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escro
adjudicator_v2, _ = testerchain.interface.deploy_contract( adjudicator_v2, _ = testerchain.interface.deploy_contract(
'MiningAdjudicator', 'MiningAdjudicator',
escrow.address, escrow.address,
ALGORITHM_SHA256, *slashing_economics.deployment_parameters)
BASE_PENALTY,
PENALTY_HISTORY_COEFFICIENT,
PERCENTAGE_PENALTY_COEFFICIENT,
REWARD_COEFFICIENT)
adjudicator_secret2 = os.urandom(SECRET_LENGTH) adjudicator_secret2 = os.urandom(SECRET_LENGTH)
adjudicator_secret2_hash = testerchain.interface.w3.keccak(adjudicator_secret2) adjudicator_secret2_hash = testerchain.interface.w3.keccak(adjudicator_secret2)
# Ursula and Alice can't upgrade library, only owner can # Ursula and Alice can't upgrade library, only owner can
@ -900,7 +890,7 @@ def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escro
tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice2}) tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice2})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
assert adjudicator.functions.evaluatedCFrags(data_hash).call() assert adjudicator.functions.evaluatedCFrags(data_hash).call()
penalty = (2 * BASE_PENALTY + 3 * PENALTY_HISTORY_COEFFICIENT) penalty = (2 * base_penalty + 3 * penalty_history_coefficient)
assert lock - penalty == escrow.functions.minerInfo(ursula1).call()[VALUE_FIELD] assert lock - penalty == escrow.functions.minerInfo(ursula1).call()[VALUE_FIELD]
assert previous_lock == escrow.functions.getLockedTokensInPast(ursula1, 1).call() assert previous_lock == escrow.functions.getLockedTokensInPast(ursula1, 1).call()
assert lock - penalty == escrow.functions.getLockedTokens(ursula1).call() assert lock - penalty == escrow.functions.getLockedTokens(ursula1).call()
@ -908,7 +898,7 @@ def test_all(testerchain, token, escrow, policy_manager, adjudicator, user_escro
assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call() assert total_previous_lock == escrow.functions.lockedPerPeriod(period - 1).call()
assert total_lock - penalty == escrow.functions.lockedPerPeriod(period).call() assert total_lock - penalty == escrow.functions.lockedPerPeriod(period).call()
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call() assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
assert alice2_balance + penalty / REWARD_COEFFICIENT == token.functions.balanceOf(alice2).call() assert alice2_balance + penalty / reward_coefficient == token.functions.balanceOf(alice2).call()
# Unlock and withdraw all tokens in MinersEscrow # Unlock and withdraw all tokens in MinersEscrow
for index in range(9): for index in range(9):

View File

@ -34,11 +34,7 @@ def adjudicator_contract(testerchain, escrow, request, slashing_economics):
contract, _ = testerchain.interface.deploy_contract( contract, _ = testerchain.interface.deploy_contract(
'MiningAdjudicator', 'MiningAdjudicator',
escrow.address, escrow.address,
slashing_economics.algorithm_sha256, *slashing_economics.deployment_parameters)
slashing_economics.base_penalty,
slashing_economics.penalty_history_coefficient,
slashing_economics.percentage_penalty_coefficient,
slashing_economics.reward_coefficient)
if request.param: if request.param:
secret = os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH) secret = os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH)

View File

@ -18,24 +18,21 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import os import os
import coincurve
import pytest import pytest
from cryptography.hazmat.backends.openssl import backend from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from eth_tester.exceptions import TransactionFailed from eth_tester.exceptions import TransactionFailed
from eth_utils import to_canonical_address, to_checksum_address from eth_utils import to_canonical_address
from typing import Tuple from typing import Tuple
from web3.contract import Contract from web3.contract import Contract
from umbral import pre from umbral import pre
from umbral.config import default_params
from umbral.curvebn import CurveBN from umbral.curvebn import CurveBN
from umbral.keys import UmbralPrivateKey from umbral.keys import UmbralPrivateKey
from umbral.point import Point from umbral.point import Point
from umbral.random_oracles import hash_to_curvebn, ExtendedKeccak from umbral.signing import Signer
from umbral.signing import Signature, Signer
from nucypher.crypto.utils import get_signature_recovery_value
from nucypher.policy.models import IndisputableEvidence from nucypher.policy.models import IndisputableEvidence
@ -45,33 +42,8 @@ secret = (123456).to_bytes(32, byteorder='big')
secret2 = (654321).to_bytes(32, byteorder='big') secret2 = (654321).to_bytes(32, byteorder='big')
def sign_data(data, umbral_privkey):
umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
# Prepare hash of the data
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(data)
data_hash = hash_ctx.finalize()
# Sign data and calculate recoverable signature
cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
signature_der_bytes = cryptography_priv_key.sign(data, ec.ECDSA(hashes.SHA256()))
signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)
recoverable_signature = make_recoverable_signature(data_hash, signature, umbral_pubkey_bytes)
return recoverable_signature
def make_recoverable_signature(data_hash, signature, umbral_pubkey_bytes):
recoverable_signature = bytes(signature) + bytes([0])
pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, data_hash, hasher=None) \
.format(compressed=False)
if pubkey_bytes != umbral_pubkey_bytes:
recoverable_signature = bytes(signature) + bytes([1])
return recoverable_signature
# TODO: Obtain real re-encryption metadata. Maybe constructing a WorkOrder and obtaining a response. # TODO: Obtain real re-encryption metadata. Maybe constructing a WorkOrder and obtaining a response.
def fragments(metadata): def mock_ursula_reencrypts(ursula_privkey, corrupt_cfrag: bool = False):
delegating_privkey = UmbralPrivateKey.gen_key() delegating_privkey = UmbralPrivateKey.gen_key()
_symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
signing_privkey = UmbralPrivateKey.gen_key() signing_privkey = UmbralPrivateKey.gen_key()
@ -86,8 +58,42 @@ def fragments(metadata):
sign_delegating_key=False, sign_delegating_key=False,
sign_receiving_key=False) sign_receiving_key=False)
capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey()) capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey())
ursula_pubkey = ursula_privkey.get_pubkey()
ursula_pubkey_bytes = ursula_pubkey.to_bytes(is_compressed=False)[1:]
specification = bytes(capsule) + ursula_pubkey_bytes + bytes(20) + bytes(32)
ursulas_signer = Signer(ursula_privkey)
bobs_signer = Signer(priv_key_bob)
task_signature = bytes(bobs_signer(specification))
metadata = bytes(ursulas_signer(task_signature))
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata) cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
return capsule, cfrag
if corrupt_cfrag:
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_signature = bytes(ursulas_signer(bytes(cfrag)))
bob_pubkey_bytes = pub_key_bob.to_bytes(is_compressed=False)[1:]
cfrag_signature_v = get_signature_recovery_value(message=bytes(cfrag),
signature=cfrag_signature,
public_key=ursula_pubkey)
task_signature_v = get_signature_recovery_value(message=task_signature,
signature=metadata,
public_key=ursula_pubkey)
recovery_values = cfrag_signature_v + task_signature_v
return capsule, cfrag, cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes
def evaluation_hash(capsule, cfrag):
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(bytes(capsule) + bytes(cfrag))
data_hash = hash_ctx.finalize()
return data_hash
@pytest.mark.slow @pytest.mark.slow
@ -113,7 +119,7 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
# Generate miner's Umbral key # Generate miner's Umbral key
miner_umbral_private_key = UmbralPrivateKey.gen_key() miner_umbral_private_key = UmbralPrivateKey.gen_key()
miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False) miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)[1:]
# Sign Umbral public key using eth-key # Sign Umbral public key using eth-key
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
@ -124,43 +130,28 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
sig_key = provider.ethereum_tester.backend._key_lookup[address] sig_key = provider.ethereum_tester.backend._key_lookup[address]
signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash)) signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash))
# Prepare hash of the data # Prepare evaluation data
metadata = os.urandom(33) capsule, cfrag, *other_stuff = mock_ursula_reencrypts(miner_umbral_private_key)
capsule, cfrag = fragments(metadata) cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes = other_stuff
assert cfrag.verify_correctness(capsule) assert cfrag.verify_correctness(capsule)
capsule_bytes = capsule.to_bytes() # Investigator prepares supporting Evidence
cfrag_bytes = cfrag.to_bytes()
# Bob prepares supporting Evidence
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
assert len(evidence_data) == 20 * 32 + 32 + 20 + 1 assert len(evidence_data) == 20 * 32 + 32 + 20 + 1
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) data_hash = evaluation_hash(capsule, cfrag)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
# This capsule and cFrag are not yet evaluated # This capsule and cFrag are not yet evaluated
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call() assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
# Generate requester's Umbral key
requester_umbral_private_key = UmbralPrivateKey.gen_key()
requester_umbral_public_key_bytes = requester_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)
# Sign capsule and cFrag
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
# Challenge using good data # Challenge using good data
args = (capsule_bytes, args = (bytes(capsule),
capsule_signature_by_requester, bytes(cfrag),
capsule_signature_by_requester_and_miner, cfrag_signature,
cfrag_bytes, task_signature,
cfrag_signature_by_miner, recovery_values,
requester_umbral_public_key_bytes, bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data) evidence_data)
@ -183,39 +174,36 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
assert investigator == event_args['investigator'] assert investigator == event_args['investigator']
assert event_args['correctness'] assert event_args['correctness']
###############################
# Test: Don't evaluate miner with data that already was checked # Test: Don't evaluate miner with data that already was checked
###############################
# TODO: be more specific on the expected exception
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
###############################
# Test: Ursula produces incorrect proof: # Test: Ursula produces incorrect proof:
metadata = os.urandom(34) ###############################
capsule, cfrag = fragments(metadata) capsule, cfrag, *other_stuff = mock_ursula_reencrypts(miner_umbral_private_key, corrupt_cfrag=True)
capsule_bytes = capsule.to_bytes() cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes = other_stuff
# Corrupt proof
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_bytes = cfrag.to_bytes()
assert not cfrag.verify_correctness(capsule) assert not cfrag.verify_correctness(capsule)
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
args = (capsule_bytes, args = (bytes(capsule),
capsule_signature_by_requester, bytes(cfrag),
capsule_signature_by_requester_and_miner, cfrag_signature,
cfrag_bytes, task_signature,
cfrag_signature_by_miner, recovery_values,
requester_umbral_public_key_bytes, bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data) evidence_data)
data_hash = evaluation_hash(capsule, cfrag)
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call() assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator}) tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
number_of_evaluations += 1 number_of_evaluations += 1
@ -243,18 +231,10 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
# Test: Bob produces wrong precomputed data # Test: Bob produces wrong precomputed data
############################### ###############################
metadata = os.urandom(34) capsule, cfrag, *other_stuff = mock_ursula_reencrypts(miner_umbral_private_key)
capsule, cfrag = fragments(metadata) cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes = other_stuff
capsule_bytes = capsule.to_bytes()
cfrag_bytes = cfrag.to_bytes()
assert cfrag.verify_correctness(capsule) assert cfrag.verify_correctness(capsule)
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
@ -265,16 +245,17 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
evidence_data[32:32+64] = random_point_bytes evidence_data[32:32+64] = random_point_bytes
evidence_data = bytes(evidence_data) evidence_data = bytes(evidence_data)
args = (capsule_bytes, args = (bytes(capsule),
capsule_signature_by_requester, bytes(cfrag),
capsule_signature_by_requester_and_miner, cfrag_signature,
cfrag_bytes, task_signature,
cfrag_signature_by_miner, recovery_values,
requester_umbral_public_key_bytes, bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data) evidence_data)
data_hash = evaluation_hash(capsule, cfrag)
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call() assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
# Evaluation must fail since Bob precomputed wrong values # Evaluation must fail since Bob precomputed wrong values
@ -292,34 +273,27 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
# Test: Second violation. Penalty is increased # Test: Second violation. Penalty is increased
############################### ###############################
# Prepare hash of the data capsule, cfrag, *other_stuff = mock_ursula_reencrypts(miner_umbral_private_key, corrupt_cfrag=True)
metadata = os.urandom(34) cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes = other_stuff
capsule, cfrag = fragments(metadata)
capsule_bytes = capsule.to_bytes()
# Corrupt proof
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_bytes = cfrag.to_bytes()
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
args = [capsule_bytes, args = (bytes(capsule),
capsule_signature_by_requester, bytes(cfrag),
capsule_signature_by_requester_and_miner, cfrag_signature,
cfrag_bytes, task_signature,
cfrag_signature_by_miner, recovery_values,
requester_umbral_public_key_bytes, bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data] evidence_data)
data_hash = evaluation_hash(capsule, cfrag)
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call() assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
worker_stake = escrow.functions.minerInfo(miner).call()[0] worker_stake = escrow.functions.minerInfo(miner).call()[0]
investigator_balance = escrow.functions.rewardInfo(investigator).call() investigator_balance = escrow.functions.rewardInfo(investigator).call()
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call() assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator}) tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
@ -350,33 +324,27 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
# Test: Third violation. Penalty reaches the maximum allowed # Test: Third violation. Penalty reaches the maximum allowed
############################### ###############################
# Prepare corrupted data again capsule, cfrag, *other_stuff = mock_ursula_reencrypts(miner_umbral_private_key, corrupt_cfrag=True)
capsule, cfrag = fragments(metadata) cfrag_signature, task_signature, recovery_values, bob_pubkey_bytes = other_stuff
capsule_bytes = capsule.to_bytes()
# Corrupt proof
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_bytes = cfrag.to_bytes()
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(capsule_bytes + cfrag_bytes)
data_hash = hash_ctx.finalize()
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key)
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
args = [capsule_bytes, args = (bytes(capsule),
capsule_signature_by_requester, bytes(cfrag),
capsule_signature_by_requester_and_miner, cfrag_signature,
cfrag_bytes, task_signature,
cfrag_signature_by_miner, recovery_values,
requester_umbral_public_key_bytes, bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data] evidence_data)
data_hash = evaluation_hash(capsule, cfrag)
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
worker_stake = escrow.functions.minerInfo(miner).call()[0] worker_stake = escrow.functions.minerInfo(miner).call()[0]
investigator_balance = escrow.functions.rewardInfo(investigator).call() investigator_balance = escrow.functions.rewardInfo(investigator).call()
assert not adjudicator_contract.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator}) tx = adjudicator_contract.functions.evaluateCFrag(*args).transact({'from': investigator})
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
number_of_evaluations += 1 number_of_evaluations += 1
@ -406,47 +374,40 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
############## ##############
# Can't evaluate miner using broken signatures # Can't evaluate miner using broken signatures
wrong_args = args[:] wrong_args = list(args)
wrong_args[1] = capsule_signature_by_requester[1:] wrong_args[2] = cfrag_signature[1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
wrong_args = args[:]
wrong_args[2] = capsule_signature_by_requester_and_miner[1:] wrong_args = list(args)
wrong_args[3] = task_signature[1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
wrong_args = args[:]
wrong_args[4] = cfrag_signature_by_miner[1:] wrong_args = list(args)
with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx)
wrong_args = args[:]
wrong_args[7] = signed_miner_umbral_public_key[1:] wrong_args[7] = signed_miner_umbral_public_key[1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
# Can't evaluate miner using wrong keys # Can't evaluate miner using wrong keys
wrong_args = args[:] wrong_args = list(args)
wrong_args[5] = UmbralPrivateKey.gen_key().get_pubkey().to_bytes(is_compressed=False) wrong_args[5] = UmbralPrivateKey.gen_key().get_pubkey().to_bytes(is_compressed=False)[1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
wrong_args = args[:]
wrong_args[6] = UmbralPrivateKey.gen_key().get_pubkey().to_bytes(is_compressed=False) wrong_args = list(args)
wrong_args[6] = UmbralPrivateKey.gen_key().get_pubkey().to_bytes(is_compressed=False)[1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
# Can't use signature for another data # Can't use signature for another data
wrong_args = args[:] wrong_args = list(args)
wrong_args[0] = bytes(args[0][0] + 1) + args[0][1:] wrong_args[1] = os.urandom(len(bytes(cfrag)))
with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx)
wrong_args = args[:]
wrong_args[3] = bytes(args[3][0] + 1) + args[3][1:]
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()
testerchain.wait_for_receipt(tx) testerchain.wait_for_receipt(tx)
@ -455,7 +416,8 @@ def test_evaluate_cfrag(testerchain, escrow, adjudicator_contract, slashing_econ
address = to_canonical_address(wrong_miner) address = to_canonical_address(wrong_miner)
sig_key = provider.ethereum_tester.backend._key_lookup[address] sig_key = provider.ethereum_tester.backend._key_lookup[address]
signed_wrong_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash)) signed_wrong_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash))
wrong_args = args[:]
wrong_args = list(args)
wrong_args[7] = signed_wrong_miner_umbral_public_key wrong_args[7] = signed_wrong_miner_umbral_public_key
with pytest.raises((TransactionFailed, ValueError)): with pytest.raises((TransactionFailed, ValueError)):
tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact() tx = adjudicator_contract.functions.evaluateCFrag(*wrong_args).transact()

View File

@ -18,34 +18,29 @@ You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>. along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
import coincurve import io
import json import json
import os import os
import re
from cryptography.hazmat.primitives.asymmetric import ec
from eth_utils import to_canonical_address
from nucypher.blockchain.economics import TokenEconomics
from nucypher.policy.models import IndisputableEvidence, Policy
from umbral import pre
from umbral.curvebn import CurveBN
from umbral.keys import UmbralPrivateKey
from umbral.signing import Signer, Signature
import time import time
from os.path import abspath, dirname from os.path import abspath, dirname
import io from eth_utils import to_canonical_address
import re
from cryptography.hazmat.backends.openssl import backend from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from twisted.logger import globalLogPublisher, Logger, jsonFileLogObserver, ILogObserver from twisted.logger import globalLogPublisher, Logger, jsonFileLogObserver, ILogObserver
from zope.interface import provider from zope.interface import provider
from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent, PolicyAgent, MiningAdjudicatorAgent from umbral import pre
from nucypher.utilities.sandbox.blockchain import TesterBlockchain from umbral.curvebn import CurveBN
from umbral.keys import UmbralPrivateKey
from umbral.signing import Signer
from nucypher.blockchain.economics import TokenEconomics
from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent, PolicyAgent, MiningAdjudicatorAgent
from nucypher.crypto.utils import get_signature_recovery_value
from nucypher.policy.models import IndisputableEvidence, Policy
from nucypher.utilities.sandbox.blockchain import TesterBlockchain
ALGORITHM_SHA256 = 1 ALGORITHM_SHA256 = 1
TOKEN_ECONOMICS = TokenEconomics() TOKEN_ECONOMICS = TokenEconomics()
@ -121,26 +116,8 @@ class AnalyzeGas:
# TODO organize support functions # TODO organize support functions
# TODO: Repeated method in test_intercontract_integration
def generate_args_for_slashing(testerchain, miner, corrupt: bool = True): def generate_args_for_slashing(testerchain, miner, corrupt: bool = True):
def sign_data(data, umbral_privkey):
umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
# Prepare hash of the data
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(data)
data_hash = hash_ctx.finalize()
# Sign data and calculate recoverable signature
cryptography_priv_key = umbral_privkey.to_cryptography_privkey()
signature_der_bytes = cryptography_priv_key.sign(data, ec.ECDSA(hashes.SHA256()))
signature = Signature.from_bytes(signature_der_bytes, der_encoded=True)
recoverable_signature = bytes(signature) + bytes([0])
pubkey_bytes = coincurve.PublicKey.from_signature_and_message(recoverable_signature, data_hash, hasher=None) \
.format(compressed=False)
if pubkey_bytes != umbral_pubkey_bytes:
recoverable_signature = bytes(signature) + bytes([1])
return recoverable_signature
delegating_privkey = UmbralPrivateKey.gen_key() delegating_privkey = UmbralPrivateKey.gen_key()
_symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey()) _symmetric_key, capsule = pre._encapsulate(delegating_privkey.get_pubkey())
signing_privkey = UmbralPrivateKey.gen_key() signing_privkey = UmbralPrivateKey.gen_key()
@ -155,18 +132,35 @@ def generate_args_for_slashing(testerchain, miner, corrupt: bool = True):
sign_delegating_key=False, sign_delegating_key=False,
sign_receiving_key=False) sign_receiving_key=False)
capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey()) capsule.set_correctness_keys(delegating_privkey.get_pubkey(), pub_key_bob, signing_privkey.get_pubkey())
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=os.urandom(34))
capsule_bytes = capsule.to_bytes() miner_umbral_private_key = UmbralPrivateKey.gen_key()
ursula_pubkey = miner_umbral_private_key.get_pubkey()
ursula_pubkey_bytes = ursula_pubkey.to_bytes(is_compressed=False)[1:]
specification = bytes(capsule) + ursula_pubkey_bytes + bytes(20) + bytes(32)
ursulas_signer = Signer(miner_umbral_private_key)
bobs_signer = Signer(priv_key_bob)
task_signature = bytes(bobs_signer(specification))
metadata = bytes(ursulas_signer(task_signature))
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
if corrupt: if corrupt:
cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve) cfrag.proof.bn_sig = CurveBN.gen_rand(capsule.params.curve)
cfrag_bytes = cfrag.to_bytes()
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) cfrag_signature = bytes(ursulas_signer(bytes(cfrag)))
hash_ctx.update(capsule_bytes + cfrag_bytes)
requester_umbral_private_key = UmbralPrivateKey.gen_key() bob_pubkey_bytes = pub_key_bob.to_bytes(is_compressed=False)[1:]
requester_umbral_public_key_bytes = requester_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)
capsule_signature_by_requester = sign_data(capsule_bytes, requester_umbral_private_key) cfrag_signature_v = get_signature_recovery_value(message=bytes(cfrag),
miner_umbral_private_key = UmbralPrivateKey.gen_key() signature=cfrag_signature,
miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False) public_key=ursula_pubkey)
task_signature_v = get_signature_recovery_value(message=task_signature,
signature=metadata,
public_key=ursula_pubkey)
recovery_values = cfrag_signature_v + task_signature_v
miner_umbral_public_key_bytes = miner_umbral_private_key.get_pubkey().to_bytes(is_compressed=False)[1:]
# Sign Umbral public key using eth-key # Sign Umbral public key using eth-key
hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend) hash_ctx = hashes.Hash(hashes.SHA256(), backend=backend)
hash_ctx.update(miner_umbral_public_key_bytes) hash_ctx.update(miner_umbral_public_key_bytes)
@ -175,16 +169,15 @@ def generate_args_for_slashing(testerchain, miner, corrupt: bool = True):
sig_key = testerchain.interface.provider.ethereum_tester.backend._key_lookup[address] sig_key = testerchain.interface.provider.ethereum_tester.backend._key_lookup[address]
signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash)) signed_miner_umbral_public_key = bytes(sig_key.sign_msg_hash(miner_umbral_public_key_hash))
capsule_signature_by_requester_and_miner = sign_data(capsule_signature_by_requester, miner_umbral_private_key)
cfrag_signature_by_miner = sign_data(cfrag_bytes, miner_umbral_private_key)
evidence = IndisputableEvidence(capsule, cfrag, ursula=None) evidence = IndisputableEvidence(capsule, cfrag, ursula=None)
evidence_data = evidence.precompute_values() evidence_data = evidence.precompute_values()
return (capsule_bytes,
capsule_signature_by_requester, return (bytes(capsule),
capsule_signature_by_requester_and_miner, bytes(cfrag),
cfrag_bytes, cfrag_signature,
cfrag_signature_by_miner, task_signature,
requester_umbral_public_key_bytes, recovery_values,
bob_pubkey_bytes,
miner_umbral_public_key_bytes, miner_umbral_public_key_bytes,
signed_miner_umbral_public_key, signed_miner_umbral_public_key,
evidence_data) evidence_data)