Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit b47fe53

Browse files
vubvub
authored andcommitted
Fixed withdrawing
1 parent dc6abda commit b47fe53

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

ethereum/casper_contract.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
minValidatorSize = 32
55
# Largest allowed validator size
66
maxValidatorSize = 131072
7-
# Base block reward
8-
BLOCK_REWARD = 10**17
97
# An epoch number that represents a validator "intending to stay forever"
108
NO_END_EPOCH = 2**99
119
# Address of "system" entry point
@@ -26,8 +24,10 @@
2624
data validatorSlotQueue[2**40][2**40]
2725
# Length of the queue
2826
data validatorSlotQueueLength[2**40]
27+
# Total amount of ETH deposited by active validators
28+
data totalActiveDeposits
2929
# Total amount of ETH deposited
30-
data totalDeposits
30+
data currentTotalDeposits
3131
# Total amount of ETH deposited during previous epochs
3232
data historicalTotalDeposits[2**40]
3333
# Keep track of future changes to total deposits
@@ -68,10 +68,10 @@
6868
$w * (1 - 2 * ($w < 0))
6969

7070
def const getBlockReward():
71-
return(max(self.totalDeposits, 1000000 * 10**18) * BLOCK_MAKING_PPB / 1000000000)
71+
return(max(self.currentTotalDeposits, 1000000 * 10**18) * BLOCK_MAKING_PPB / 1000000000)
7272

73-
def const getLockDuration():
74-
return(max(min(self.totalDeposits / 10**18 / 2, 10000000), self.epochLength * 2))
73+
def const getCurrentLockDuration():
74+
return(max(min(self.currentTotalDeposits / 10**18 / 2, 10000000), self.epochLength * 2))
7575

7676
def const getEpochLength():
7777
return(self.epochLength)
@@ -94,7 +94,7 @@ def const getValidatorCount(i):
9494
def const getHistoricalTotalDeposits(epoch):
9595
return(self.historicalTotalDeposits[epoch])
9696

97-
def deposit(validation_code:str, randao):
97+
def deposit(validation_code:str, randao, address):
9898
# Deposit too small
9999
if msg.value < minValidatorSize * 10**18:
100100
~invalid()
@@ -129,9 +129,10 @@ def deposit(validation_code:str, randao):
129129
self.validators[i][j].origDeposit = msg.value
130130
self.validators[i][j].start_epoch = self.currentEpoch + 2
131131
self.validators[i][j].end_epoch = NO_END_EPOCH
132-
self.validators[i][j].address = msg.sender
132+
self.validators[i][j].address = address
133133
self.validators[i][j].randao = randao
134-
self.validators[i][j].lock_duration = self.getLockDuration()
134+
self.currentTotalDeposits += msg.value
135+
self.validators[i][j].lock_duration = self.getCurrentLockDuration()
135136
self.totalDepositDeltas[self.validators[i][j].start_epoch] += msg.value
136137
~sstorebytes(ref(self.vchashToIndices[validation_code_hash]), [i, j], 64)
137138
log(type=NewValidator)
@@ -145,12 +146,12 @@ def newEpoch(epoch):
145146
while q < len(validatorSizes):
146147
self.historicalValidatorCounts[epoch][q] = self.validatorCounts[q]
147148
q += 1
148-
self.totalDeposits += self.totalDepositDeltas[epoch]
149-
self.historicalTotalDeposits[epoch] = self.totalDeposits
149+
self.totalActiveDeposits += self.totalDepositDeltas[epoch]
150+
self.historicalTotalDeposits[epoch] = self.totalActiveDeposits
150151
self.currentEpoch = epoch
151152

152153
def const getTotalDeposits():
153-
return(self.totalDeposits)
154+
return(self.currentTotalDeposits)
154155

155156
def const getBlockNumber():
156157
return(self.blockNumber)
@@ -448,13 +449,18 @@ def const getEndEpoch(vchash:bytes32):
448449
extractIndices(ref(i), ref(j), vchash)
449450
return(self.validators[i][j].end_epoch)
450451

452+
def const getLockDuration(vchash:bytes32):
453+
extractIndices(ref(i), ref(j), vchash)
454+
return(self.validators[i][j].lock_duration)
455+
451456
def const getCurrentEpoch():
452457
return(self.currentEpoch)
453458

