Added validation code mechanism
This commit is contained in:
parent
470e7671fd
commit
87520a39b1
|
@ -92,6 +92,8 @@ total_destroyed: wei_value
|
|||
# Sighash calculator library address
|
||||
sighasher: address
|
||||
|
||||
# Purity checker library address
|
||||
purity_checker: address
|
||||
|
||||
# Reward for preparing or committing, as fraction of deposit size
|
||||
reward_factor: public(decimal)
|
||||
|
@ -136,6 +138,8 @@ def initiate():
|
|||
self.current_epoch = block.number / self.epoch_length
|
||||
# Set the sighash calculator address
|
||||
self.sighasher = 0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24
|
||||
# Set the purity checker address
|
||||
self.purity_checker = 0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91
|
||||
# Set an initial root of the epoch hash chain
|
||||
self.consensus_messages[0].ancestry_hash_justified[0x0000000000000000000000000000000000000000000000000000000000000000] = True
|
||||
# self.consensus_messages[0].committed = True
|
||||
|
@ -182,6 +186,7 @@ def initialize_epoch(epoch: num):
|
|||
# Send a deposit to join the validator set
|
||||
def deposit(validation_addr: address, withdrawal_addr: address):
|
||||
assert self.current_epoch == block.number / self.epoch_length
|
||||
assert extract32(raw_call(self.purity_checker, concat('\xa1\x90>\xab', as_bytes32(validation_addr)), gas=500000, outsize=32), 0) != as_bytes32(0)
|
||||
self.validators[self.nextValidatorIndex] = {
|
||||
deposit: msg.value,
|
||||
dynasty_start: self.dynasty + 2,
|
||||
|
@ -210,11 +215,7 @@ def flick_status(validator_index: num, logout_msg: bytes <= 1024):
|
|||
sig = values[2]
|
||||
assert self.current_epoch == epoch
|
||||
# Signature check
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
as_num256(extract32(sig, 0)),
|
||||
as_num256(extract32(sig, 32)),
|
||||
as_num256(extract32(sig, 64))) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash, sig), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Logging in
|
||||
if login_flag:
|
||||
# Check that we are logged out
|
||||
|
@ -323,11 +324,7 @@ def prepare(validator_index: num, prepare_msg: bytes <= 1024):
|
|||
sig = values[5]
|
||||
# For now, the sig is a simple ECDSA sig
|
||||
# Check the signature
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
extract32(sig, 0, type=num256),
|
||||
extract32(sig, 32, type=num256),
|
||||
extract32(sig, 64, type=num256)) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash, sig), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that we are in an epoch after we started validating
|
||||
assert self.current_epoch >= self.dynasty_start_epoch[self.validators[validator_index].dynasty_start]
|
||||
# Check that this prepare has not yet been made
|
||||
|
@ -386,11 +383,7 @@ def commit(validator_index: num, commit_msg: bytes <= 1024):
|
|||
prev_commit_epoch = values[2]
|
||||
sig = values[3]
|
||||
# Check the signature
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
extract32(sig, 0, type=num256),
|
||||
extract32(sig, 32, type=num256),
|
||||
extract32(sig, 64, type=num256)) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash, sig), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that we are in the right epoch
|
||||
assert self.current_epoch == block.number / self.epoch_length
|
||||
assert self.current_epoch == epoch
|
||||
|
@ -441,14 +434,8 @@ def double_prepare_slash(validator_index: num, prepare1: bytes <= 1000, prepare2
|
|||
epoch2 = values2[0]
|
||||
sig2 = values2[5]
|
||||
# Check the signatures
|
||||
assert ecrecover(sighash1,
|
||||
as_num256(extract32(sig1, 0)),
|
||||
as_num256(extract32(sig1, 32)),
|
||||
as_num256(extract32(sig1, 64))) == self.validators[validator_index].addr
|
||||
assert ecrecover(sighash2,
|
||||
as_num256(extract32(sig2, 0)),
|
||||
as_num256(extract32(sig2, 32)),
|
||||
as_num256(extract32(sig2, 64))) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash1, sig1), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash2, sig2), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that they're from the same epoch
|
||||
assert epoch1 == epoch2
|
||||
# Check that they're not the same message
|
||||
|
@ -474,14 +461,8 @@ def prepare_commit_inconsistency_slash(validator_index: num, prepare_msg: bytes
|
|||
commit_epoch = values2[0]
|
||||
sig2 = values2[3]
|
||||
# Check the signatures
|
||||
assert ecrecover(sighash1,
|
||||
as_num256(extract32(sig1, 0)),
|
||||
as_num256(extract32(sig1, 32)),
|
||||
as_num256(extract32(sig1, 64))) == self.validators[validator_index].addr
|
||||
assert ecrecover(sighash2,
|
||||
as_num256(extract32(sig2, 0)),
|
||||
as_num256(extract32(sig2, 32)),
|
||||
as_num256(extract32(sig2, 64))) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash1, sig1), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash2, sig2), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that they're not the same message
|
||||
assert sighash1 != sighash2
|
||||
# Check that the prepare refers to something older than the commit
|
||||
|
@ -504,10 +485,7 @@ def commit_non_justification_slash(validator_index: num, commit_msg: bytes <= 10
|
|||
sig = values[3]
|
||||
# Check the signature
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
extract32(sig, 0, type=num256),
|
||||
extract32(sig, 32, type=num256),
|
||||
extract32(sig, 64, type=num256)) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash, sig), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that the commit is old enough
|
||||
assert self.current_epoch == block.number / self.epoch_length
|
||||
assert (self.current_epoch - epoch) * self.epoch_length * self.block_time > self.insufficiency_slash_delay
|
||||
|
@ -543,10 +521,7 @@ def prepare_non_justification_slash(validator_index: num, prepare_msg: bytes <=
|
|||
source_ancestry_hash = values[4]
|
||||
sig = values[5]
|
||||
# Check the signature
|
||||
assert ecrecover(sighash,
|
||||
extract32(sig, 0, type=num256),
|
||||
extract32(sig, 32, type=num256),
|
||||
extract32(sig, 64, type=num256)) == self.validators[validator_index].addr
|
||||
assert extract32(raw_call(self.validators[validator_index].addr, concat(sighash, sig), gas=500000, outsize=32), 0) == as_bytes32(1)
|
||||
# Check that the view change is old enough
|
||||
assert self.current_epoch == block.number / self.epoch_length
|
||||
assert (self.current_epoch - epoch) * self.block_time * self.epoch_length > self.insufficiency_slash_delay
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from ethereum import tester as t
|
||||
from ethereum import utils, state_transition, transactions, abi
|
||||
from viper import compiler
|
||||
import serpent
|
||||
from ethereum.slogging import LogRecorder, configure_logging, set_level
|
||||
config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug'
|
||||
#configure_logging(config_string=config_string)
|
||||
|
@ -19,6 +20,15 @@ def inject_tx(txhex):
|
|||
assert s.state.get_code(contract_address)
|
||||
return contract_address
|
||||
|
||||
code_template = """
|
||||
~calldatacopy(0, 0, 128)
|
||||
~call(3000, 1, 0, 0, 128, 0, 32)
|
||||
return(~mload(0) == %s)
|
||||
"""
|
||||
|
||||
def mk_validation_code(address):
|
||||
return serpent.compile(code_template % (utils.checksum_encode(address)))
|
||||
|
||||
# Install RLP decoder library
|
||||
rlp_decoder_address = inject_tx( '0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f')
|
||||
|
||||
|
@ -37,10 +47,14 @@ ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'con
|
|||
assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1
|
||||
assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1
|
||||
|
||||
k1_valcode_addr = s.send(t.k0, "", 0, mk_validation_code(t.a0))
|
||||
assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1
|
||||
|
||||
# Install Casper
|
||||
|
||||
casper_code = open('simple_casper.v.py').read().replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(t.a0)) \
|
||||
.replace('0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24', utils.checksum_encode(sighasher_address))
|
||||
casper_code = open('simple_casper.v.py').read().replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(k1_valcode_addr)) \
|
||||
.replace('0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24', utils.checksum_encode(sighasher_address)) \
|
||||
.replace('0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91', utils.checksum_encode(purity_checker_address))
|
||||
|
||||
print('Casper code length', len(compiler.compile(casper_code)))
|
||||
|
||||
|
@ -50,15 +64,6 @@ print('Gas consumed to launch Casper', s.state.receipts[-1].gas_used - s.state.r
|
|||
|
||||
# Helper functions for making a prepare, commit, login and logout message
|
||||
|
||||
code_template = """
|
||||
~calldatacopy(0, 0, 128)
|
||||
~call(3000, 1, 0, 0, 128, 0, 32)
|
||||
return(~mload(0) == %s)
|
||||
"""
|
||||
|
||||
def mk_validation_code(address):
|
||||
return serpent.compile(code_template % (utils.checksum_encode(address)))
|
||||
|
||||
def mk_prepare(epoch, hash, ancestry_hash, source_epoch, source_ancestry_hash, key):
|
||||
sighash = utils.sha3(rlp.encode([epoch, hash, ancestry_hash, source_epoch, source_ancestry_hash]))
|
||||
v, r, s = utils.ecdsa_raw_sign(sighash, key)
|
||||
|
@ -209,7 +214,9 @@ assert casper.get_current_epoch() == 1
|
|||
assert casper.get_consensus_messages__ancestry_hash_justified(0, b'\x00' * 32)
|
||||
print("Epoch 1 initialized")
|
||||
for k in (t.k1, t.k2, t.k3, t.k4, t.k5, t.k6):
|
||||
casper.deposit(utils.privtoaddr(k), utils.privtoaddr(k), value=3 * 10**18)
|
||||
valcode_addr = s.send(t.k0, '', 0, mk_validation_code(utils.privtoaddr(k)))
|
||||
assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [valcode_addr]))) == 1
|
||||
casper.deposit(valcode_addr, utils.privtoaddr(k), value=3 * 10**18)
|
||||
print("Processed 6 deposits")
|
||||
casper.prepare(0, mk_prepare(1, b'\x10' * 32, b'\x00' * 32, 0, b'\x00' * 32, t.k0))
|
||||
casper.commit(0, mk_commit(1, b'\x10' * 32, 0, t.k0))
|
||||
|
|
Loading…
Reference in New Issue