Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

enhancement/validator-mutating-functions #70

Merged
merged 5 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions Sources/BeaconChain/BeaconChain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ extension BeaconChain {

for (i, _) in state.validatorRegistry.enumerated() {
if getEffectiveBalance(state: state, index: ValidatorIndex(i)) >= MAX_DEPOSIT_AMOUNT {
activateValidator(state: &state, index: ValidatorIndex(i), genesis: true)
state.validatorRegistry[i].activate(state: state, genesis: true)
}
}

Expand Down Expand Up @@ -442,27 +442,9 @@ extension BeaconChain {

extension BeaconChain {

static func activateValidator(state: inout BeaconState, index: ValidatorIndex, genesis: Bool) {
state.validatorRegistry[Int(index)].activationEpoch = genesis ? GENESIS_EPOCH : getCurrentEpoch(state: state).delayedActivationExitEpoch()
}

static func initiateValidatorExit(state: inout BeaconState, index: ValidatorIndex) {
state.validatorRegistry[Int(index)].initiatedExit = true
}

static func exitValidator(state: inout BeaconState, index: ValidatorIndex) {
var validator = state.validatorRegistry[Int(index)]
if validator.exitEpoch <= getCurrentEpoch(state: state).delayedActivationExitEpoch() {
return
}

validator.exitEpoch = getCurrentEpoch(state: state).delayedActivationExitEpoch()
state.validatorRegistry[Int(index)] = validator
}

static func slashValidator(state: inout BeaconState, index: ValidatorIndex) {
assert(state.slot < state.validatorRegistry[Int(index)].withdrawableEpoch.startSlot())
exitValidator(state: &state, index: index)
state.validatorRegistry[Int(index)].exit(state: state)

state.latestSlashedBalances[Int(getCurrentEpoch(state: state) % LATEST_SLASHED_EXIT_LENGTH)] += getEffectiveBalance(state: state, index: index)

Expand All @@ -476,8 +458,4 @@ extension BeaconChain {
state.validatorRegistry[Int(index)].slashed = true
state.validatorRegistry[Int(index)].withdrawableEpoch = currentEpoch + LATEST_SLASHED_EXIT_LENGTH
}

static func prepareValidatorForWithdrawal(state: inout BeaconState, index: ValidatorIndex) {
state.validatorRegistry[Int(index)].withdrawableEpoch = getCurrentEpoch(state: state) + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
}
}
21 changes: 19 additions & 2 deletions Sources/BeaconChain/DataStructures/State/Validator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,30 @@ import Foundation
struct Validator {
let pubkey: Data
let withdrawalCredentials: Data
var activationEpoch: UInt64
var exitEpoch: UInt64
private(set) var activationEpoch: UInt64
private(set) var exitEpoch: UInt64
var withdrawableEpoch: UInt64
var initiatedExit: Bool
var slashed: Bool

func isActive(epoch: Epoch) -> Bool {
return activationEpoch <= epoch && epoch < exitEpoch
}

// @todo passing state kinda seems ugly
mutating func activate(state: BeaconState, genesis: Bool) {
activationEpoch = genesis ? GENESIS_EPOCH : BeaconChain.getCurrentEpoch(state: state).delayedActivationExitEpoch()
}

mutating func exit(state: BeaconState) {
if exitEpoch <= BeaconChain.getCurrentEpoch(state: state).delayedActivationExitEpoch() {
return
}

exitEpoch = BeaconChain.getCurrentEpoch(state: state).delayedActivationExitEpoch()
}

mutating func prepareForWithdrawal(state: BeaconState) {
withdrawableEpoch = BeaconChain.getCurrentEpoch(state: state) + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
}
}
10 changes: 5 additions & 5 deletions Sources/BeaconChain/StateTransition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ extension StateTransition {
)
)

BeaconChain.initiateValidatorExit(state: &state, index: exit.validatorIndex)
state.validatorRegistry[Int(exit.validatorIndex)].initiatedExit = true
}
}

Expand Down Expand Up @@ -698,7 +698,7 @@ extension StateTransition {
break
}

BeaconChain.prepareValidatorForWithdrawal(state: &state, index: ValidatorIndex(i))
state.validatorRegistry[i].prepareForWithdrawal(state: state)
}
}

Expand All @@ -717,7 +717,7 @@ extension StateTransition {
break
}

BeaconChain.activateValidator(state: &state, index: ValidatorIndex(i), genesis: false)
state.validatorRegistry[i].activate(state: state, genesis: false)
}
}

Expand All @@ -729,7 +729,7 @@ extension StateTransition {
break
}