454459
# Finalize withdrawing and take one's money out
455460
def withdraw(vchash:bytes32):
456461
extractIndices(ref(i), ref(j), vchash)
457-
if self.validators[i][j].end_epoch * self.epochLength + self.validators[i][j].lock_duration < block.timestamp:
462+
if self.validators[i][j].end_epoch * self.epochLength + self.validators[i][j].lock_duration <= block.number:
463+
self.currentTotalDeposits -= self.validators[i][j].origDeposit
458464
send(self.validators[i][j].address, self.validators[i][j].deposit)
459465
self.validators[i][j].deposit = 0
460466
self.validatorSlotQueue[i][self.validatorSlotQueueLength[i]] = j

ethereum/casper_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ def make_casper_genesis(validators, alloc, timestamp=0, epoch_length=100):
184184
t = Transaction(0, 0, 10**8, casper_config['CASPER_ADDR'], 0, ct.encode('initialize', [timestamp, epoch_length, 0, 4712388]))
185185
apply_transaction(state, t)
186186
# Add validators
187-
for i, (vcode, deposit_size, randao_commitment) in enumerate(validators):
187+
for i, (vcode, deposit_size, randao_commitment, address) in enumerate(validators):
188188
state.set_balance(utils.int_to_addr(1), deposit_size)
189189
t = Transaction(i, 0, 10**8, casper_config['CASPER_ADDR'], deposit_size,
190-
ct.encode('deposit', [vcode, randao_commitment]))
190+
ct.encode('deposit', [vcode, randao_commitment, address]))
191191
t._sender = utils.int_to_addr(1)
192192
success = apply_transaction(state, t)
193193
assert success
@@ -210,7 +210,7 @@ def make_casper_genesis(validators, alloc, timestamp=0, epoch_length=100):
210210
t._sender = casper_config['CASPER_ADDR']
211211
apply_transaction(state, t)
212212
assert call_casper(state, 'getEpoch', []) == 0
213-
assert call_casper(state, 'getTotalDeposits', []) == sum([d for a,d,r in validators])
213+
assert call_casper(state, 'getTotalDeposits', []) == sum([d for a,d,r,a in validators])
214214
state.commit()
215215
return state
216216

ethereum/tests/test_pos.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525
configure_logging(config_string=config_string)
2626

2727
NUM_PARTICIPANTS = 10
28+
BLOCK_MAKING_PPB = 10
2829

