mirror of
https://github.com/status-im/research.git
synced 2025-01-26 23:10:20 +00:00
Added bit mask features
This commit is contained in:
parent
8094cb1a8a
commit
941e8a6de5
@ -4,6 +4,8 @@ validators: public({
|
||||
deposit: wei_value,
|
||||
# The dynasty the validator is joining
|
||||
dynasty_start: num,
|
||||
# The dynasty the validator joined for the first time
|
||||
original_dynasty_start: num,
|
||||
# The dynasty the validator is leaving
|
||||
dynasty_end: num,
|
||||
# The timestamp at which the validator can withdraw
|
||||
@ -12,16 +14,16 @@ validators: public({
|
||||
addr: address,
|
||||
# Addess to withdraw to
|
||||
withdrawal_addr: address,
|
||||
# The max epoch at which the validator prepared
|
||||
max_prepared: num,
|
||||
# The max epoch at which the validator committed
|
||||
max_committed: num
|
||||
# Previous epoch in which this validator committed
|
||||
prev_commit_epoch: num
|
||||
}[num])
|
||||
|
||||
# The current dynasty (validator set changes between dynasties)
|
||||
dynasty: public(num)
|
||||
|
||||
# Amount of wei added to the total deposits in the next dynasty
|
||||
next_dynasty_wei_delta: wei_value
|
||||
|
||||
# Amount of wei added to the total deposits in the dynasty after that
|
||||
second_next_dynasty_wei_delta: wei_value
|
||||
|
||||
@ -31,10 +33,15 @@ total_deposits: public(wei_value[num])
|
||||
# Mapping of dynasty to start epoch of that dynasty
|
||||
dynasty_start_epoch: public(num[num])
|
||||
|
||||
# Mapping of epoch to what dynasty it is
|
||||
dynasty_in_epoch: public(num[num])
|
||||
|
||||
# Information for use in processing cryptoeconomic commitments
|
||||
consensus_messages: public({
|
||||
# How many prepares are there for this hash (hash of message hash + view source) from the current dynasty
|
||||
prepares: wei_value[bytes32],
|
||||
# Bitmap of which validator IDs have already prepared
|
||||
prepare_bitmap: num256[num][bytes32],
|
||||
# From the previous dynasty
|
||||
prev_dyn_prepares: wei_value[bytes32],
|
||||
# Is a prepare referencing the given ancestry hash justified?
|
||||
@ -51,6 +58,10 @@ consensus_messages: public({
|
||||
deposit_scale_factor: decimal
|
||||
}[num]) # index: epoch
|
||||
|
||||
# A bitmap, where the ith bit of dynasty_mark[arg1][arg2] shows
|
||||
# whether or not validator arg1 is active during dynasty arg2*256+i
|
||||
dynasty_mask: num256[num][num]
|
||||
|
||||
# ancestry[x][y] = k > 0: x is a kth generation ancestor of y
|
||||
ancestry: public(num[bytes32][bytes32])
|
||||
|
||||
@ -108,17 +119,17 @@ def initiate():
|
||||
# Only ~1 day, for testing purposes
|
||||
self.insufficiency_slash_delay = 86400
|
||||
# Temporary backdoor for testing purposes (to allow recovering destroyed deposits)
|
||||
self.owner = 0x1db3439a222c519ab44bb1144fc28167b4fa6ee6
|
||||
self.owner = 0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6
|
||||
# Add an initial validator
|
||||
self.validators[0] = {
|
||||
deposit: as_wei_value(3, ether),
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 1000000000000000000000000000000,
|
||||
original_dynasty_start: 0,
|
||||
withdrawal_epoch: 1000000000000000000000000000000,
|
||||
addr: 0x1db3439a222c519ab44bb1144fc28167b4fa6ee6,
|
||||
withdrawal_addr: 0x1db3439a222c519ab44bb1144fc28167b4fa6ee6,
|
||||
max_prepared: 0,
|
||||
max_committed: 0
|
||||
addr: 0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6,
|
||||
withdrawal_addr: 0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6,
|
||||
prev_commit_epoch: 0,
|
||||
}
|
||||
self.nextValidatorIndex = 1
|
||||
# Initialize the epoch counter
|
||||
@ -127,6 +138,7 @@ def initiate():
|
||||
self.sighasher = 0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24
|
||||
# Set an initial root of the epoch hash chain
|
||||
self.consensus_messages[0].ancestry_hash_justified[0x0000000000000000000000000000000000000000000000000000000000000000] = True
|
||||
# self.consensus_messages[0].committed = True
|
||||
# Set initial total deposit counter
|
||||
self.total_deposits[0] = as_wei_value(3, ether)
|
||||
# Set deposit scale factor
|
||||
@ -151,6 +163,7 @@ def initialize_epoch(epoch: num):
|
||||
self.next_dynasty_wei_delta = self.second_next_dynasty_wei_delta
|
||||
self.second_next_dynasty_wei_delta = 0
|
||||
self.dynasty_start_epoch[self.dynasty] = epoch
|
||||
self.dynasty_in_epoch[epoch] = self.dynasty
|
||||
# Compute square root factor
|
||||
ether_deposited_as_number = self.total_deposits[self.dynasty] / as_wei_value(1, ether)
|
||||
sqrt = ether_deposited_as_number / 2.0
|
||||
@ -172,12 +185,12 @@ def deposit(validation_addr: address, withdrawal_addr: address):
|
||||
self.validators[self.nextValidatorIndex] = {
|
||||
deposit: msg.value,
|
||||
dynasty_start: self.dynasty + 2,
|
||||
original_dynasty_start: self.dynasty + 2,
|
||||
dynasty_end: 1000000000000000000000000000000,
|
||||
withdrawal_epoch: 1000000000000000000000000000000,
|
||||
addr: validation_addr,
|
||||
withdrawal_addr: withdrawal_addr,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
prev_commit_epoch: 0,
|
||||
}
|
||||
self.nextValidatorIndex += 1
|
||||
self.second_next_dynasty_wei_delta += msg.value
|
||||
@ -206,6 +219,8 @@ def flick_status(validator_index: num, logout_msg: bytes <= 1024):
|
||||
if login_flag:
|
||||
# Check that we are logged out
|
||||
assert self.validators[validator_index].dynasty_end < self.dynasty
|
||||
# Check that we logged out for less than 3840 dynasties (min: ~2 months)
|
||||
assert self.validators[validator_index].dynasty_end >= self.dynasty - 3840
|
||||
# Apply the per-epoch deposit penalty
|
||||
prev_login_epoch = self.dynasty_start_epoch[self.validators[validator_index].dynasty_start]
|
||||
prev_logout_epoch = self.dynasty_start_epoch[self.validators[validator_index].dynasty_end + 1]
|
||||
@ -214,7 +229,22 @@ def flick_status(validator_index: num, logout_msg: bytes <= 1024):
|
||||
(self.consensus_messages[prev_logout_epoch].deposit_scale_factor /
|
||||
self.consensus_messages[prev_login_epoch].deposit_scale_factor))
|
||||
# Log back in
|
||||
self.validators[validator_index].dynasty_start = self.dynasty + 2
|
||||
# Go through the dynasty mask to clear out the ineligible dynasties
|
||||
old_ds = self.validators[validator_index].dynasty_end
|
||||
new_ds = self.dynasty + 2
|
||||
for i in range(old_ds / 256, old_ds / 256 + 16):
|
||||
if old_ds > i * 256:
|
||||
s = old_ds % 256
|
||||
else:
|
||||
s = 0
|
||||
if new_ds < i * 256 + 256:
|
||||
e = new_ds % 256
|
||||
else:
|
||||
e = 256
|
||||
self.dynasty_mask[validator_index][i] = num256_sub(shift(as_num256(1), e), shift(as_num256(1), s))
|
||||
if e < 256:
|
||||
break
|
||||
self.validators[validator_index].dynasty_start = new_ds
|
||||
self.validators[validator_index].dynasty_end = 1000000000000000000000000000000
|
||||
self.second_next_dynasty_wei_delta += self.validators[validator_index].deposit
|
||||
# Logging out
|
||||
@ -227,6 +257,19 @@ def flick_status(validator_index: num, logout_msg: bytes <= 1024):
|
||||
# Set the withdrawal date
|
||||
self.validators[validator_index].withdrawal_epoch = self.current_epoch + self.withdrawal_delay / self.block_time / self.epoch_length
|
||||
|
||||
# Removes a validator from the validator pool
|
||||
def delete_validator(validator_index: num):
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
original_dynasty_start: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
prev_commit_epoch: 0,
|
||||
}
|
||||
|
||||
# Withdraw deposited ether
|
||||
def withdraw(validator_index: num):
|
||||
# Check that we can withdraw
|
||||
@ -240,16 +283,30 @@ def withdraw(validator_index: num):
|
||||
self.consensus_messages[prev_login_epoch].deposit_scale_factor))
|
||||
# Withdraw
|
||||
send(self.validators[validator_index].withdrawal_addr, self.validators[validator_index].deposit)
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
}
|
||||
self.delete_validator(validator_index)
|
||||
|
||||
# Checks if a given validator could have prepared in a given epoch
|
||||
def check_eligible_in_epoch(validator_index: num, epoch: num) -> num(const):
|
||||
# Time limit for submitting a prepare
|
||||
assert epoch > self.current_epoch - 3840
|
||||
# Original starting dynasty of the validator; fail if before
|
||||
do = self.validators[validator_index].original_dynasty_start
|
||||
# Ending dynasty of the current login period
|
||||
de = self.validators[validator_index].dynasty_end
|
||||
# Dynasty of the prepare
|
||||
dc = self.dynasty_in_epoch[epoch]
|
||||
# Dynasty before the prepare (for prev dynasty checking)
|
||||
dp = dc - 1
|
||||
# Check against mask to see if the dynasty was eligible before
|
||||
cur_in_mask = bitwise_and(self.dynasty_mask[validator_index][dc / 256], shift(as_num256(1), dc % 256))
|
||||
prev_in_mask = bitwise_and(self.dynasty_mask[validator_index][dp / 256], shift(as_num256(1), dp % 256))
|
||||
o = 0
|
||||
# Return result as bitmask, bit 1 = in_current_dynasty, bit 0 = in_prev_dynasty
|
||||
if ((do <= dc and cur_in_mask == as_num256(0)) and dc < de):
|
||||
o += 2
|
||||
if ((do <= dp and prev_in_mask == as_num256(0)) and dp < de):
|
||||
o += 1
|
||||
return o
|
||||
|
||||
# Process a prepare message
|
||||
def prepare(validator_index: num, prepare_msg: bytes <= 1024):
|
||||
@ -271,35 +328,38 @@ def prepare(validator_index: num, prepare_msg: bytes <= 1024):
|
||||
extract32(sig, 0, type=num256),
|
||||
extract32(sig, 32, type=num256),
|
||||
extract32(sig, 64, type=num256)) == self.validators[validator_index].addr
|
||||
# Check that we are in the right epoch
|
||||
assert self.current_epoch == block.number / self.epoch_length
|
||||
assert self.current_epoch == epoch
|
||||
# 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
|
||||
assert not bitwise_and(self.consensus_messages[epoch].prepare_bitmap[sighash][validator_index / 256],
|
||||
shift(as_num256(1), validator_index % 256))
|
||||
# Check that we are at least (epoch length / 4) blocks into the epoch
|
||||
# assert block.number % self.epoch_length >= self.epoch_length / 4
|
||||
# Check that this validator was active in either the previous dynasty or the current one
|
||||
ds = self.validators[validator_index].dynasty_start
|
||||
de = self.validators[validator_index].dynasty_end
|
||||
dc = self.dynasty
|
||||
in_current_dynasty = (ds <= dc) and (dc < de)
|
||||
in_prev_dynasty = (ds <= (dc - 1)) and ((dc - 1) < de)
|
||||
epochcheck = self.check_eligible_in_epoch(validator_index, epoch)
|
||||
in_current_dynasty = epochcheck >= 2
|
||||
in_prev_dynasty = (epochcheck % 2) == 1
|
||||
assert in_current_dynasty or in_prev_dynasty
|
||||
# Check that the prepare is on top of a justified prepare
|
||||
assert self.consensus_messages[source_epoch].ancestry_hash_justified[source_ancestry_hash]
|
||||
# Check that we have not yet prepared for this epoch
|
||||
#assert self.validators[validator_index].max_prepared == epoch - 1
|
||||
# Pay the reward if the blockhash is correct
|
||||
if True: #if blockhash(epoch * self.epoch_length) == hash:
|
||||
reward = floor(self.validators[validator_index].deposit * self.reward_factor)
|
||||
# Pay the reward if the prepare was submitted in time and the blockhash is correct
|
||||
this_validators_deposit = self.validators[validator_index].deposit
|
||||
if self.current_epoch == epoch: #if blockhash(epoch * self.epoch_length) == hash:
|
||||
reward = floor(this_validators_deposit * self.reward_factor)
|
||||
self.validators[validator_index].deposit += reward
|
||||
self.total_deposits[self.dynasty] += reward
|
||||
# Can't prepare for this epoch again
|
||||
self.validators[validator_index].max_prepared = epoch
|
||||
self.consensus_messages[epoch].prepare_bitmap[sighash][validator_index / 256] = \
|
||||
bitwise_or(self.consensus_messages[epoch].prepare_bitmap[sighash][validator_index / 256],
|
||||
shift(as_num256(1), validator_index % 256))
|
||||
# self.validators[validator_index].max_prepared = epoch
|
||||
# Record that this prepare took place
|
||||
new_ancestry_hash = sha3(concat(hash, ancestry_hash))
|
||||
if in_current_dynasty:
|
||||
self.consensus_messages[epoch].prepares[sighash] += self.validators[validator_index].deposit
|
||||
self.consensus_messages[epoch].prepares[sighash] += this_validators_deposit
|
||||
if in_prev_dynasty:
|
||||
self.consensus_messages[epoch].prev_dyn_prepares[sighash] += self.validators[validator_index].deposit
|
||||
self.consensus_messages[epoch].prev_dyn_prepares[sighash] += this_validators_deposit
|
||||
# If enough prepares with the same epoch_source and hash are made,
|
||||
# then the hash value is justified for commitment
|
||||
if (self.consensus_messages[epoch].prepares[sighash] >= self.total_deposits[self.dynasty] * 2 / 3 and \
|
||||
@ -308,17 +368,19 @@ def prepare(validator_index: num, prepare_msg: bytes <= 1024):
|
||||
self.consensus_messages[epoch].ancestry_hash_justified[new_ancestry_hash] = True
|
||||
self.consensus_messages[epoch].hash_justified[hash] = True
|
||||
# Add a parent-child relation between ancestry hashes to the ancestry table
|
||||
self.ancestry[ancestry_hash][new_ancestry_hash] = 1
|
||||
if not self.ancestry[ancestry_hash][new_ancestry_hash]:
|
||||
self.ancestry[ancestry_hash][new_ancestry_hash] = 1
|
||||
raw_log([self.prepare_log_topic], prepare_msg)
|
||||
|
||||
# Process a commit message
|
||||
def commit(validator_index: num, commit_msg: bytes <= 1024):
|
||||
sighash = extract32(raw_call(self.sighasher, commit_msg, gas=200000, outsize=32), 0)
|
||||
# Extract parameters
|
||||
values = RLPList(commit_msg, [num, bytes32, bytes])
|
||||
values = RLPList(commit_msg, [num, bytes32, num, bytes])
|
||||
epoch = values[0]
|
||||
hash = values[1]
|
||||
sig = values[2]
|
||||
prev_commit_epoch = values[2]
|
||||
sig = values[3]
|
||||
# Check the signature
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
@ -333,21 +395,21 @@ def commit(validator_index: num, commit_msg: bytes <= 1024):
|
||||
# Check that the commit is justified
|
||||
assert self.consensus_messages[epoch].hash_justified[hash]
|
||||
# Check that this validator was active in either the previous dynasty or the current one
|
||||
ds = self.validators[validator_index].dynasty_start
|
||||
de = self.validators[validator_index].dynasty_end
|
||||
dc = self.dynasty
|
||||
in_current_dynasty = (ds <= dc) and (dc < de)
|
||||
in_prev_dynasty = (ds <= (dc - 1)) and ((dc - 1) < de)
|
||||
epochcheck = self.check_eligible_in_epoch(validator_index, epoch)
|
||||
in_current_dynasty = epochcheck >= 2
|
||||
in_prev_dynasty = (epochcheck % 2) == 1
|
||||
assert in_current_dynasty or in_prev_dynasty
|
||||
# Check that we have not yet committed for this epoch
|
||||
#assert self.validators[validator_index].max_committed == epoch - 1
|
||||
assert self.validators[validator_index].prev_commit_epoch == prev_commit_epoch
|
||||
assert prev_commit_epoch < epoch
|
||||
self.validators[validator_index].prev_commit_epoch = epoch
|
||||
# Pay the reward if the blockhash is correct
|
||||
if True: #if blockhash(epoch * self.epoch_length) == hash:
|
||||
reward = floor(self.validators[validator_index].deposit * self.reward_factor)
|
||||
self.validators[validator_index].deposit += reward
|
||||
self.total_deposits[self.dynasty] += reward
|
||||
# Can't commit for this epoch again
|
||||
self.validators[validator_index].max_committed = epoch
|
||||
# self.validators[validator_index].max_committed = epoch
|
||||
# Record that this commit took place
|
||||
if in_current_dynasty:
|
||||
self.consensus_messages[epoch].commits[hash] += self.validators[validator_index].deposit
|
||||
@ -391,16 +453,7 @@ def double_prepare_slash(validator_index: num, prepare1: bytes <= 1000, prepare2
|
||||
send(msg.sender, validator_deposit / 25)
|
||||
self.total_destroyed += validator_deposit * 24 / 25
|
||||
self.total_deposits[self.dynasty] -= (validator_deposit - validator_deposit / 25)
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
}
|
||||
self.delete_validator(validator_index)
|
||||
|
||||
def prepare_commit_inconsistency_slash(validator_index: num, prepare_msg: bytes <= 1024, commit_msg: bytes <= 1024):
|
||||
# Get hash for signature, and implicitly assert that it is an RLP list
|
||||
@ -409,12 +462,12 @@ def prepare_commit_inconsistency_slash(validator_index: num, prepare_msg: bytes
|
||||
sighash2 = extract32(raw_call(self.sighasher, commit_msg, gas=200000, outsize=32), 0)
|
||||
# Extract parameters
|
||||
values1 = RLPList(prepare_msg, [num, bytes32, bytes32, num, bytes32, bytes])
|
||||
values2 = RLPList(commit_msg, [num, bytes32, bytes])
|
||||
values2 = RLPList(commit_msg, [num, bytes32, num, bytes])
|
||||
prepare_epoch = values1[0]
|
||||
prepare_source_epoch = values1[3]
|
||||
sig1 = values1[5]
|
||||
commit_epoch = values2[0]
|
||||
sig2 = values2[2]
|
||||
sig2 = values2[3]
|
||||
# Check the signatures
|
||||
assert ecrecover(sighash1,
|
||||
as_num256(extract32(sig1, 0)),
|
||||
@ -435,24 +488,15 @@ def prepare_commit_inconsistency_slash(validator_index: num, prepare_msg: bytes
|
||||
send(msg.sender, validator_deposit / 25)
|
||||
self.total_destroyed += validator_deposit * 24 / 25
|
||||
self.total_deposits[self.dynasty] -= validator_deposit
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
}
|
||||
self.delete_validator(validator_index)
|
||||
|
||||
def commit_non_justification_slash(validator_index: num, commit_msg: bytes <= 1024):
|
||||
sighash = extract32(raw_call(self.sighasher, commit_msg, gas=200000, outsize=32), 0)
|
||||
# Extract parameters
|
||||
values = RLPList(commit_msg, [num, bytes32, bytes])
|
||||
values = RLPList(commit_msg, [num, bytes32, num, bytes])
|
||||
epoch = values[0]
|
||||
hash = values[1]
|
||||
sig = values[2]
|
||||
sig = values[3]
|
||||
# Check the signature
|
||||
assert len(sig) == 96
|
||||
assert ecrecover(sighash,
|
||||
@ -468,16 +512,7 @@ def commit_non_justification_slash(validator_index: num, commit_msg: bytes <= 10
|
||||
send(msg.sender, validator_deposit / 25)
|
||||
self.total_destroyed += validator_deposit * 24 / 25
|
||||
self.total_deposits[self.dynasty] -= validator_deposit
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
}
|
||||
self.delete_validator(validator_index)
|
||||
|
||||
# Fill in the table for which hash is what-degree ancestor of which other hash
|
||||
def derive_parenthood(older: bytes32, hash: bytes32, newer: bytes32):
|
||||
@ -523,16 +558,7 @@ def prepare_non_justification_slash(validator_index: num, prepare_msg: bytes <=
|
||||
send(msg.sender, validator_deposit / 25)
|
||||
self.total_destroyed += validator_deposit * 24 / 25
|
||||
self.total_deposits[self.dynasty] -= validator_deposit
|
||||
self.validators[validator_index] = {
|
||||
deposit: 0,
|
||||
dynasty_start: 0,
|
||||
dynasty_end: 0,
|
||||
withdrawal_epoch: 0,
|
||||
addr: None,
|
||||
withdrawal_addr: None,
|
||||
max_prepared: 0,
|
||||
max_committed: 0,
|
||||
}
|
||||
self.delete_validator(validator_index)
|
||||
|
||||
# Temporary backdoor for testing purposes (to allow recovering destroyed deposits)
|
||||
def owner_withdraw():
|
||||
|
@ -1,8 +1,8 @@
|
||||
from ethereum import tester as t
|
||||
from ethereum import utils, state_transition, transactions
|
||||
from ethereum import utils, state_transition, transactions, abi
|
||||
from viper import compiler
|
||||
#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'
|
||||
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)
|
||||
import rlp
|
||||
s = t.state()
|
||||
@ -12,20 +12,33 @@ t.gas_limit = 9999999
|
||||
EPOCH_LENGTH = 100
|
||||
|
||||
# Install RLP decoder library
|
||||
s.state.set_balance('0xfe2ec957647679d210034b65e9c7db2452910b0c', 9350880000000000)
|
||||
state_transition.apply_transaction(s.state, rlp.decode(utils.decode_hex('f903bd808506fc23ac008304c1908080b903aa6103988061000e6000396103a65660006101bf5361202059905901600090526101008152602081019050602052600060605261040036018060200159905901600090528181526020810190509050608052600060e0527f0100000000000000000000000000000000000000000000000000000000000000600035046101005260c061010051121561007e57fe5b60f86101005112156100a95760c061010051036001013614151561009e57fe5b6001610120526100ec565b60f761010051036020036101000a600161012051013504610140526101405160f7610100510360010101361415156100dd57fe5b60f76101005103600101610120525b5b366101205112156102ec577f01000000000000000000000000000000000000000000000000000000000000006101205135046101005260e0516060516020026020510152600160605101606052608061010051121561017a57600160e0516080510152600161012051602060e0516080510101376001610120510161012052602160e0510160e0526102da565b60b8610100511215610218576080610100510360e05160805101526080610100510360016101205101602060e05160805101013760816101005114156101ef5760807f010000000000000000000000000000000000000000000000000000000000000060016101205101350412156101ee57fe5b5b600160806101005103016101205101610120526020608061010051030160e0510160e0526102d9565b60c06101005112156102d65760b761010051036020036101000a6001610120510135046101405260007f0100000000000000000000000000000000000000000000000000000000000000600161012051013504141561027357fe5b603861014051121561028157fe5b6101405160e05160805101526101405160b761010051600161012051010103602060e05160805101013761014051600160b7610100510301016101205101610120526020610140510160e0510160e0526102d8565bfe5b5b5b602060605113156102e757fe5b6100ed565b60e051606051602002602051015261082059905901600090526108008152602081019050610160526000610120525b6060516101205113151561035c576020602060605102610120516020026020510151010161012051602002610160510152600161012051016101205261031b565b60e0518060206020606051026101605101018260805160006004600a8705601201f161038457fe5b50602060e051602060605102010161016051f35b6000f31b2d4f'), transactions.Transaction))
|
||||
assert s.state.get_code('0x0b8178879f97f2ada01fb8d219ee3d0ad74e91e0')
|
||||
s.state.set_balance('0x0A51b02F77E7c8dc64962B9d5FdAb8D9eC6cfBbe', 9366960000000000)
|
||||
state_transition.apply_transaction(s.state, rlp.decode(utils.decode_hex('f903bf808506fc23ac008304c3a88080b903ac61039a8061000e6000396103a85660006101df5361202059905901600090526101008152602081019050602052600060605261040036018060200159905901600090528181526020810190509050608052600060e0527f0100000000000000000000000000000000000000000000000000000000000000600035046101005260c061010051121561007e57fe5b60f86101005112156100a95760c061010051036001013614151561009e57fe5b6001610120526100ec565b60f761010051036020036101000a600161012051013504610140526101405160f7610100510360010101361415156100dd57fe5b60f76101005103600101610120525b5b366101205112156102ec577f01000000000000000000000000000000000000000000000000000000000000006101205135046101005260e0516060516020026020510152600160605101606052608061010051121561017a57600160e0516080510152600161012051602060e0516080510101376001610120510161012052602160e0510160e0526102da565b60b8610100511215610218576080610100510360e05160805101526080610100510360016101205101602060e05160805101013760816101005114156101ef5760807f010000000000000000000000000000000000000000000000000000000000000060016101205101350412156101ee57fe5b5b600160806101005103016101205101610120526020608061010051030160e0510160e0526102d9565b60c06101005112156102d65760b761010051036020036101000a6001610120510135046101405260007f0100000000000000000000000000000000000000000000000000000000000000600161012051013504141561027357fe5b603861014051121561028157fe5b6101405160e05160805101526101405160b761010051600161012051010103602060e05160805101013761014051600160b7610100510301016101205101610120526020610140510160e0510160e0526102d8565bfe5b5b5b602060605113156102e757fe5b6100ed565b60e051606051602002602051015261082059905901600090526108008152602081019050610160526000610120525b6060516101205113151561035c576020602060605102610120516020026020510151010161012051602002610160510152600161012051016101205261031b565b60e051600a8105601201816020602060605102610160510101836080516000600486f161038557fe5b5050602060e051602060605102010161016051f35b6000f31b2d4f'), transactions.Transaction))
|
||||
rlp_decoder_address = utils.normalize_address('0x84E7F44DdDc2Eaf6cdd08C18c80d1c4E15F99FF8')
|
||||
assert s.state.get_code(rlp_decoder_address)
|
||||
|
||||
# Install sig hasher
|
||||
|
||||
s.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000)
|
||||
|
||||
state_transition.apply_transaction(s.state, rlp.decode(utils.decode_hex('f902b9808506fc23ac008303b5608080b902a66102948061000e6000396102a2567f01000000000000000000000000000000000000000000000000000000000000006000350460205260c0602051121561003857fe6100a7565b60f8602051121561005657600160405260c0602051036060526100a6565b60f76020510360010160405260007f010000000000000000000000000000000000000000000000000000000000000060013504141561009157fe5b60f7602051036020036101000a600135046060525b5b36606051604051011415156100b857fe5b604051608052600060a0525b3660405112156101c0577f0100000000000000000000000000000000000000000000000000000000000000604051350460c052608060c05112156101165760405160a0526001604051016040526101bb565b60b860c051121561014257608060c0510360605260405160a052600160605101604051016040526101ba565b60c060c05112156101b75760007f01000000000000000000000000000000000000000000000000000000000000006001604051013504141561018057fe5b60b760c051036020036101000a600160405101350460605260405160a052600160b760c051036060510101604051016040526101b9565bfe5b5b5b6100c4565b60805160a0510360e0526103e861010052603860e051121561020f5760e05160c001610100515360e051608051600161010051013760e0516001016101005120610120526020610120f3610293565b60006101405260e051610160525b610160511561024257600161014051016101405261010061016051046101605261021d565b6101405160f7016101005153610140516020036101000a60e05102600161010051015260e0516080516101405160016101005101013760e05161014051600101016101005120610180526020610180f35b5b6000f31b2d4f'), transactions.Transaction))
|
||||
assert s.state.get_code('0x476c2ca9a7f3b16feca86512276271faf63b6a24')
|
||||
sighasher_address = utils.normalize_address('0x476c2ca9a7f3b16feca86512276271faf63b6a24')
|
||||
assert s.state.get_code(sighasher_address)
|
||||
|
||||
# Install purity checker
|
||||
|
||||
s.state.set_balance('0xea0f0d55ee82edf248ed648a9a8d213fba8b5081', 10842480000000000)
|
||||
state_transition.apply_transaction(s.state, rlp.decode(utils.decode_hex('f90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f'), transactions.Transaction))
|
||||
purity_checker_address = utils.normalize_address('0x9f56d05661285a8fcc0dbdb3c8070ad024030af3')
|
||||
assert s.state.get_code(purity_checker_address)
|
||||
|
||||
ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}])
|
||||
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
|
||||
|
||||
# Install Casper
|
||||
|
||||
casper_code = open('simple_casper.v.py').read().replace('0x1db3439a222c519ab44bb1144fc28167b4fa6ee6', utils.checksum_encode(t.a0))
|
||||
casper_code = open('simple_casper.v.py').read().replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(t.a0))
|
||||
|
||||
print('Casper code length', len(compiler.compile(casper_code)))
|
||||
|
||||
@ -35,17 +48,26 @@ 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)
|
||||
sig = utils.encode_int32(v) + utils.encode_int32(r) + utils.encode_int32(s)
|
||||
return rlp.encode([epoch, hash, ancestry_hash, source_epoch, source_ancestry_hash, sig])
|
||||
|
||||
def mk_commit(epoch, hash, key):
|
||||
sighash = utils.sha3(rlp.encode([epoch, hash]))
|
||||
def mk_commit(epoch, hash, prev_commit_epoch, key):
|
||||
sighash = utils.sha3(rlp.encode([epoch, hash, prev_commit_epoch]))
|
||||
v, r, s = utils.ecdsa_raw_sign(sighash, key)
|
||||
sig = utils.encode_int32(v) + utils.encode_int32(r) + utils.encode_int32(s)
|
||||
return rlp.encode([epoch, hash, sig])
|
||||
return rlp.encode([epoch, hash, prev_commit_epoch, sig])
|
||||
|
||||
def mk_status_flicker(epoch, login, key):
|
||||
sighash = utils.sha3(rlp.encode([epoch, login]))
|
||||
@ -59,24 +81,31 @@ print("Starting tests")
|
||||
casper.initiate()
|
||||
# Initialize the first epoch
|
||||
s.state.block_number = EPOCH_LENGTH
|
||||
casper.initialize_epoch(1)
|
||||
print('foo', casper.initialize_epoch(1))
|
||||
assert casper.get_nextValidatorIndex() == 1
|
||||
start = s.snapshot()
|
||||
print("Epoch initialized")
|
||||
print("Reward factor: %.8f" % (casper.get_reward_factor() * 2 / 3))
|
||||
# Send a prepare message
|
||||
casper.prepare(0, mk_prepare(1, '\x35' * 32, '\x00' * 32, 0, '\x00' * 32, t.k0))
|
||||
print('Gas consumed for a prepare', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used)
|
||||
epoch_1_anchash = utils.sha3(b'\x35' * 32 + b'\x00' * 32)
|
||||
assert casper.get_consensus_messages__hash_justified(1, b'\x35' * 32)
|
||||
assert casper.get_consensus_messages__ancestry_hash_justified(1, epoch_1_anchash)
|
||||
print('Gas consumed for a prepare', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used)
|
||||
print("Prepare message processed")
|
||||
try:
|
||||
casper.prepare(0, mk_prepare(1, '\x35' * 32, '\x00' * 32, 0, '\x00' * 32, t.k0))
|
||||
success = True
|
||||
except:
|
||||
success = False
|
||||
assert not success
|
||||
print("Prepare message fails the second time")
|
||||
# Send a commit message
|
||||
casper.commit(0, mk_commit(1, '\x35' * 32, t.k0))
|
||||
casper.commit(0, mk_commit(1, '\x35' * 32, 0, t.k0))
|
||||
print('Gas consumed for a commit', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used)
|
||||
# Check that we committed
|
||||
assert casper.get_consensus_messages__committed(1)
|
||||
print("Commit message processed")
|
||||
print('Gas consumed for a commit', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used)
|
||||
# Initialize the second epoch
|
||||
s.state.block_number += EPOCH_LENGTH
|
||||
casper.initialize_epoch(2)
|
||||
@ -87,7 +116,7 @@ print("Second epoch initialized, dynasty increased as expected")
|
||||
# Send a prepare message
|
||||
casper.prepare(0, mk_prepare(2, '\x45' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0))
|
||||
# Send a commit message
|
||||
epoch_2_commit = mk_commit(2, '\x45' * 32, t.k0)
|
||||
epoch_2_commit = mk_commit(2, '\x45' * 32, 1, t.k0)
|
||||
casper.commit(0, epoch_2_commit)
|
||||
epoch_2_anchash = utils.sha3(b'\x45' * 32 + epoch_1_anchash)
|
||||
assert casper.get_consensus_messages__ancestry_hash_justified(2, epoch_2_anchash)
|
||||
@ -112,7 +141,7 @@ s.revert(snapshot)
|
||||
print("PREPARE_COMMIT_CONSISTENCY slashing condition works")
|
||||
# Finish the third epoch
|
||||
casper.prepare(0, p1)
|
||||
casper.commit(0, mk_commit(3, '\x56' * 32, t.k0))
|
||||
casper.commit(0, mk_commit(3, '\x56' * 32, 2, t.k0))
|
||||
epoch_3_anchash = utils.sha3(b'\x56' * 32 + epoch_2_anchash)
|
||||
assert casper.get_consensus_messages__ancestry_hash_justified(3, epoch_3_anchash)
|
||||
assert casper.get_consensus_messages__committed(3)
|
||||
@ -133,7 +162,7 @@ epoch_5_anchash = utils.sha3(b'\x78' * 32 + epoch_4_anchash)
|
||||
p5 = mk_prepare(5, '\x78' * 32, epoch_4_anchash, 3, epoch_3_anchash, t.k0)
|
||||
casper.prepare(0, p5)
|
||||
# Test the COMMIT_REQ slashing condition
|
||||
kommit = mk_commit(5, b'\x80' * 32, t.k0)
|
||||
kommit = mk_commit(5, b'\x80' * 32, 3, t.k0)
|
||||
epoch_inc = 1 + int(86400 / 14 / EPOCH_LENGTH)
|
||||
s.state.block_number += EPOCH_LENGTH * epoch_inc
|
||||
print("Speeding up time to test remaining two slashing conditions")
|
||||
@ -178,7 +207,7 @@ 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)
|
||||
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, t.k0))
|
||||
casper.commit(0, mk_commit(1, b'\x10' * 32, 0, t.k0))
|
||||
epoch_1_anchash = utils.sha3(b'\x10' * 32 + b'\x00' * 32)
|
||||
assert casper.get_consensus_messages__committed(1)
|
||||
print("Prepared and committed")
|
||||
@ -187,7 +216,7 @@ casper.initialize_epoch(2)
|
||||
print("Epoch 2 initialized")
|
||||
assert casper.get_dynasty() == 1
|
||||
casper.prepare(0, mk_prepare(2, b'\x20' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0))
|
||||
casper.commit(0, mk_commit(2, b'\x20' * 32, t.k0))
|
||||
casper.commit(0, mk_commit(2, b'\x20' * 32, 1, t.k0))
|
||||
epoch_2_anchash = utils.sha3(b'\x20' * 32 + epoch_1_anchash)
|
||||
assert casper.get_consensus_messages__committed(2)
|
||||
print("Confirmed that one key is still sufficient to prepare and commit")
|
||||
@ -225,14 +254,14 @@ for i, k in ((1, t.k1), (2, t.k2), (3, t.k3)):
|
||||
# Still not prepared
|
||||
assert not casper.get_consensus_messages__hash_justified(3, b'\x30' * 32)
|
||||
print("Prepare from four of seven validators still not sufficient")
|
||||
# Prepare from a firth validator
|
||||
# Prepare from a fifth validator
|
||||
casper.prepare(4, mk_prepare(3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k4))
|
||||
# NOW we're prepared!
|
||||
assert casper.get_consensus_messages__hash_justified(3, b'\x30' * 32)
|
||||
print("Prepare from five of seven validators sufficient!")
|
||||
# Five commits
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]):
|
||||
casper.commit(i, mk_commit(3, b'\x30' * 32, k))
|
||||
casper.commit(i, mk_commit(3, b'\x30' * 32, 2 if i == 0 else 0, k))
|
||||
# And we committed!
|
||||
assert casper.get_consensus_messages__committed(3)
|
||||
print("Commit from five of seven validators sufficient")
|
||||
@ -246,7 +275,7 @@ epoch_4_anchash = utils.sha3(b'\x40' * 32 + epoch_3_anchash)
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]):
|
||||
casper.prepare(i, mk_prepare(4, b'\x40' * 32, epoch_3_anchash, 3, epoch_3_anchash, k))
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]):
|
||||
casper.commit(i, mk_commit(4, b'\x40' * 32, k))
|
||||
casper.commit(i, mk_commit(4, b'\x40' * 32, 3, k))
|
||||
assert casper.get_consensus_messages__committed(4)
|
||||
print("Prepared and committed")
|
||||
# Start epoch 5 / dynasty 4
|
||||
@ -270,7 +299,7 @@ for i, k in [(3, t.k3), (4, t.k4)]:
|
||||
assert casper.get_consensus_messages__hash_justified(5, b'\x50' * 32)
|
||||
print("Five prepares sufficient")
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]):
|
||||
casper.commit(i, mk_commit(5, b'\x50' * 32, k))
|
||||
casper.commit(i, mk_commit(5, b'\x50' * 32, 4, k))
|
||||
# Committed!
|
||||
assert casper.get_consensus_messages__committed(5)
|
||||
# Start epoch 6 / dynasty 5
|
||||
@ -282,7 +311,17 @@ print("Epoch 6 initialized")
|
||||
old_deposit_start = casper.get_dynasty_start_epoch(casper.get_validators__dynasty_start(4))
|
||||
old_deposit_end = casper.get_dynasty_start_epoch(casper.get_validators__dynasty_end(4) + 1)
|
||||
old_deposit = casper.get_validators__deposit(4)
|
||||
# Explanation:
|
||||
# * During dynasty 0, the validator deposited, so he joins the current set in dynasty 2
|
||||
# (epoch 3), and the previous set in dynasty 3 (epoch 4)
|
||||
# * During dynasty 2, the validator logs off, so he leaves the current set in dynasty 4
|
||||
# (epoch 5) and the previous set in dynasty 5 (epoch 6)
|
||||
assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0]
|
||||
casper.flick_status(4, mk_status_flicker(6, 1, t.k4))
|
||||
# Explanation:
|
||||
# * During dynasty 7, the validator will log on again. Hence, the dynasty mask
|
||||
# should include dynasties 4, 5, 6
|
||||
assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0]
|
||||
new_deposit = casper.get_validators__deposit(4)
|
||||
print("One validator logging back in")
|
||||
print("Penalty from %d epochs: %.4f" % (old_deposit_end - old_deposit_start, 1 - new_deposit / old_deposit))
|
||||
@ -292,7 +331,7 @@ epoch_6_anchash = utils.sha3(b'\x60' * 32 + epoch_5_anchash)
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2]):
|
||||
casper.prepare(i, mk_prepare(6, b'\x60' * 32, epoch_5_anchash, 5, epoch_5_anchash, k))
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2]):
|
||||
casper.commit(i, mk_commit(6, b'\x60' * 32, k))
|
||||
casper.commit(i, mk_commit(6, b'\x60' * 32, 5, k))
|
||||
assert casper.get_consensus_messages__committed(6)
|
||||
print("Three of four prepares and commits sufficient")
|
||||
# Start epoch 7 / dynasty 6
|
||||
@ -304,8 +343,11 @@ print("Epoch 7 initialized")
|
||||
epoch_7_anchash = utils.sha3(b'\x70' * 32 + epoch_6_anchash)
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2]):
|
||||
casper.prepare(i, mk_prepare(7, b'\x70' * 32, epoch_6_anchash, 6, epoch_6_anchash, k))
|
||||
print('Gas consumed for first prepare', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used)
|
||||
print('Gas consumed for second prepare', s.state.receipts[-2].gas_used - s.state.receipts[-3].gas_used)
|
||||
print('Gas consumed for third prepare', s.state.receipts[-3].gas_used - s.state.receipts[-4].gas_used)
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2]):
|
||||
casper.commit(i, mk_commit(7, b'\x70' * 32, k))
|
||||
casper.commit(i, mk_commit(7, b'\x70' * 32, 6, k))
|
||||
assert casper.get_consensus_messages__committed(7)
|
||||
print("Three of four prepares and commits sufficient")
|
||||
# Start epoch 8 / dynasty 7
|
||||
@ -329,8 +371,10 @@ for i, k in [(3, t.k3)]:
|
||||
assert casper.get_consensus_messages__hash_justified(8, b'\x80' * 32)
|
||||
print("Four of five prepares sufficient")
|
||||
for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]):
|
||||
casper.commit(i, mk_commit(8, b'\x80' * 32, k))
|
||||
casper.commit(i, mk_commit(8, b'\x80' * 32, 7 if i < 3 else 5, k))
|
||||
assert casper.get_consensus_messages__committed(8)
|
||||
print("Committed")
|
||||
# Validator rejoins current validator set in epoch 8
|
||||
assert [casper.check_eligible_in_epoch(4, i) for i in range(9)] == [0, 0, 0, 2, 3, 1, 0, 0, 2]
|
||||
|
||||
print("All tests passed")
|
||||
|
@ -1,12 +1,12 @@
|
||||
import random
|
||||
import datetime
|
||||
|
||||
hashpower = 14 * 10**12.
|
||||
diffs = [hashpower * 14.15]
|
||||
times = [1489762567]
|
||||
diffs = [257.74 * 10**12]
|
||||
hashpower = diffs[0] / 14.7
|
||||
times = [1491920186]
|
||||
|
||||
|
||||
for i in range(3368795, 6010000):
|
||||
for i in range(3517029, 6010000):
|
||||
blocktime = random.expovariate(hashpower / diffs[-1])
|
||||
adjfac = max(1 - int(blocktime / 10), -99) / 2048.
|
||||
newdiff = diffs[-1] * (1 + adjfac)
|
||||
|
@ -1,8 +1,8 @@
|
||||
macro calldatachar($x):
|
||||
div(calldataload($x), 2**248)
|
||||
|
||||
# sum([2**x for x in [0x31, 0x32, 0x33, 0x3a, 0x3b, 0x3c, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x54, 0x55, 0xf0, 0xff])
|
||||
mask = 57897811465722876096115075801844696845150819816717215668290421542284681019392
|
||||
# sum([2**x for x in [0x31, 0x32, 0x33, 0x3a, 0x3b, 0x3c, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x54, 0x55, 0xf0, 0xff]])
|
||||
mask = 57897811465722876096115075801844696845150819816717216876035649536196444422144
|
||||
|
||||
data approved_addrs[]
|
||||
|
||||
@ -26,14 +26,23 @@ def submit(addr: address):
|
||||
i += c - 0x5e
|
||||
# Call, callcode, delegatecall
|
||||
elif c == 0xf1 or c == 0xf2 or c == 0xf4:
|
||||
# Pattern-match two ways of setting the gas parameter:
|
||||
# Pattern-match four ways of setting the gas parameter:
|
||||
#
|
||||
# 1. PUSH<value>
|
||||
# 2. sub(gas, PUSH<value>)
|
||||
# 2. sub(GAS, PUSH<value>)
|
||||
# 3. GAS
|
||||
# 4. SWAP1 <address> (<gas> ... )
|
||||
# 5. DUP
|
||||
if op >= 2 and ops[op - 1] >= 0x60 and ops[op - 1] <= 0x7f:
|
||||
address_entry = op - 2
|
||||
elif op >= 4 and ops[op - 1] == 0x03 and ops[op - 2] == 0x5a and ops[op - 3] >= 0x60 and ops[op - 3] <= 0x7f:
|
||||
address_entry = op - 4
|
||||
elif op >= 2 and ops[op - 1] == 0x5a:
|
||||
address_entry = op - 2
|
||||
elif op >= 2 and ops[op - 1] == 0x90:
|
||||
address_entry = op - 2
|
||||
elif op >= 2 and ops[op - 1] >= 0x80 and ops[op - 1] < 0x90:
|
||||
address_entry = op - 2
|
||||
else:
|
||||
~invalid()
|
||||
# Operation before the gas parameter must satisfy one of three conditions:
|
||||
|
Loading…
x
Reference in New Issue
Block a user