BeaconChain.exitValidator(state: &state, index: ValidatorIndex(i))
state.validatorRegistry[i].exit(state: state)
}
}

Expand All @@ -745,7 +745,7 @@ extension StateTransition {
static func processEjections(state: inout BeaconState) {
for i in state.validatorRegistry.activeIndices(epoch: BeaconChain.getCurrentEpoch(state: state)) {
if state.validatorBalances[Int(i)] < EJECTION_BALANCE {
BeaconChain.exitValidator(state: &state, index: i)
state.validatorRegistry[Int(i)].exit(state: state)
}
}
}
Expand Down
78 changes: 0 additions & 78 deletions Tests/BeaconChainTests/BeaconChainTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,83 +55,5 @@ final class BeaconChainTests: XCTestCase {
// )
// )
// )
// }

func testInitiateValidatorExit() {
var state = BeaconChain.genesisState(
genesisTime: 0,
latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)),
depositLength: 0
)

for _ in 0..<3 {
state.validatorRegistry.append(
Validator(
pubkey: Data(count: 32),
withdrawalCredentials: Data(count: 32),
activationEpoch: 0,
exitEpoch: 0,
withdrawableEpoch: 0,
initiatedExit: false,
slashed: false
)
)
}

BeaconChain.initiateValidatorExit(state: &state, index: 2)

XCTAssertFalse(state.validatorRegistry[0].initiatedExit)
XCTAssertTrue(state.validatorRegistry[2].initiatedExit)
}

func testActivateValidator() {
var state = BeaconChain.genesisState(
genesisTime: 0,
latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)),
depositLength: 0
)

state.slot = 10
state.validatorRegistry.append(
Validator(
pubkey: Data(count: 32),
withdrawalCredentials: Data(count: 32),
activationEpoch: 0,
exitEpoch: 0,
withdrawableEpoch: 0,
initiatedExit: false,
slashed: false
)
)

BeaconChain.activateValidator(state: &state, index: 0, genesis: false)
XCTAssertEqual(state.validatorRegistry[0].activationEpoch, 5)
}

// func testExitValidator() {
// var state = BeaconChain.genesisState(
// genesisTime: 0,
// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32))
// )
//
// state.slot = 100
// state.validatorRegistry.append(
// Validator(
// pubkey: Data(count: 32),
// withdrawalCredentials: Data(count: 32),
// activationEpoch: 0,
// exitEpoch: 0,
// withdrawalEpoch: 0,
// penalizedEpoch: 0,
// exitCount: 0,
// statusFlags: 0,
// latestCustodyReseedSlot: 0,
// penultimateCustodyReseedSlot: 0
// )
// )
//
// BeaconChain.exitValidator(state: &state, index: 0)
// XCTAssertEqual(state.validatorRegistry[0].exitEpoch, 1 + ENTRY_EXIT_DELAY)
// XCTAssertEqual(state.validatorRegistry[0].exitCount, 1)
// }
}
42 changes: 42 additions & 0 deletions Tests/BeaconChainTests/DataStructures/State/ValidatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,48 @@ final class ValidatorTests: XCTestCase {

}

func testActivate() {
var state = BeaconChain.genesisState(
genesisTime: 0,
latestEth1Data: Eth1Data(depositRoot: ZERO_HASH, blockHash: ZERO_HASH),
depositLength: 0
)

state.slot = 10
var validator = createValidator(epoch: 1)

validator.activate(state: state, genesis: false)
XCTAssertEqual(validator.activationEpoch, 5)
}

func testExitValidator() {
var state = BeaconChain.genesisState(
genesisTime: 0,
latestEth1Data: Eth1Data(depositRoot: ZERO_HASH, blockHash: ZERO_HASH),
depositLength: 0
)

state.slot = 100
var validator = createValidator(epoch: BeaconChain.getCurrentEpoch(state: state).delayedActivationExitEpoch())
validator.exit(state: state)

XCTAssertEqual(validator.exitEpoch, BeaconChain.getCurrentEpoch(state: state).delayedActivationExitEpoch())
}

func testPrepareForWithdrawal() {
var state = BeaconChain.genesisState(
genesisTime: 0,
latestEth1Data: Eth1Data(depositRoot: ZERO_HASH, blockHash: ZERO_HASH),
depositLength: 0
)

state.slot = 0
var validator = createValidator(epoch: 1)
validator.prepareForWithdrawal(state: state)

XCTAssertEqual(validator.withdrawableEpoch, MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
}

private func createValidator(epoch: Epoch) -> Validator {
return Validator(
pubkey: ZERO_HASH,
Expand Down