2930
print 'Initializing privkeys, addresses and randaos for validators'
3031
privkeys = [utils.sha3(str(i)) for i in range(NUM_PARTICIPANTS)]
3132
addrs = [utils.privtoaddr(k) for k in privkeys]
3233
randaos = [RandaoManager(utils.sha3(str(i))) for i in range(NUM_PARTICIPANTS)]
33-
deposit_sizes = [i * 50 + 50 for i in range(NUM_PARTICIPANTS)]
34+
deposit_sizes = [i * 500 + 500 for i in range(NUM_PARTICIPANTS)]
3435
vcodes = [generate_validation_code(a) for a in addrs]
3536
vchashes = [utils.sha3(c) for c in vcodes]
3637
assert len(privkeys) == len(addrs) == len(randaos) == len(deposit_sizes) == len(vcodes) == len(vchashes) == NUM_PARTICIPANTS
@@ -39,13 +40,17 @@
3940
ct = get_casper_ct()
4041
assert ct
4142
print 'Constructing genesis'
42-
s = make_casper_genesis(validators=[(generate_validation_code(a), ds * 10**18, r.get(9999))
43+
s = make_casper_genesis(validators=[(generate_validation_code(a), ds * 10**18, r.get(9999), a)
4344
for a, ds, r in zip(addrs, deposit_sizes, randaos)][:-1],
4445
alloc={a: {'balance': 10**18} for a in addrs},
4546
timestamp=int(time.time() - 99999),
4647
epoch_length=100)
4748
print 'Genesis constructed successfully'
4849
chains = [Chain(s.to_snapshot(), env=s.env) for i in range(NUM_PARTICIPANTS)]
50+
withdrawal_time_1 = call_casper(chains[0].state, 'getLockDuration', [vchashes[0]])
51+
52+
# List of validator IDs that created each block
53+
vids = []
4954

5055
# Create and sign a block
5156
def make_block(chain, key, randao, vchash, skips):
@@ -68,6 +73,7 @@ def make_block(chain, key, randao, vchash, skips):
6873
assert validate_block_header(s, b.header)
6974
print 'Validation successful'
7075
assert chains[0].add_block(b)
76+
vids.append(next_validator_id)
7177
print 'Block added to chain'
7278
# Make another block
7379
next_validator = call_casper(chains[0].state, 'getValidator', [0])
@@ -77,6 +83,7 @@ def make_block(chain, key, randao, vchash, skips):
7783
b2 = make_block(chains[0], privkeys[next_validator_id],
7884
randaos[next_validator_id], vchashes[next_validator_id], skip_count)
7985
assert chains[0].add_block(b2)
86+
vids.append(next_validator_id)
8087
print 'Second block added to chain'
8188
# Make a dunkle and include it in a transaction
8289
next_validator = call_casper(chains[1].state, 'getValidator', [1])
@@ -108,7 +115,6 @@ def make_block(chain, key, randao, vchash, skips):
108115
chains[0].state.commit()
109116
print 'Added new validator "in-flight", indices:', vchashes[-1].encode('hex')
110117
# Create some blocks
111-
vids = []
112118
bn = call_casper(chains[0].state, 'getBlockNumber')
113119
for i in range(bn + 1, 200):
114120
next_validator = call_casper(chains[0].state, 'getValidator', [0])
@@ -128,6 +134,7 @@ def make_block(chain, key, randao, vchash, skips):
128134
assert call_casper(chains[0].state, 'getEndEpoch', [vchashes[0]]) == 4
129135
chains[0].state.commit()
130136
print 'Withdrew a validator'
137+
print '%d blocks before ETH becomes available' % withdrawal_time_1
131138
for i in range(200, 400):
132139
next_validator = call_casper(chains[0].state, 'getValidator', [0])
133140
next_validator_id = vchashes.index(next_validator)
@@ -139,14 +146,26 @@ def make_block(chain, key, randao, vchash, skips):
139146
print 'Created 200 blocks after the deposit, created by validators:', vids[-200:]
140147
assert len(vchashes) - 1 in vids
141148
assert 0 in vids
142-
for i in range(400, 600):
149+
for i in range(400, 400 + withdrawal_time_1 + 1):
143150
next_validator = call_casper(chains[0].state, 'getValidator', [0])
144151
next_validator_id = vchashes.index(next_validator)
145152
b = make_block(chains[0], privkeys[next_validator_id], randaos[next_validator_id],
146153
vchashes[next_validator_id], 0)
147154
assert chains[0].add_block(b)
148155
vids.append(next_validator_id)
149-
print 'Created 200 blocks after the withdrawal, created by validators:', vids[-200:]
156+
print 'Created %d blocks after the withdrawal, created by validators:' % (withdrawal_time_1 + 1), vids[-200:]
150157
assert len(vchashes) - 1 in vids
151158
assert 0 not in vids[-200:]
159+
pre_bal = chains[0].state.get_balance(addrs[0])
160+
txdata = ct.encode('withdraw', [vchashes[0]])
161+
t4 = Transaction(chains[0].state.get_nonce(addrs[0]), 0, 1000000, casper_config['CASPER_ADDR'], 0, txdata).sign(privkeys[0])
162+
apply_transaction(chains[0].state, t4)
163+
post_bal = chains[0].state.get_balance(addrs[0])
164+
print 'Wei withdrawn:', post_bal - pre_bal
165+
blocks_by_v0_in_stage1 = len([x for x in vids[:200] if x == 0])
166+
expected_revenue_in_stage1 = blocks_by_v0_in_stage1 * max(sum(deposit_sizes[:-1]), 1000000) * 10**18 * BLOCK_MAKING_PPB / 10**9
167+
blocks_by_v0_in_stage2 = len([x for x in vids[200:400] if x == 0])
168+
expected_revenue_in_stage2 = blocks_by_v0_in_stage2 * max(sum(deposit_sizes), 1000000) * 10**18 * BLOCK_MAKING_PPB / 10**9
169+
170+
assert post_bal - pre_bal == deposit_sizes[0] * 10**18 + expected_revenue_in_stage1 + expected_revenue_in_stage2
152171
print 'PoS test fully passed'

0 commit comments

Comments
 (0)