From dd078b86c5d78823058b822ba40abe6db4c9e3a6 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 1 Jul 2019 23:01:32 +0200 Subject: [PATCH 01/41] removed all the old stuff --- Sources/BeaconChain/BLS.swift | 16 - Sources/BeaconChain/BeaconChain.swift | 457 --------- Sources/BeaconChain/Constants.swift | 60 -- .../DataStructures/Blocks/BeaconBlock.swift | 11 - .../Blocks/BeaconBlockBody.swift | 10 - .../Blocks/ProposalSignedData.swift | 8 - .../DataStructures/State/BeaconState.swift | 35 - .../DataStructures/State/Crosslink.swift | 6 - .../DataStructures/State/Eth1Data.swift | 6 - .../DataStructures/State/Eth1DataVote.swift | 6 - .../DataStructures/State/Fork.swift | 19 - .../State/PendingAttestation.swift | 8 - .../DataStructures/State/Validator.swift | 32 - .../Attestations/Attestation.swift | 8 - .../Attestations/AttestationData.swift | 12 - .../AttestationDataAndCustodyBit.swift | 6 - .../AttesterSlashings/AttesterSlashing.swift | 6 - .../SlashableAttestation.swift | 8 - .../Transactions/Deposits/Deposit.swift | 7 - .../Transactions/Deposits/DepositData.swift | 7 - .../Transactions/Deposits/DepositInput.swift | 7 - .../Transactions/ProposerSlashing.swift | 7 - .../Transactions/Transfer.swift | 11 - .../Transactions/VoluntaryExit.swift | 7 - Sources/BeaconChain/Enums/Domain.swift | 10 - .../Extensions/Array+AttestationTarget.swift | 17 - .../Extensions/Array+Validator.swift | 15 - .../Extensions/Array+ValidatorIndex.swift | 8 - Sources/BeaconChain/Extensions/Array.swift | 13 - Sources/BeaconChain/Extensions/Data.swift | 24 - Sources/BeaconChain/Extensions/Epoch.swift | 12 - Sources/BeaconChain/Extensions/Int.swift | 8 - Sources/BeaconChain/Extensions/Numeric.swift | 11 - Sources/BeaconChain/Extensions/Slot.swift | 8 - Sources/BeaconChain/Extensions/UInt64.swift | 19 - .../BeaconChain/ForkChoice/ForkChoice.swift | 7 - Sources/BeaconChain/ForkChoice/LMDGhost.swift | 22 - Sources/BeaconChain/Operators/Power.swift | 18 - Sources/BeaconChain/StateTransition.swift | 968 ------------------ Sources/BeaconChain/Store/Store.swift | 25 - Sources/BeaconChain/Types.swift | 12 - Tests/BeaconChainTests/BeaconChainTests.swift | 59 -- .../DataStructures/State/ForkTests.swift | 27 - .../DataStructures/State/ValidatorTests.swift | 68 -- .../Array+AttestationTargetTests.swift | 47 - .../Array+ValidatorIndexTests.swift | 20 - .../Extensions/Array+ValidatorTests.swift | 30 - .../Extensions/ArrayTests.swift | 11 - .../Extensions/EpochTests.swift | 13 - .../Extensions/IntTests.swift | 10 - .../Extensions/SlotTests.swift | 9 - Tests/BeaconChainTests/Mocks/MockStore.swift | 20 - .../StateTransitionTests.swift | 224 ---- Tests/LinuxMain.swift | 2 - 54 files changed, 2497 deletions(-) delete mode 100644 Sources/BeaconChain/BLS.swift delete mode 100644 Sources/BeaconChain/Constants.swift delete mode 100644 Sources/BeaconChain/DataStructures/Blocks/BeaconBlock.swift delete mode 100644 Sources/BeaconChain/DataStructures/Blocks/BeaconBlockBody.swift delete mode 100644 Sources/BeaconChain/DataStructures/Blocks/ProposalSignedData.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/BeaconState.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/Crosslink.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/Eth1Data.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/Eth1DataVote.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/Fork.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/PendingAttestation.swift delete mode 100644 Sources/BeaconChain/DataStructures/State/Validator.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Attestations/Attestation.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationData.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationDataAndCustodyBit.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/AttesterSlashing.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/SlashableAttestation.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Deposits/Deposit.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositData.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositInput.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/ProposerSlashing.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/Transfer.swift delete mode 100644 Sources/BeaconChain/DataStructures/Transactions/VoluntaryExit.swift delete mode 100644 Sources/BeaconChain/Enums/Domain.swift delete mode 100644 Sources/BeaconChain/Extensions/Array+AttestationTarget.swift delete mode 100644 Sources/BeaconChain/Extensions/Array+Validator.swift delete mode 100644 Sources/BeaconChain/Extensions/Array+ValidatorIndex.swift delete mode 100644 Sources/BeaconChain/Extensions/Array.swift delete mode 100644 Sources/BeaconChain/Extensions/Data.swift delete mode 100644 Sources/BeaconChain/Extensions/Epoch.swift delete mode 100644 Sources/BeaconChain/Extensions/Int.swift delete mode 100644 Sources/BeaconChain/Extensions/Numeric.swift delete mode 100644 Sources/BeaconChain/Extensions/Slot.swift delete mode 100644 Sources/BeaconChain/Extensions/UInt64.swift delete mode 100644 Sources/BeaconChain/ForkChoice/ForkChoice.swift delete mode 100644 Sources/BeaconChain/ForkChoice/LMDGhost.swift delete mode 100644 Sources/BeaconChain/Operators/Power.swift delete mode 100644 Sources/BeaconChain/StateTransition.swift delete mode 100644 Sources/BeaconChain/Store/Store.swift delete mode 100644 Sources/BeaconChain/Types.swift delete mode 100644 Tests/BeaconChainTests/BeaconChainTests.swift delete mode 100644 Tests/BeaconChainTests/DataStructures/State/ForkTests.swift delete mode 100644 Tests/BeaconChainTests/DataStructures/State/ValidatorTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/Array+AttestationTargetTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/Array+ValidatorIndexTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/Array+ValidatorTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/ArrayTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/EpochTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/IntTests.swift delete mode 100644 Tests/BeaconChainTests/Extensions/SlotTests.swift delete mode 100644 Tests/BeaconChainTests/Mocks/MockStore.swift delete mode 100644 Tests/BeaconChainTests/StateTransitionTests.swift diff --git a/Sources/BeaconChain/BLS.swift b/Sources/BeaconChain/BLS.swift deleted file mode 100644 index ee4e9ea..0000000 --- a/Sources/BeaconChain/BLS.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation - -class BLS { - - static func verify(pubkey: Data, message: Data, signature: Data, domain: UInt64) -> Bool { - return true - } - - static func verify(pubkeys: [Data], messages: [Data], signature: Data, domain: UInt64) -> Bool { - return true - } - - static func aggregate(pubkeys: [Data]) -> Data { - return Data(count: 32) - } -} diff --git a/Sources/BeaconChain/BeaconChain.swift b/Sources/BeaconChain/BeaconChain.swift index 305452a..e237141 100644 --- a/Sources/BeaconChain/BeaconChain.swift +++ b/Sources/BeaconChain/BeaconChain.swift @@ -1,461 +1,4 @@ import Foundation -// @todo figure out better name -// @todo refactor so this isn't all in one class - class BeaconChain { - - static func hash(_ data: Any) -> Data { - // @todo - return Data(count: 0) - } - - static func hashTreeRoot(_ data: Any) -> Data { - // @todo - return Data(count: 0) - } - - static func signedRoot(_ data: Any, field: String) -> Data { - // @todo - return Data(count: 0) - } - -} - -extension BeaconChain { - - static func getPreviousEpoch(state: BeaconState) -> Epoch { - return max(getCurrentEpoch(state: state) - 1, GENESIS_EPOCH) - } - - static func getCurrentEpoch(state: BeaconState) -> Epoch { - return state.slot.toEpoch() - } -} - -extension BeaconChain { - - // @todo check this shit - static func getPermutedIndex(index i: Int, listSize: Int, seed: Bytes32) -> Int { - assert(i < listSize) - assert(listSize < 2**40) - - var index = i - for round in 0..) -> Int in - return ptr.pointee - } % listSize - let flip = (pivot - index) % listSize - let position = max(index, flip) - - var positionBytes = position / 256 - let source = hash(seed + roundBytes + Data(bytes: &positionBytes, count: 4)) - - let byte = source[(position % 256) / 8] - let bit = (byte >> (position % 8)) % UInt8(2) - index = bit == 1 ? flip : index - } - - return index - } - - static func getShuffling(seed: Bytes32, validators: [Validator], epoch: Epoch) -> [[ValidatorIndex]] { - let activeValidatorIndices = validators.activeIndices(epoch: epoch) - - let shuffledActiveValidatorIndices = activeValidatorIndices.map { - activeValidatorIndices[getPermutedIndex(index: Int($0), listSize: activeValidatorIndices.count, seed: seed)] - } - - return shuffledActiveValidatorIndices.split(count: getEpochCommitteeCount(activeValidatorCount: activeValidatorIndices.count)) - } -} - -extension BeaconChain { - - static func getEpochCommitteeCount(activeValidatorCount: Int) -> Int { - return Int( - max( - 1, - min( - SHARD_COUNT / SLOTS_PER_EPOCH, - UInt64(activeValidatorCount) / SLOTS_PER_EPOCH / TARGET_COMMITTEE_SIZE - ) - ) * SLOTS_PER_EPOCH - ) - } - - static func getPreviousEpochCommitteeCount(state: BeaconState) -> Int { - let previousActiveValidators = state.validatorRegistry.activeIndices(epoch: state.previousShufflingEpoch) - return getEpochCommitteeCount(activeValidatorCount: previousActiveValidators.count) - } - - static func getCurrentEpochCommitteeCount(state: BeaconState) -> Int { - let currentActiveValidators = state.validatorRegistry.activeIndices(epoch: state.currentShufflingEpoch) - return getEpochCommitteeCount(activeValidatorCount: currentActiveValidators.count) - } - - static func getNextEpochCommitteeCount(state: BeaconState) -> Int { - let nextActiveValidators = state.validatorRegistry.activeIndices(epoch: getCurrentEpoch(state: state) + 1) - return getEpochCommitteeCount(activeValidatorCount: nextActiveValidators.count) - } - - static func crosslinkCommittees( - _ state: BeaconState, - at slot: Slot, - registryChange: Bool = false - ) -> [([ValidatorIndex], Shard)] { - let epoch = slot.toEpoch() - let currentEpoch = getCurrentEpoch(state: state) - let previousEpoch = getPreviousEpoch(state: state) - let nextEpoch = currentEpoch + 1 - - assert(previousEpoch <= epoch && epoch <= nextEpoch) - - var committeesPerEpoch: Int! - var seed: Data! - var shufflingEpoch: UInt64! - var shufflingStartShard: UInt64! - - switch epoch { - case currentEpoch: - committeesPerEpoch = getCurrentEpochCommitteeCount(state: state) - seed = state.currentShufflingSeed - shufflingEpoch = state.currentShufflingEpoch - shufflingStartShard = state.currentShufflingStartShard - case previousEpoch: - committeesPerEpoch = getPreviousEpochCommitteeCount(state: state) - seed = state.previousShufflingSeed - shufflingEpoch = state.previousShufflingEpoch - shufflingStartShard = state.previousShufflingStartShard - case nextEpoch: - let currentCommitteesPerEpoch = getCurrentEpochCommitteeCount(state: state) - committeesPerEpoch = getNextEpochCommitteeCount(state: state) - shufflingEpoch = nextEpoch - let epochsSinceLastRegistryUpdate = currentEpoch - state.validatorRegistryUpdateEpoch - if registryChange { - seed = generateSeed(state: state, epoch: nextEpoch) - shufflingStartShard = (state.currentShufflingStartShard + UInt64(currentCommitteesPerEpoch)) % SHARD_COUNT - } else if epochsSinceLastRegistryUpdate > 1 && Int(epochsSinceLastRegistryUpdate).isPowerOfTwo() { - seed = generateSeed(state: state, epoch: nextEpoch) - shufflingStartShard = state.currentShufflingStartShard - } else { - seed = state.currentShufflingSeed - shufflingStartShard = state.currentShufflingStartShard - } - default: - break - } - - let shuffling = getShuffling(seed: seed, validators: state.validatorRegistry, epoch: shufflingEpoch) - - let offset = slot % SLOTS_PER_EPOCH - let committeesPerSlot = UInt64(committeesPerEpoch) / SLOTS_PER_EPOCH - let slotStartShard = (shufflingStartShard + committeesPerSlot * offset) % SHARD_COUNT - - return (0.. Bytes32 { - assert(state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH) - assert(slot < state.slot) - return state.latestBlockRoots[Int(slot % LATEST_BLOCK_ROOTS_LENGTH)] - } - - static func getRandaoMix(state: BeaconState, epoch: Epoch) -> Bytes32 { - let currentEpoch = getCurrentEpoch(state: state) - assert(currentEpoch - LATEST_RANDAO_MIXES_LENGTH < epoch && epoch <= currentEpoch) - return state.latestRandaoMixes[Int(epoch % LATEST_RANDAO_MIXES_LENGTH)] - } - - static func getActiveIndexRoot(state: BeaconState, epoch: Epoch) -> Bytes32 { - let currentEpoch = getCurrentEpoch(state: state) - assert(currentEpoch - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY < epoch && epoch <= currentEpoch + ACTIVATION_EXIT_DELAY) - return state.latestActiveIndexRoots[Int(epoch % LATEST_ACTIVE_INDEX_ROOTS_LENGTH)] - } -} - -extension BeaconChain { - - static func generateSeed(state: BeaconState, epoch: Epoch) -> Data { - return hash( - getRandaoMix(state: state, epoch: epoch - MIN_SEED_LOOKAHEAD) + - getActiveIndexRoot(state: state, epoch: epoch) + - epoch.bytes32 - ) - } - - static func getBeaconProposerIndex(state: BeaconState, slot: Slot) -> ValidatorIndex { - let firstCommittee = crosslinkCommittees(state, at: slot)[0].0 - return firstCommittee[Int(slot) % firstCommittee.count] - } - - static func merkleRoot(values: [Bytes32]) -> Bytes32 { - var o = [Data](repeating: Data(repeating: 0, count: 1), count: values.count - 1) - o.append(contentsOf: values) - - for i in stride(from: values.count - 1, through: 0, by: -1) { - o[i] = hash(o[i * 2] + o[i * 2 + 1]) - } - - return o[1] - } - - static func getAttestationParticipants( - state: BeaconState, - attestationData: AttestationData, - bitfield: Data - ) -> [ValidatorIndex] { - let crosslinkCommittees = self.crosslinkCommittees(state, at: attestationData.slot) - - assert(crosslinkCommittees.map({ return $0.1 }).contains(attestationData.shard)) - - // @todo clean this ugly up - guard let crosslinkCommittee = crosslinkCommittees.first(where: { - $0.1 == attestationData.shard - })?.0 else { - assert(false) - } - - assert(verifyBitfield(bitfield: bitfield, committeeSize: crosslinkCommittee.count)) - - return crosslinkCommittee.enumerated().compactMap { - if getBitfieldBit(bitfield: bitfield, i: $0.offset) == 0b1 { - return $0.element - } - - return nil - } - } - - static func getEffectiveBalance(state: BeaconState, index: ValidatorIndex) -> Gwei { - return min(state.validatorBalances[Int(index)], MAX_DEPOSIT_AMOUNT) - } - - static func getBitfieldBit(bitfield: Data, i: Int) -> Int { - return Int((bitfield[i / 8] >> (i % 8))) % 2 - } - - static func verifyBitfield(bitfield: Data, committeeSize: Int) -> Bool { - if bitfield.count != (committeeSize + 7) / 8 { - return false - } - - for i in (committeeSize + 1)..<(bitfield.count * 8) { - if getBitfieldBit(bitfield: bitfield, i: i) == 0b1 { - return false - } - } - - return true - } -} - -extension BeaconChain { - - static func verifySlashableAttestation(state: BeaconState, slashableAttestation: SlashableAttestation) -> Bool { - if slashableAttestation.custodyBitfield != Data(repeating: 0, count: slashableAttestation.custodyBitfield.count) { - return false - } - - if slashableAttestation.validatorIndices.count == 0 { - return false - } - - for i in 0..<(slashableAttestation.validatorIndices.count - 1) { - if slashableAttestation.validatorIndices[i] >= slashableAttestation.validatorIndices[i + 1] { - return false - } - } - - if !verifyBitfield(bitfield: slashableAttestation.custodyBitfield, committeeSize: slashableAttestation.validatorIndices.count) { - return false - } - - if slashableAttestation.validatorIndices.count > MAX_INDICES_PER_SLASHABLE_VOTE { - return false - } - - var custodyBit0Indices = [UInt64]() - var custodyBit1Indices = [UInt64]() - - for (i, validatorIndex) in slashableAttestation.validatorIndices.enumerated() { - if getBitfieldBit(bitfield: slashableAttestation.custodyBitfield, i: i) == 0b0 { - custodyBit0Indices.append(validatorIndex) - } else { - custodyBit1Indices.append(validatorIndex) - } - } - - return BLS.verify( - pubkeys: [ - BLS.aggregate( - pubkeys: custodyBit0Indices.map { (i) in - return state.validatorRegistry[Int(i)].pubkey - } - ), - BLS.aggregate( - pubkeys: custodyBit1Indices.map { (i) in - return state.validatorRegistry[Int(i)].pubkey - } - ) - ], - messages: [ - hashTreeRoot(AttestationDataAndCustodyBit(data: slashableAttestation.data, custodyBit: false)), - hashTreeRoot(AttestationDataAndCustodyBit(data: slashableAttestation.data, custodyBit: true)), - ], - signature: slashableAttestation.aggregateSignature, - domain: state.fork.domain(epoch: slashableAttestation.data.slot.toEpoch(), type: .attestation) - ) - } - - static func isDoubleVote(_ left: AttestationData, _ right: AttestationData) -> Bool { - return left.slot.toEpoch() == right.slot.toEpoch() - } - - static func isSurroundVote(_ left: AttestationData, _ right: AttestationData) -> Bool { - return left.justifiedEpoch < right.justifiedEpoch && - right.slot.toEpoch() < left.slot.toEpoch() - } -} - -extension BeaconChain { - - static func getInitialBeaconState( - genesisValidatorDeposits: [Deposit], - genesisTime: UInt64, - latestEth1Data: Eth1Data - ) -> BeaconState { - - var state = genesisState( - genesisTime: genesisTime, - latestEth1Data: latestEth1Data, - depositLength: genesisValidatorDeposits.count - ) - - for deposit in genesisValidatorDeposits { - processDeposit(state: &state, deposit: deposit) - } - - for (i, _) in state.validatorRegistry.enumerated() { - if getEffectiveBalance(state: state, index: ValidatorIndex(i)) >= MAX_DEPOSIT_AMOUNT { - state.validatorRegistry[i].activate(state: state, genesis: true) - } - } - - let genesisActiveIndexRoot = hashTreeRoot(state.validatorRegistry.activeIndices(epoch: GENESIS_EPOCH)) - - for i in 0.. BeaconState { - return BeaconState( - slot: GENESIS_SLOT, - genesisTime: genesisTime, - fork: Fork( - previousVersion: GENESIS_FORK_VERSION, - currentVersion: GENESIS_FORK_VERSION, - epoch: GENESIS_EPOCH - ), - validatorRegistry: [Validator](), - validatorBalances: [UInt64](), - validatorRegistryUpdateEpoch: GENESIS_EPOCH, - latestRandaoMixes: [Data](repeating: EMPTY_SIGNATURE, count: Int(LATEST_RANDAO_MIXES_LENGTH)), - previousShufflingStartShard: GENESIS_START_SHARD, - currentShufflingStartShard: GENESIS_START_SHARD, - previousShufflingEpoch: GENESIS_EPOCH, - currentShufflingEpoch: GENESIS_EPOCH, - previousShufflingSeed: ZERO_HASH, - currentShufflingSeed: ZERO_HASH, - previousJustifiedEpoch: GENESIS_EPOCH, - justifiedEpoch: GENESIS_EPOCH, - justificationBitfield: 0, - finalizedEpoch: GENESIS_EPOCH, - latestCrosslinks: [Crosslink](repeating: Crosslink(epoch: GENESIS_EPOCH, crosslinkDataRoot: ZERO_HASH), count: Int(SHARD_COUNT)), - latestBlockRoots: [Data](repeating: ZERO_HASH, count: Int(LATEST_BLOCK_ROOTS_LENGTH)), - latestActiveIndexRoots: [Data](repeating: ZERO_HASH, count: Int(LATEST_ACTIVE_INDEX_ROOTS_LENGTH)), - latestSlashedBalances: [UInt64](repeating: 0, count: Int(LATEST_SLASHED_EXIT_LENGTH)), - latestAttestations: [PendingAttestation](), - batchedBlockRoots: [Data](), - latestEth1Data: latestEth1Data, - eth1DataVotes: [Eth1DataVote](), - depositIndex: UInt64(depositLength) - ) - } -} - -extension BeaconChain { - - static func processDeposit(state: inout BeaconState, deposit: Deposit) { - let depositInput = deposit.depositData.depositInput - - let proofIsValid = BLS.verify( - pubkey: depositInput.pubkey, - message: BeaconChain.signedRoot(depositInput, field: "proofOfPossession"), - signature: depositInput.proofOfPossession, - domain: state.fork.domain(epoch: BeaconChain.getCurrentEpoch(state: state), type: .deposit) - ) - - if !proofIsValid { - return - } - - let pubkey = depositInput.pubkey - let amount = deposit.depositData.amount - let withdrawalCredentials = depositInput.withdrawalCredentials - - if let index = state.validatorRegistry.firstIndex(where: { $0.pubkey == pubkey }) { - assert(state.validatorRegistry[index].withdrawalCredentials == withdrawalCredentials) - state.validatorBalances[index] += amount - } else { - let validator = Validator( - pubkey: pubkey, - withdrawalCredentials: withdrawalCredentials, - activationEpoch: FAR_FUTURE_EPOCH, - exitEpoch: FAR_FUTURE_EPOCH, - withdrawableEpoch: FAR_FUTURE_EPOCH, - initiatedExit: false, - slashed: false - ) - - state.validatorRegistry.append(validator) - state.validatorBalances.append(amount) - } - } -} - -extension BeaconChain { - - static func slashValidator(state: inout BeaconState, index: ValidatorIndex) { - assert(state.slot < state.validatorRegistry[Int(index)].withdrawableEpoch.startSlot()) - state.validatorRegistry[Int(index)].exit(state: state) - - state.latestSlashedBalances[Int(getCurrentEpoch(state: state) % LATEST_SLASHED_EXIT_LENGTH)] += getEffectiveBalance(state: state, index: index) - - let whistleblowerIndex = getBeaconProposerIndex(state: state, slot: state.slot) - let whistleblowerReward = getEffectiveBalance(state: state, index: index) / WHISTLEBLOWER_REWARD_QUOTIENT - - state.validatorBalances[Int(whistleblowerIndex)] += whistleblowerReward - state.validatorBalances[Int(index)] -= whistleblowerReward - - let currentEpoch = getCurrentEpoch(state: state) - state.validatorRegistry[Int(index)].slashed = true - state.validatorRegistry[Int(index)].withdrawableEpoch = currentEpoch + LATEST_SLASHED_EXIT_LENGTH - } } diff --git a/Sources/BeaconChain/Constants.swift b/Sources/BeaconChain/Constants.swift deleted file mode 100644 index d5a8a0c..0000000 --- a/Sources/BeaconChain/Constants.swift +++ /dev/null @@ -1,60 +0,0 @@ -import Foundation - -// Misc -let SHARD_COUNT = UInt64(2**10) -let TARGET_COMMITTEE_SIZE = UInt64(2**7) -let MAX_BALANCE_CHURN_QUOTIENT = UInt64(2**5) -let BEACON_CHAIN_SHARD_NUMBER = UInt64.max -let MAX_INDICES_PER_SLASHABLE_VOTE = UInt64(2**12) -let MAX_EXIT_DEQUEUES_PER_EPOCH = UInt64(2**2) -let SHUFFLE_ROUND_COUNT = 90 - -// Deposit Contract -//let DEPOSIT_CONTRACT_ADDRESS = -let DEPOSIT_CONTRACT_TREE_DEPTH = UInt64(2**5) - -// GWEI Values -let MIN_DEPOSIT_AMOUNT = UInt64(2**0 * UInt64(1e9)) -let MAX_DEPOSIT_AMOUNT = UInt64(2**5 * UInt64(1e9)) -let FORK_CHOICE_BALANCE_INCREMENT = UInt64(2**0 * UInt64(1e9)) -let EJECTION_BALANCE = UInt64(2**4 * UInt64(1e9)) - -// Initial Values -let GENESIS_FORK_VERSION = UInt64(0) -let GENESIS_SLOT = UInt64(2**32) -let GENESIS_EPOCH = Slot(GENESIS_SLOT).toEpoch() -let GENESIS_START_SHARD = UInt64(0) -let FAR_FUTURE_EPOCH = UInt64.max -let ZERO_HASH = Data(repeating: 0, count: 32) // @todo create type -let EMPTY_SIGNATURE = Data(repeating: 0, count: 96) -let BLS_WITHDRAWAL_PREFIX_BYTE = Data(repeating: 0, count: 1) - -// Time parameters -let SECONDS_PER_SLOT = UInt64(6) -let MIN_ATTESTATION_INCLUSION_DELAY = UInt64(2**2) -let SLOTS_PER_EPOCH = UInt64(2**6) -let MIN_SEED_LOOKAHEAD = UInt64(2**0) -let ACTIVATION_EXIT_DELAY = UInt64(2**2) -let EPOCHS_PER_ETH1_VOTING_PERIOD = UInt64(2**4) -let MIN_VALIDATOR_WITHDRAWABILITY_DELAY = UInt64(2**8) - -// State list lengths -let LATEST_BLOCK_ROOTS_LENGTH = UInt64(2**13) -let LATEST_RANDAO_MIXES_LENGTH = UInt64(2**13) -let LATEST_ACTIVE_INDEX_ROOTS_LENGTH = UInt64(2**13) -let LATEST_SLASHED_EXIT_LENGTH = UInt64(2**13) - -// Reward and penalty quotients -let BASE_REWARD_QUOTIENT = UInt64(2**5) -let WHISTLEBLOWER_REWARD_QUOTIENT = UInt64(2**9) -let ATTESTATION_INCLUSION_REWARD_QUOTIENT = UInt64(2**3) -let INACTIVITY_PENALTY_QUOTIENT = UInt64(2**24) -let MIN_PENALTY_QUOTIENT = UInt64(2**5) - -// Max transactions per block -let MAX_PROPOSER_SLASHINGS = UInt64(2**4) -let MAX_ATTESTER_SLASHINGS = UInt64(2**0) -let MAX_ATTESTATIONS = UInt64(2**7) -let MAX_DEPOSITS = UInt64(2**4) -let MAX_VOLUNTARY_EXITS = UInt64(2**4) -let MAX_TRANSFERS = UInt64(2**4) diff --git a/Sources/BeaconChain/DataStructures/Blocks/BeaconBlock.swift b/Sources/BeaconChain/DataStructures/Blocks/BeaconBlock.swift deleted file mode 100644 index 01903cc..0000000 --- a/Sources/BeaconChain/DataStructures/Blocks/BeaconBlock.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public struct BeaconBlock: Equatable { - let slot: UInt64 - let parentRoot: Data - let stateRoot: Data - let randaoReveal: Data - let eth1Data: Eth1Data - let body: BeaconBlockBody - var signature: Data -} diff --git a/Sources/BeaconChain/DataStructures/Blocks/BeaconBlockBody.swift b/Sources/BeaconChain/DataStructures/Blocks/BeaconBlockBody.swift deleted file mode 100644 index 2936799..0000000 --- a/Sources/BeaconChain/DataStructures/Blocks/BeaconBlockBody.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation - -struct BeaconBlockBody: Equatable { - let proposerSlashings: [ProposerSlashing] - let attesterSlashings: [AttesterSlashing] - let attestations: [Attestation] - let deposits: [Deposit] - let voluntaryExits: [VoluntaryExit] - let transfers: [Transfer] -} diff --git a/Sources/BeaconChain/DataStructures/Blocks/ProposalSignedData.swift b/Sources/BeaconChain/DataStructures/Blocks/ProposalSignedData.swift deleted file mode 100644 index 56f1c31..0000000 --- a/Sources/BeaconChain/DataStructures/Blocks/ProposalSignedData.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -struct Proposal: Equatable { - let slot: UInt64 - let shard: UInt64 - let blockRoot: Data - let signature: Data -} diff --git a/Sources/BeaconChain/DataStructures/State/BeaconState.swift b/Sources/BeaconChain/DataStructures/State/BeaconState.swift deleted file mode 100644 index 1a36ae7..0000000 --- a/Sources/BeaconChain/DataStructures/State/BeaconState.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Foundation - -struct BeaconState { - var slot: UInt64 - let genesisTime: UInt64 - let fork: Fork - - var validatorRegistry: [Validator] - var validatorBalances: [UInt64] - var validatorRegistryUpdateEpoch: UInt64 - - var latestRandaoMixes: [Data] - var previousShufflingStartShard: UInt64 - let currentShufflingStartShard: UInt64 - var previousShufflingEpoch: UInt64 - var currentShufflingEpoch: UInt64 - var previousShufflingSeed: Data - var currentShufflingSeed: Data - - var previousJustifiedEpoch: UInt64 - var justifiedEpoch: UInt64 - var justificationBitfield: UInt64 - var finalizedEpoch: UInt64 - - var latestCrosslinks: [Crosslink] - var latestBlockRoots: [Data] - var latestActiveIndexRoots: [Data] - var latestSlashedBalances: [UInt64] - var latestAttestations: [PendingAttestation] - var batchedBlockRoots: [Data] - - var latestEth1Data: Eth1Data - var eth1DataVotes: [Eth1DataVote] - var depositIndex: UInt64 -} diff --git a/Sources/BeaconChain/DataStructures/State/Crosslink.swift b/Sources/BeaconChain/DataStructures/State/Crosslink.swift deleted file mode 100644 index d9f0e81..0000000 --- a/Sources/BeaconChain/DataStructures/State/Crosslink.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -struct Crosslink: Equatable { - let epoch: UInt64 - let crosslinkDataRoot: Data -} diff --git a/Sources/BeaconChain/DataStructures/State/Eth1Data.swift b/Sources/BeaconChain/DataStructures/State/Eth1Data.swift deleted file mode 100644 index 7fc1993..0000000 --- a/Sources/BeaconChain/DataStructures/State/Eth1Data.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -struct Eth1Data: Equatable { - let depositRoot: Data - let blockHash: Data -} diff --git a/Sources/BeaconChain/DataStructures/State/Eth1DataVote.swift b/Sources/BeaconChain/DataStructures/State/Eth1DataVote.swift deleted file mode 100644 index 74d3dd8..0000000 --- a/Sources/BeaconChain/DataStructures/State/Eth1DataVote.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -struct Eth1DataVote { - let eth1Data: Eth1Data - var voteCount: UInt64 -} diff --git a/Sources/BeaconChain/DataStructures/State/Fork.swift b/Sources/BeaconChain/DataStructures/State/Fork.swift deleted file mode 100644 index 1f18384..0000000 --- a/Sources/BeaconChain/DataStructures/State/Fork.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -struct Fork { - let previousVersion: UInt64 - let currentVersion: UInt64 - let epoch: UInt64 - - func version(epoch: Epoch) -> UInt64 { - if epoch < self.epoch { - return previousVersion - } - - return currentVersion - } - - func domain(epoch: Epoch, type: Domain) -> UInt64 { - return version(epoch: epoch) * 2 ** 32 + type.rawValue - } -} diff --git a/Sources/BeaconChain/DataStructures/State/PendingAttestation.swift b/Sources/BeaconChain/DataStructures/State/PendingAttestation.swift deleted file mode 100644 index 2aec5c5..0000000 --- a/Sources/BeaconChain/DataStructures/State/PendingAttestation.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -struct PendingAttestation { - let aggregationBitfield: Data - let data: AttestationData - let custodyBitfield: Data - let inclusionSlot: UInt64 -} diff --git a/Sources/BeaconChain/DataStructures/State/Validator.swift b/Sources/BeaconChain/DataStructures/State/Validator.swift deleted file mode 100644 index ce22f4b..0000000 --- a/Sources/BeaconChain/DataStructures/State/Validator.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation - -struct Validator { - let pubkey: Data - let withdrawalCredentials: Data - 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 - } -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Attestations/Attestation.swift b/Sources/BeaconChain/DataStructures/Transactions/Attestations/Attestation.swift deleted file mode 100644 index 3ddf7ac..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Attestations/Attestation.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public struct Attestation: Equatable { - let aggregationBitfield: Data - let data: AttestationData - let custodyBitfield: Data - let aggregateSignature: Data -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationData.swift b/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationData.swift deleted file mode 100644 index c749f31..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationData.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -struct AttestationData: Equatable { - let slot: Slot - let shard: UInt64 - let beaconBlockRoot: Data - let epochBoundaryRoot: Data - let crosslinkDataRoot: Data - let latestCrosslink: Crosslink - let justifiedEpoch: Epoch - let justifiedBlockRoot: Data -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationDataAndCustodyBit.swift b/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationDataAndCustodyBit.swift deleted file mode 100644 index ce72d23..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Attestations/AttestationDataAndCustodyBit.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -struct AttestationDataAndCustodyBit { - let data: AttestationData - let custodyBit: Bool -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/AttesterSlashing.swift b/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/AttesterSlashing.swift deleted file mode 100644 index 0960a6f..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/AttesterSlashing.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -struct AttesterSlashing: Equatable { - let slashableAttestation1: SlashableAttestation - let slashableAttestation2: SlashableAttestation -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/SlashableAttestation.swift b/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/SlashableAttestation.swift deleted file mode 100644 index ccca11a..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/AttesterSlashings/SlashableAttestation.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -struct SlashableAttestation: Equatable { - let validatorIndices: [UInt64] - let data: AttestationData - let custodyBitfield: Data - let aggregateSignature: Data -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Deposits/Deposit.swift b/Sources/BeaconChain/DataStructures/Transactions/Deposits/Deposit.swift deleted file mode 100644 index 140d64c..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Deposits/Deposit.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct Deposit: Equatable { - let branch: [Data] - let index: UInt64 - let depositData: DepositData -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositData.swift b/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositData.swift deleted file mode 100644 index 55b2b73..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositData.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct DepositData: Equatable { - let amount: UInt64 - let timestamp: UInt64 - let depositInput: DepositInput -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositInput.swift b/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositInput.swift deleted file mode 100644 index 1fbcc05..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Deposits/DepositInput.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct DepositInput: Equatable { - let pubkey: Data - let withdrawalCredentials: Data - let proofOfPossession: Data -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/ProposerSlashing.swift b/Sources/BeaconChain/DataStructures/Transactions/ProposerSlashing.swift deleted file mode 100644 index b3ef745..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/ProposerSlashing.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct ProposerSlashing: Equatable { - let proposerIndex: UInt64 - let proposal1: Proposal - let proposal2: Proposal -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/Transfer.swift b/Sources/BeaconChain/DataStructures/Transactions/Transfer.swift deleted file mode 100644 index 5dcede7..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/Transfer.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -struct Transfer: Equatable { - let from: UInt64 - let to: UInt64 - let amount: UInt64 - let fee: UInt64 - let slot: UInt64 - let pubkey: Data - let signature: Data -} diff --git a/Sources/BeaconChain/DataStructures/Transactions/VoluntaryExit.swift b/Sources/BeaconChain/DataStructures/Transactions/VoluntaryExit.swift deleted file mode 100644 index afea8bd..0000000 --- a/Sources/BeaconChain/DataStructures/Transactions/VoluntaryExit.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct VoluntaryExit: Equatable { - let epoch: UInt64 - let validatorIndex: UInt64 - let signature: Data -} diff --git a/Sources/BeaconChain/Enums/Domain.swift b/Sources/BeaconChain/Enums/Domain.swift deleted file mode 100644 index 7a0fa95..0000000 --- a/Sources/BeaconChain/Enums/Domain.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation - -enum Domain: UInt64 { - case deposit - case attestation - case proposal - case exit - case randao - case transfer -} diff --git a/Sources/BeaconChain/Extensions/Array+AttestationTarget.swift b/Sources/BeaconChain/Extensions/Array+AttestationTarget.swift deleted file mode 100644 index 577446d..0000000 --- a/Sources/BeaconChain/Extensions/Array+AttestationTarget.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -extension Array where Element == AttestationTarget { - - func votes(store: Store, state: BeaconState, block: BeaconBlock) -> UInt64 { - return compactMap { - (index, target) in - - guard store.ancestor(block: target, slot: target.slot) == block else { - return nil - } - - return BeaconChain.getEffectiveBalance(state: state, index: index) / FORK_CHOICE_BALANCE_INCREMENT - } - .reduce(0, +) - } -} diff --git a/Sources/BeaconChain/Extensions/Array+Validator.swift b/Sources/BeaconChain/Extensions/Array+Validator.swift deleted file mode 100644 index c27c903..0000000 --- a/Sources/BeaconChain/Extensions/Array+Validator.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -extension Array where Element == Validator { - - func activeIndices(epoch: Epoch) -> [ValidatorIndex] { - return enumerated().compactMap { - (k, v) in - if v.isActive(epoch: epoch) { - return ValidatorIndex(k) - } - - return nil - } - } -} diff --git a/Sources/BeaconChain/Extensions/Array+ValidatorIndex.swift b/Sources/BeaconChain/Extensions/Array+ValidatorIndex.swift deleted file mode 100644 index f196d39..0000000 --- a/Sources/BeaconChain/Extensions/Array+ValidatorIndex.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -extension Array where Element == ValidatorIndex { - - func totalBalance(state: BeaconState) -> Gwei { - return map { BeaconChain.getEffectiveBalance(state: state, index: $0) }.reduce(0, +) - } -} diff --git a/Sources/BeaconChain/Extensions/Array.swift b/Sources/BeaconChain/Extensions/Array.swift deleted file mode 100644 index 4b7af6f..0000000 --- a/Sources/BeaconChain/Extensions/Array.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -extension Array { - - func split(count: Int) -> [[Element]] { - let length = self.count - - return (0.. Data { - var temp = left - - for i in 0.. Bool { - for i in 0...left.count { - if left[i] > right[i] { - return false - } - } - - return true - } -} diff --git a/Sources/BeaconChain/Extensions/Epoch.swift b/Sources/BeaconChain/Extensions/Epoch.swift deleted file mode 100644 index 2d917f0..0000000 --- a/Sources/BeaconChain/Extensions/Epoch.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -extension Epoch { - - func startSlot() -> Slot { - return self * SLOTS_PER_EPOCH - } - - func delayedActivationExitEpoch() -> Epoch { - return self + 1 + ACTIVATION_EXIT_DELAY - } -} diff --git a/Sources/BeaconChain/Extensions/Int.swift b/Sources/BeaconChain/Extensions/Int.swift deleted file mode 100644 index a8f20d1..0000000 --- a/Sources/BeaconChain/Extensions/Int.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -extension Int { - - func isPowerOfTwo() -> Bool { - return (self > 0) && (self & (self - 1) == 0) - } -} diff --git a/Sources/BeaconChain/Extensions/Numeric.swift b/Sources/BeaconChain/Extensions/Numeric.swift deleted file mode 100644 index d5a9adb..0000000 --- a/Sources/BeaconChain/Extensions/Numeric.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -extension Numeric { - - // @todo kinda ugly? - var bytes32: Data { - var source = self - - return Data(bytes: &source, count: 32) - } -} diff --git a/Sources/BeaconChain/Extensions/Slot.swift b/Sources/BeaconChain/Extensions/Slot.swift deleted file mode 100644 index 77179c6..0000000 --- a/Sources/BeaconChain/Extensions/Slot.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -extension Slot { - - func toEpoch() -> Epoch { - return self / SLOTS_PER_EPOCH - } -} diff --git a/Sources/BeaconChain/Extensions/UInt64.swift b/Sources/BeaconChain/Extensions/UInt64.swift deleted file mode 100644 index 2d8cfc4..0000000 --- a/Sources/BeaconChain/Extensions/UInt64.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -extension UInt64 { - - func sqrt() -> UInt64 { - assert(self >= 0) - - var x = self - var y = (x + 1) / 2 - - while y < x { - x = y - y = (x + self / x) / 2 - } - - return x - } - -} diff --git a/Sources/BeaconChain/ForkChoice/ForkChoice.swift b/Sources/BeaconChain/ForkChoice/ForkChoice.swift deleted file mode 100644 index a7f50c0..0000000 --- a/Sources/BeaconChain/ForkChoice/ForkChoice.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -protocol ForkChoice { - - func execute(store: Store, startState: BeaconState, startBlock: BeaconBlock) -> BeaconBlock - -} diff --git a/Sources/BeaconChain/ForkChoice/LMDGhost.swift b/Sources/BeaconChain/ForkChoice/LMDGhost.swift deleted file mode 100644 index 691fa2c..0000000 --- a/Sources/BeaconChain/ForkChoice/LMDGhost.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation - -class LMDGhost: ForkChoice { - - func execute(store: Store, startState: BeaconState, startBlock: BeaconBlock) -> BeaconBlock { - let targets = startState.validatorRegistry.activeIndices(epoch: startState.slot.toEpoch()).map { - ($0, store.latestAttestationTarget(validator: $0)) - } - - var head = startBlock - while true { - let children = store.children(head) - if children.count == 0 { - return head - } - - head = children.max { - targets.votes(store: store, state: startState, block: $0) < targets.votes(store: store, state: startState, block: $1) - }! - } - } -} diff --git a/Sources/BeaconChain/Operators/Power.swift b/Sources/BeaconChain/Operators/Power.swift deleted file mode 100644 index 3ddb25e..0000000 --- a/Sources/BeaconChain/Operators/Power.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Foundation - -precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } -infix operator ** : PowerPrecedence - -extension UInt64 { - - static func ** (radix: UInt64, power: UInt64) -> UInt64 { - return UInt64(pow(Double(radix), Double(power))) - } -} - -extension Int { - - static func ** (radix: Int, power: Int) -> Int { - return Int(pow(Double(radix), Double(power))) - } -} diff --git a/Sources/BeaconChain/StateTransition.swift b/Sources/BeaconChain/StateTransition.swift deleted file mode 100644 index 16587eb..0000000 --- a/Sources/BeaconChain/StateTransition.swift +++ /dev/null @@ -1,968 +0,0 @@ -import Foundation - -// @todo refactor so this isn't all in one class - -class StateTransition { - - static func processSlot(state: inout BeaconState, previousBlockRoot: Data) { - state.slot += 1 - state.latestBlockRoots[Int((state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH)] = previousBlockRoot - - if state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0 { - state.batchedBlockRoots.append(BeaconChain.merkleRoot(values: state.latestBlockRoots)) - } - } -} - -extension StateTransition { - - static func processBlock(state: inout BeaconState, block: BeaconBlock) { - assert(state.slot == block.slot) - - blockSignature(state: &state, block: block) - randao(state: &state, block: block) - eth1data(state: &state, block: block) - proposerSlashings(state: &state, block: block) - attesterSlashings(state: &state, block: block) - attestations(state: &state, block: block) - deposits(state: &state, block: block) - voluntaryExits(state: &state, block: block) - } - - static func blockSignature(state: inout BeaconState, block: BeaconBlock) { - let proposer = state.validatorRegistry[Int(BeaconChain.getBeaconProposerIndex(state: state, slot: state.slot))] - let proposal = Proposal( - slot: block.slot, - shard: BEACON_CHAIN_SHARD_NUMBER, - blockRoot: BeaconChain.signedRoot(block, field: "signature"), - signature: block.signature - ) - - assert( - BLS.verify( - pubkey: proposer.pubkey, - message: BeaconChain.signedRoot(proposal, field: "signature"), - signature: proposal.signature, - domain: state.fork.domain(epoch: BeaconChain.getCurrentEpoch(state: state), type: .proposal) - ) - ) - } - - static func randao(state: inout BeaconState, block: BeaconBlock) { - let proposer = state.validatorRegistry[Int(BeaconChain.getBeaconProposerIndex(state: state, slot: state.slot))] - - var epoch = BeaconChain.getCurrentEpoch(state: state) - assert( - BLS.verify( - pubkey: proposer.pubkey, - message: Data(bytes: &epoch, count: 32), - signature: block.randaoReveal, - domain: state.fork.domain(epoch: BeaconChain.getCurrentEpoch(state: state), type: .randao) - ) - ) - - state.latestRandaoMixes[Int(BeaconChain.getCurrentEpoch(state: state) % LATEST_RANDAO_MIXES_LENGTH)] = BeaconChain.getRandaoMix(state: state, epoch: BeaconChain.getCurrentEpoch(state: state)) ^ BeaconChain.hash(block.randaoReveal) - } - - static func eth1data(state: inout BeaconState, block: BeaconBlock) { - for (i, vote) in state.eth1DataVotes.enumerated() { - if vote.eth1Data == block.eth1Data { - state.eth1DataVotes[i].voteCount += 1 - continue - } - - state.eth1DataVotes.append(Eth1DataVote(eth1Data: block.eth1Data, voteCount: 1)) - } - } - - static func proposerSlashings(state: inout BeaconState, block: BeaconBlock) { - assert(block.body.proposerSlashings.count <= MAX_PROPOSER_SLASHINGS) - - for proposerSlashing in block.body.proposerSlashings { - let proposer = state.validatorRegistry[Int(proposerSlashing.proposerIndex)] - // @todo none of these should be asserts - assert(proposerSlashing.proposal1.slot == proposerSlashing.proposal2.slot) - assert(proposerSlashing.proposal1.shard == proposerSlashing.proposal2.shard) - assert(proposerSlashing.proposal1.blockRoot != proposerSlashing.proposal2.blockRoot) - assert(!proposer.slashed) - - assert( - BLS.verify( - pubkey: proposer.pubkey, - message: BeaconChain.signedRoot(proposerSlashing.proposal1, field: "signature"), - signature: proposerSlashing.proposal1.signature, - domain: state.fork.domain(epoch: proposerSlashing.proposal1.slot.toEpoch(), type: .proposal) - ) - ) - - assert( - BLS.verify( - pubkey: proposer.pubkey, - message: BeaconChain.signedRoot(proposerSlashing.proposal2, field: "signature"), - signature: proposerSlashing.proposal2.signature, - domain: state.fork.domain(epoch: proposerSlashing.proposal2.slot.toEpoch(), type: .proposal) - ) - ) - - BeaconChain.slashValidator(state: &state, index: proposerSlashing.proposerIndex) - } - } - - static func attesterSlashings(state: inout BeaconState, block: BeaconBlock) { - assert(block.body.attesterSlashings.count <= MAX_ATTESTER_SLASHINGS) - - for attesterSlashing in block.body.attesterSlashings { - let slashableAttestation1 = attesterSlashing.slashableAttestation1 - let slashableAttestation2 = attesterSlashing.slashableAttestation2 - - assert(slashableAttestation1.data != slashableAttestation2.data) - assert( - BeaconChain.isDoubleVote(slashableAttestation1.data, slashableAttestation2.data) - || BeaconChain.isSurroundVote(slashableAttestation1.data, slashableAttestation2.data) - ) - - assert(BeaconChain.verifySlashableAttestation(state: state, slashableAttestation: slashableAttestation1)) - assert(BeaconChain.verifySlashableAttestation(state: state, slashableAttestation: slashableAttestation2)) - - let slashableIndices = slashableAttestation1.validatorIndices.filter { - slashableAttestation2.validatorIndices.contains($0) - && state.validatorRegistry[Int($0)].slashed == false - } - - assert(slashableIndices.count >= 1) - - for i in slashableIndices { - BeaconChain.slashValidator(state: &state, index: i) - } - } - } - - static func attestations(state: inout BeaconState, block: BeaconBlock) { - assert(block.body.attestations.count <= MAX_ATTESTATIONS) - - for attestation in block.body.attestations { - assert(attestation.data.slot >= GENESIS_SLOT) - assert(attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot) - assert(state.slot < attestation.data.slot + SLOTS_PER_EPOCH) - - let e = (attestation.data.slot + 1).toEpoch() >= BeaconChain.getCurrentEpoch(state: state) ? state.justifiedEpoch : state.previousJustifiedEpoch - assert(attestation.data.justifiedEpoch == e) - assert(attestation.data.justifiedBlockRoot == BeaconChain.getBlockRoot(state: state, slot: attestation.data.justifiedEpoch.startSlot())) - - assert( - state.latestCrosslinks[Int(attestation.data.shard)] == attestation.data.latestCrosslink || - state.latestCrosslinks[Int(attestation.data.shard)] == Crosslink( - epoch: attestation.data.slot.toEpoch(), - crosslinkDataRoot: attestation.data.crosslinkDataRoot - ) - ) - - assert(attestation.custodyBitfield == Data(repeating: 0, count: 32)) - assert(attestation.aggregationBitfield != Data(repeating: 0, count: 32)) - - let crosslinkCommittee = BeaconChain.crosslinkCommittees(state, at: attestation.data.slot).filter { - $0.1 == attestation.data.shard - }.first?.0 - - for i in 0.. epoch.delayedActivationExitEpoch()) - assert(epoch >= exit.epoch) - - assert( - BLS.verify( - pubkey: validator.pubkey, - message: BeaconChain.signedRoot(exit, field: "signature"), - signature: exit.signature, - domain: state.fork.domain(epoch: exit.epoch, type: .exit) - ) - ) - - state.validatorRegistry[Int(exit.validatorIndex)].initiatedExit = true - } - } - - static func transfers(state: inout BeaconState, block: BeaconBlock) { - assert(block.body.transfers.count <= MAX_TRANSFERS) - - for transfer in block.body.transfers { - assert(state.validatorBalances[Int(transfer.from)] >= transfer.amount) - assert(state.validatorBalances[Int(transfer.from)] >= transfer.fee) - assert( - state.validatorBalances[Int(transfer.from)] == transfer.amount + transfer.fee - || state.validatorBalances[Int(transfer.from)] >= transfer.amount + transfer.fee + MIN_DEPOSIT_AMOUNT - ) - - assert(state.slot == transfer.slot) - assert( - BeaconChain.getCurrentEpoch(state: state) >= state.validatorRegistry[Int(transfer.from)].withdrawableEpoch - || state.validatorRegistry[Int(transfer.from)].activationEpoch == FAR_FUTURE_EPOCH - ) - assert(state.validatorRegistry[Int(transfer.from)].withdrawalCredentials == BLS_WITHDRAWAL_PREFIX_BYTE + BeaconChain.hash(transfer.pubkey).suffix(from: 1)) - - assert( - BLS.verify( - pubkey: transfer.pubkey, - message: BeaconChain.signedRoot(transfer, field: "signature"), - signature: transfer.signature, - domain: state.fork.domain(epoch: transfer.slot.toEpoch(), type: .transfer) - ) - ) - - state.validatorBalances[Int(transfer.from)] -= transfer.amount + transfer.fee - state.validatorBalances[Int(transfer.to)] += transfer.amount - state.validatorBalances[Int(BeaconChain.getBeaconProposerIndex(state: state, slot: state.slot))] += transfer.fee - } - } - - static func verifyMerkleBranch(leaf: Bytes32, branch: [Bytes32], depth: Int, index: Int, root: Bytes32) -> Bool { - var value = leaf - for i in 0.. state.validatorRegistryUpdateEpoch && shards.count == 0 { - updateValidatorRegistry(state: &state) - } else { - let epochsSinceLastRegistryUpdate = currentEpoch - state.validatorRegistryUpdateEpoch - if epochsSinceLastRegistryUpdate > 1 && Int(epochsSinceLastRegistryUpdate).isPowerOfTwo() { - state.currentShufflingEpoch = nextEpoch - state.currentShufflingSeed = BeaconChain.generateSeed(state: state, epoch: state.currentShufflingEpoch) - } - } - - processSlashing(state: &state) - processExitQueue(state: &state) - - state.latestActiveIndexRoots[Int((nextEpoch % ACTIVATION_EXIT_DELAY) % LATEST_ACTIVE_INDEX_ROOTS_LENGTH)] = BeaconChain.hashTreeRoot( - state.validatorRegistry.activeIndices(epoch: nextEpoch + ACTIVATION_EXIT_DELAY) - ) - - state.latestSlashedBalances[Int(nextEpoch % LATEST_SLASHED_EXIT_LENGTH)] = state.latestSlashedBalances[Int(currentEpoch % LATEST_SLASHED_EXIT_LENGTH)] - state.latestRandaoMixes[Int(nextEpoch % LATEST_RANDAO_MIXES_LENGTH)] = BeaconChain.getRandaoMix( - state: state, - epoch: currentEpoch - ) - - // @todo check this - // Remove any attestation in state.latest_attestations such that slot_to_epoch(attestation.data.slot) < current_epoch. - state.latestAttestations.removeAll { - $0.data.slot.toEpoch() >= currentEpoch - } - } - - private static func eth1data(state: inout BeaconState, nextEpoch: Epoch) { - if nextEpoch % EPOCHS_PER_ETH1_VOTING_PERIOD != 0 { - return - } - - for vote in state.eth1DataVotes { - if vote.voteCount * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH { - state.latestEth1Data = vote.eth1Data - } - } - - state.eth1DataVotes = [Eth1DataVote]() - } - - private static func justification( - state: inout BeaconState, - previousEpoch: Epoch, - currentEpoch: Epoch, - previousTotalBalance: Gwei, - previousEpochBoundaryAttestingBalance: Gwei, - currentTotalBalance: Gwei, - currentEpochBoundaryAttestingBalance: Gwei - ) { - var newJustifiedEpoch = state.justifiedEpoch - state.justificationBitfield = state.justificationBitfield << 1 - - if 3 * previousEpochBoundaryAttestingBalance >= 2 * previousTotalBalance { - state.justificationBitfield |= 2 - newJustifiedEpoch = previousEpoch - } - - if 3 * currentEpochBoundaryAttestingBalance >= 2 * currentTotalBalance { - state.justificationBitfield |= 1 - newJustifiedEpoch = currentEpoch - } - - if (state.justificationBitfield >> 1) % 8 == 0b111 && state.previousJustifiedEpoch == previousEpoch - 2 { - state.finalizedEpoch = state.previousJustifiedEpoch - } - - if (state.justificationBitfield >> 1) % 4 == 0b11 && state.previousJustifiedEpoch == previousEpoch - 1 { - state.finalizedEpoch = state.previousJustifiedEpoch - } - - if (state.justificationBitfield >> 0) % 8 == 0b111 && state.justifiedEpoch == previousEpoch - 1 { - state.finalizedEpoch = state.justifiedEpoch - } - - if (state.justificationBitfield >> 0) % 4 == 0b11 && state.justifiedEpoch == previousEpoch { - state.finalizedEpoch = state.justifiedEpoch - } - - state.previousJustifiedEpoch = state.justifiedEpoch - state.justifiedEpoch = newJustifiedEpoch - } - - private static func crosslink( - state: inout BeaconState, - previousEpoch: Epoch, - currentEpoch: Epoch, - nextEpoch: Epoch, - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) { - - for slot in previousEpoch.startSlot()..= 2 * crosslinkCommittee.totalBalance(state: state) { - state.latestCrosslinks[Int(shard)] = Crosslink( - epoch: slot.toEpoch(), - crosslinkDataRoot: winningRoot( - state: state, - committee: crosslinkCommittee, - shard: shard, - currentEpochAttestations: currentEpochAttestations, - previousEpochAttestations: previousEpochAttestations - ) - ) - } - } - } - } - - private static func rewardsAndPenalties( - state: inout BeaconState, - previousEpoch: Epoch, - currentEpoch: Epoch, - nextEpoch: Epoch, - previousTotalBalance: Gwei, - totalBalance: UInt64, - previousEpochAttestingBalance: UInt64, - previousEpochBoundaryAttesterIndices: [ValidatorIndex], - previousEpochBoundaryAttestingBalance: UInt64, - previousEpochHeadAttesterIndices: [ValidatorIndex], - previousEpochHeadAttestingBalance: UInt64, - previousEpochAttesterIndices: [ValidatorIndex], - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) { - let baseRewardQuotient = previousTotalBalance.sqrt() / BASE_REWARD_QUOTIENT - - let epochsSinceFinality = nextEpoch - state.finalizedEpoch - - let activeValidators = Set(state.validatorRegistry.activeIndices(epoch: currentEpoch)) - - if epochsSinceFinality <= 4 { - - expectedFFGSource( - state: &state, - previousEpochAttesterIndices: previousEpochAttesterIndices, - activeValidators: activeValidators, - previousEpochAttestingBalance: previousEpochAttestingBalance, - baseRewardQuotient: baseRewardQuotient, - totalBalance: previousTotalBalance - ) - - expectedFFGTarget( - state: &state, - previousEpochBoundaryAttesterIndices: previousEpochBoundaryAttesterIndices, - activeValidators: activeValidators, - previousEpochBoundaryAttestingBalance: previousEpochBoundaryAttestingBalance, - baseRewardQuotient: baseRewardQuotient, - totalBalance: previousTotalBalance - ) - - expectedBeaconChainHead( - state: &state, - previousEpochHeadAttesterIndices: previousEpochHeadAttesterIndices, - activeValidators: activeValidators, - previousEpochHeadAttestingBalance: previousEpochHeadAttestingBalance, - baseRewardQuotient: baseRewardQuotient, - totalBalance: previousTotalBalance - ) - - for index in previousEpochAttesterIndices { - state.validatorBalances[Int(index)] += baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) + MIN_ATTESTATION_INCLUSION_DELAY / inclusionDistance(state: state, index: index) - } - - } else { - deductInactivityBalance( - state: &state, - activeValidators: activeValidators, - excluding: previousEpochAttesterIndices, - epochsSinceFinality: epochsSinceFinality, - baseRewardQuotient: baseRewardQuotient - ) - - deductInactivityBalance( - state: &state, - activeValidators: activeValidators, - excluding: previousEpochBoundaryAttesterIndices, - epochsSinceFinality: epochsSinceFinality, - baseRewardQuotient: baseRewardQuotient - ) - - activeValidators.subtracting(Set(previousEpochHeadAttesterIndices)).forEach({ - (index) in - state.validatorBalances[Int(index)] -= baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - }) - - activeValidators.forEach({ - index in - if state.validatorRegistry[Int(index)].slashed { - state.validatorBalances[Int(index)] -= 2 * inactivityPenalty(state: state, index: index, epochsSinceFinality: epochsSinceFinality, baseRewardQuotient: baseRewardQuotient) + baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - } - }) - - for index in previousEpochAttesterIndices { - let base = baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - state.validatorBalances[Int(index)] -= base - base * MIN_ATTESTATION_INCLUSION_DELAY / inclusionDistance(state: state, index: index) - } - } - - for index in previousEpochAttesterIndices { - let proposer = BeaconChain.getBeaconProposerIndex( - state: state, - slot: inclusionSlot(state: state, index: Int(index)) - ) - state.validatorBalances[Int(proposer)] += baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) / ATTESTATION_INCLUSION_REWARD_QUOTIENT - } - - for slot in previousEpoch.startSlot()..= validator.exitEpoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY - } - } - - eligibleIndices.sort { - state.validatorRegistry[$0].exitEpoch > state.validatorRegistry[$1].exitEpoch - } - - for (dequeues, i) in eligibleIndices.enumerated() { - if dequeues >= MAX_EXIT_DEQUEUES_PER_EPOCH { - break - } - - state.validatorRegistry[i].prepareForWithdrawal(state: state) - } - } - - static func updateValidatorRegistry(state: inout BeaconState) { - let currentEpoch = BeaconChain.getCurrentEpoch(state: state) - let activeValidatorIndices = state.validatorRegistry.activeIndices(epoch: currentEpoch) - - let totalBalance = activeValidatorIndices.totalBalance(state: state) - let maxBalanceChurn = max(MAX_DEPOSIT_AMOUNT, totalBalance / (2 * MAX_BALANCE_CHURN_QUOTIENT)) - - var balanceChurn = UInt64(0) - for (i, v) in state.validatorRegistry.enumerated() { - if v.activationEpoch == FAR_FUTURE_EPOCH && state.validatorBalances[Int(i)] >= MAX_DEPOSIT_AMOUNT { - balanceChurn += BeaconChain.getEffectiveBalance(state: state, index: ValidatorIndex(i)) - if balanceChurn > maxBalanceChurn { - break - } - - state.validatorRegistry[i].activate(state: state, genesis: false) - } - } - - balanceChurn = 0 - for (i, v) in state.validatorRegistry.enumerated() { - if v.activationEpoch == FAR_FUTURE_EPOCH && v.initiatedExit { - balanceChurn += BeaconChain.getEffectiveBalance(state: state, index: ValidatorIndex(i)) - if balanceChurn > maxBalanceChurn { - break - } - - state.validatorRegistry[i].exit(state: state) - } - } - - state.validatorRegistryUpdateEpoch = currentEpoch - } - - static func shufflingSeedData(state: inout BeaconState, nextEpoch: Epoch) { - state.previousShufflingEpoch = state.currentShufflingEpoch - state.previousShufflingSeed = state.currentShufflingSeed - state.previousShufflingStartShard = state.currentShufflingStartShard - } - - static func processEjections(state: inout BeaconState) { - for i in state.validatorRegistry.activeIndices(epoch: BeaconChain.getCurrentEpoch(state: state)) { - if state.validatorBalances[Int(i)] < EJECTION_BALANCE { - state.validatorRegistry[Int(i)].exit(state: state) - } - } - } - - static func deductInactivityBalance( - state: inout BeaconState, - activeValidators: Set, - excluding: [ValidatorIndex], - epochsSinceFinality: UInt64, - baseRewardQuotient: UInt64 - ) { - activeValidators.subtracting(Set(excluding)).forEach { - state.validatorBalances[Int($0)] -= inactivityPenalty(state: state, index: $0, epochsSinceFinality: epochsSinceFinality, baseRewardQuotient: baseRewardQuotient) - } - } - - static func expectedFFGSource( - state: inout BeaconState, - previousEpochAttesterIndices: [ValidatorIndex], - activeValidators: Set, - previousEpochAttestingBalance: UInt64, - baseRewardQuotient: UInt64, - totalBalance: UInt64 - ) { - for index in previousEpochAttesterIndices { - state.validatorBalances[Int(index)] += baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) * previousEpochAttestingBalance / totalBalance - } - - activeValidators.subtracting(Set(previousEpochAttesterIndices)).forEach({ - (index) in - state.validatorBalances[Int(index)] -= baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - }) - } - - static func expectedFFGTarget( - state: inout BeaconState, - previousEpochBoundaryAttesterIndices: [ValidatorIndex], - activeValidators: Set, - previousEpochBoundaryAttestingBalance: UInt64, - baseRewardQuotient: UInt64, - totalBalance: UInt64 - ) { - for index in previousEpochBoundaryAttesterIndices { - state.validatorBalances[Int(index)] += baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) * previousEpochBoundaryAttestingBalance / totalBalance - } - - activeValidators.subtracting(Set(previousEpochBoundaryAttesterIndices)).forEach({ - (index) in - state.validatorBalances[Int(index)] -= baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - }) - } - - static func expectedBeaconChainHead( - state: inout BeaconState, - previousEpochHeadAttesterIndices: [ValidatorIndex], - activeValidators: Set, - previousEpochHeadAttestingBalance: UInt64, - baseRewardQuotient: UInt64, - totalBalance: UInt64 - ) { - for index in previousEpochHeadAttesterIndices { - state.validatorBalances[Int(index)] += baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) * previousEpochHeadAttestingBalance / totalBalance - } - - activeValidators.subtracting(Set(previousEpochHeadAttesterIndices)).forEach({ - (index) in - state.validatorBalances[Int(index)] -= baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) - }) - } - - private static func baseReward(state: BeaconState, index: ValidatorIndex, baseRewardQuotient: UInt64) -> UInt64 { - return BeaconChain.getEffectiveBalance(state: state, index: index) / baseRewardQuotient / 5 - } - - private static func inactivityPenalty( - state: BeaconState, - index: ValidatorIndex, - epochsSinceFinality: UInt64, - baseRewardQuotient: UInt64 - ) -> UInt64 { - return baseReward(state: state, index: index, baseRewardQuotient: baseRewardQuotient) + BeaconChain.getEffectiveBalance(state: state, index: index) * epochsSinceFinality / INACTIVITY_PENALTY_QUOTIENT / 2 - } - - private static func attestingValidators( - state: BeaconState, - committee: [ValidatorIndex], - shard: UInt64, - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) -> [ValidatorIndex] { - let root = winningRoot( - state: state, - committee: committee, - shard: shard, - currentEpochAttestations: currentEpochAttestations, - previousEpochAttestations: previousEpochAttestations - ) - - return attestingValidatorIndices( - state: state, - committee: committee, - shard: shard, - crosslinkDataRoot: root, - currentEpochAttestations: currentEpochAttestations, - previousEpochAttestations: previousEpochAttestations - ) - } - - private static func totalAttestingBalance( - state: BeaconState, - committee: [ValidatorIndex], - shard: UInt64, - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) -> UInt64 { - return attestingValidators( - state: state, - committee: committee, - shard: shard, - currentEpochAttestations: currentEpochAttestations, - previousEpochAttestations: previousEpochAttestations - ) - .totalBalance(state: state) - } - - private static func attestingValidatorIndices( - state: BeaconState, - committee: [ValidatorIndex], - shard: UInt64, - crosslinkDataRoot: Data, - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) -> [ValidatorIndex] { - return (currentEpochAttestations + previousEpochAttestations) - .filter { - $0.data.shard == shard && $0.data.crosslinkDataRoot == crosslinkDataRoot - } - .flatMap { - return BeaconChain.getAttestationParticipants( - state: state, - attestationData: $0.data, - bitfield: $0.aggregationBitfield - ) - } - } - - private static func winningRoot( - state: BeaconState, - committee: [ValidatorIndex], - shard: UInt64, - currentEpochAttestations: [PendingAttestation], - previousEpochAttestations: [PendingAttestation] - ) -> Data { - let candidateRoots = (currentEpochAttestations + previousEpochAttestations) - .filter { - $0.data.shard == shard - } - .map { - $0.data.crosslinkDataRoot - } - - var winnerRoot = Data(count: 0) - var winnerBalance = UInt64(0) - for root in candidateRoots { - let indices = attestingValidatorIndices( - state: state, - committee: committee, - shard: shard, - crosslinkDataRoot: root, - currentEpochAttestations: currentEpochAttestations, - previousEpochAttestations: previousEpochAttestations - ) - - let rootBalance = indices.totalBalance(state: state) - - if rootBalance > winnerBalance || (rootBalance == winnerBalance && root < winnerRoot) { - winnerBalance = rootBalance - winnerRoot = root - } - } - - return winnerRoot - } - - private static func inclusionDistance(state: BeaconState, index: ValidatorIndex) -> UInt64 { - for a in state.latestAttestations { - let participated = BeaconChain.getAttestationParticipants(state: state, attestationData: a.data, bitfield: a.aggregationBitfield) - - for i in participated { - if index == i { - return a.inclusionSlot - a.data.slot - } - } - } - - return 0 - } - - private static func inclusionSlot(state: BeaconState, index: Int) -> UInt64 { - for a in state.latestAttestations { - let participated = BeaconChain.getAttestationParticipants(state: state, attestationData: a.data, bitfield: a.aggregationBitfield) - - for i in participated { - if index == i { - return a.inclusionSlot - } - } - } - - return 0 - } -} - -extension StateTransition { - - static func processStateRoot(state: BeaconState) { - // @todo Verify block.state_root == hash_tree_root(state) if there exists a block for the slot being processed. - } - -} diff --git a/Sources/BeaconChain/Store/Store.swift b/Sources/BeaconChain/Store/Store.swift deleted file mode 100644 index baba99f..0000000 --- a/Sources/BeaconChain/Store/Store.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -public protocol Store { - - func parent(_ block: BeaconBlock) -> BeaconBlock - func children(_ block: BeaconBlock) -> [BeaconBlock] - func latestAttestation(validator: ValidatorIndex) -> Attestation - func latestAttestationTarget(validator: ValidatorIndex) -> BeaconBlock -} - -extension Store { - - func ancestor(block: BeaconBlock, slot: Slot) -> BeaconBlock? { - if block.slot == slot { - return block - } - - if block.slot < slot { - return nil - } - - return ancestor(block: parent(block), slot: slot) - } -} - diff --git a/Sources/BeaconChain/Types.swift b/Sources/BeaconChain/Types.swift deleted file mode 100644 index 425cd80..0000000 --- a/Sources/BeaconChain/Types.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -public typealias Slot = UInt64 -typealias Epoch = UInt64 -typealias Shard = UInt64 -public typealias ValidatorIndex = UInt64 -typealias Gwei = UInt64 -typealias Bytes32 = Data // @todo needs to be 32 fixed length data -typealias BLSPubkey = Data // @todo needs to be 48 fixed length data -typealias BLSSignature = Data // @todo needs to be 96 fixed length data - -typealias AttestationTarget = (ValidatorIndex, BeaconBlock) diff --git a/Tests/BeaconChainTests/BeaconChainTests.swift b/Tests/BeaconChainTests/BeaconChainTests.swift deleted file mode 100644 index 660ab2f..0000000 --- a/Tests/BeaconChainTests/BeaconChainTests.swift +++ /dev/null @@ -1,59 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class BeaconChainTests: XCTestCase { - - func testIsDoubleVote() { - let dummy = Data(count: 1) - let attestation = AttestationData( - slot: 128, - shard: 0, - beaconBlockRoot: dummy, - epochBoundaryRoot: dummy, - crosslinkDataRoot: dummy, - latestCrosslink: Crosslink(epoch: 0, crosslinkDataRoot: dummy), - justifiedEpoch: 0, - justifiedBlockRoot: dummy - ) - - XCTAssert(BeaconChain.isDoubleVote(attestation, attestation)) - } - - func testIntegerSquareRoot() { - let numbers = [(UInt64(20), UInt64(4)), (200, 14), (1987, 44), (34989843, 5915), (97282, 311)] - - for num in numbers { - XCTAssertEqual(num.1, num.0.sqrt()) - } - } - -// func testIsSurroundVote() { -// let data = AttestationData( -// slot: 192, -// shard: 0, -// beaconBlockRoot: Data(count: 32), -// epochBoundaryRoot: Data(count: 32), -// shardBlockRoot: Data(count: 32), -// latestCrosslinkRoot: Data(count: 32), -// justifiedEpoch: 0, -// justifiedBlockRoot: Data(count: 32) -// ) -// -// XCTAssertFalse(BeaconChain.isSurroundVote(data, data)) -// XCTAssertTrue( -// BeaconChain.isSurroundVote( -// data, -// AttestationData( -// slot: 128, -// shard: 0, -// beaconBlockRoot: Data(count: 32), -// epochBoundaryRoot: Data(count: 32), -// shardBlockRoot: Data(count: 32), -// latestCrosslinkRoot: Data(count: 32), -// justifiedEpoch: 64, -// justifiedBlockRoot: Data(count: 32) -// ) -// ) -// ) -// } -} diff --git a/Tests/BeaconChainTests/DataStructures/State/ForkTests.swift b/Tests/BeaconChainTests/DataStructures/State/ForkTests.swift deleted file mode 100644 index 6abaee3..0000000 --- a/Tests/BeaconChainTests/DataStructures/State/ForkTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ForkTests: XCTestCase { - - func testVersion() { - let fork = Fork(previousVersion: 10, currentVersion: 20, epoch: 1) - XCTAssertEqual(10, fork.version(epoch: 0)) - XCTAssertEqual(20, fork.version(epoch: 2)) - } - - - func testDomain() { - let data = Fork(previousVersion: 2, currentVersion: 3, epoch: 10) - let constant = 2**32 - - XCTAssertEqual( - data.domain(epoch: 9, type: .proposal), - Epoch((2*constant)+2) - ) - - XCTAssertEqual( - data.domain(epoch: 11, type: .exit), - Epoch((3*constant)+3) - ) - } -} diff --git a/Tests/BeaconChainTests/DataStructures/State/ValidatorTests.swift b/Tests/BeaconChainTests/DataStructures/State/ValidatorTests.swift deleted file mode 100644 index c51c2d6..0000000 --- a/Tests/BeaconChainTests/DataStructures/State/ValidatorTests.swift +++ /dev/null @@ -1,68 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ValidatorTests: XCTestCase { - - func testIsActive() { - let epoch = Epoch(10) - - XCTAssertFalse(createValidator(epoch: epoch).isActive(epoch: epoch + 2)) - XCTAssertTrue(createValidator(epoch: epoch).isActive(epoch: epoch)) - - } - - 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, - withdrawalCredentials: ZERO_HASH, - activationEpoch: epoch - 1, - exitEpoch: epoch + 1, - withdrawableEpoch: epoch, - initiatedExit: false, - slashed: false - ) - } - -} diff --git a/Tests/BeaconChainTests/Extensions/Array+AttestationTargetTests.swift b/Tests/BeaconChainTests/Extensions/Array+AttestationTargetTests.swift deleted file mode 100644 index f0a698e..0000000 --- a/Tests/BeaconChainTests/Extensions/Array+AttestationTargetTests.swift +++ /dev/null @@ -1,47 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ArrayAttestationTargetTests: XCTestCase { - - func testVotes() { - var state = BeaconChain.genesisState( - genesisTime: 10, - latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)), - depositLength: 0 - ) - - state.validatorBalances.append(32000000000) - state.validatorBalances.append(32000000000) - state.validatorBalances.append(32000000000) - - let block = BeaconBlock( - slot: GENESIS_SLOT, - parentRoot: ZERO_HASH, - stateRoot: ZERO_HASH, - randaoReveal: ZERO_HASH, - eth1Data: state.latestEth1Data, - body: BeaconBlockBody( - proposerSlashings: [ProposerSlashing](), - attesterSlashings: [AttesterSlashing](), - attestations: [Attestation](), - deposits: [Deposit](), - voluntaryExits: [VoluntaryExit](), - transfers: [Transfer]() - ), - signature: ZERO_HASH - ) - - let store = MockStore() - - var badBlock = block - badBlock.signature = EMPTY_SIGNATURE - - var targets = [AttestationTarget]() - targets.append((0, block)) - targets.append((1, badBlock)) - targets.append((2, block)) - - XCTAssertEqual(64, targets.votes(store: store, state: state, block: block)) - } - -} diff --git a/Tests/BeaconChainTests/Extensions/Array+ValidatorIndexTests.swift b/Tests/BeaconChainTests/Extensions/Array+ValidatorIndexTests.swift deleted file mode 100644 index 5babb23..0000000 --- a/Tests/BeaconChainTests/Extensions/Array+ValidatorIndexTests.swift +++ /dev/null @@ -1,20 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ArrayValidatorIndexTests: XCTestCase { - - func testTotalBalance() { - var state = BeaconChain.genesisState( - genesisTime: 10, - latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)), - depositLength: 0 - ) - - // @todo make dynamic - state.validatorBalances.append(10) - state.validatorBalances.append(10) - - XCTAssertEqual([ValidatorIndex(0), 1].totalBalance(state: state), 20) - } - -} \ No newline at end of file diff --git a/Tests/BeaconChainTests/Extensions/Array+ValidatorTests.swift b/Tests/BeaconChainTests/Extensions/Array+ValidatorTests.swift deleted file mode 100644 index 07f8168..0000000 --- a/Tests/BeaconChainTests/Extensions/Array+ValidatorTests.swift +++ /dev/null @@ -1,30 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ArrayValidatorTests: XCTestCase { - - func testActiveIndices() { - - let epoch = Epoch(10) - - let validators = [ - createValidator(epoch: epoch), - createValidator(epoch: epoch), - createValidator(epoch: Epoch(12)) - ] - - XCTAssertEqual(validators.activeIndices(epoch: epoch), [ValidatorIndex(0), 1]) - } - - private func createValidator(epoch: Epoch) -> Validator { - return Validator( - pubkey: ZERO_HASH, - withdrawalCredentials: ZERO_HASH, - activationEpoch: epoch - 1, - exitEpoch: epoch + 1, - withdrawableEpoch: 1, - initiatedExit: false, - slashed: false - ) - } -} diff --git a/Tests/BeaconChainTests/Extensions/ArrayTests.swift b/Tests/BeaconChainTests/Extensions/ArrayTests.swift deleted file mode 100644 index f3e9b50..0000000 --- a/Tests/BeaconChainTests/Extensions/ArrayTests.swift +++ /dev/null @@ -1,11 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class ArrayTests: XCTestCase { - - func testSplit() { - let array = [0, 1, 2, 3] - XCTAssertEqual([[0, 1], [2, 3]], array.split(count: 2)) - } - -} \ No newline at end of file diff --git a/Tests/BeaconChainTests/Extensions/EpochTests.swift b/Tests/BeaconChainTests/Extensions/EpochTests.swift deleted file mode 100644 index 8b3fdcd..0000000 --- a/Tests/BeaconChainTests/Extensions/EpochTests.swift +++ /dev/null @@ -1,13 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class EpochTests: XCTestCase { - - func testStartSlot() { - XCTAssertEqual(Epoch(1).startSlot(), 64) - } - - func testEntryExitEpoch() { - XCTAssertEqual(Epoch(1).delayedActivationExitEpoch(), 6) - } -} diff --git a/Tests/BeaconChainTests/Extensions/IntTests.swift b/Tests/BeaconChainTests/Extensions/IntTests.swift deleted file mode 100644 index f521b3a..0000000 --- a/Tests/BeaconChainTests/Extensions/IntTests.swift +++ /dev/null @@ -1,10 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class IntTests: XCTestCase { - - func testIsPowerOfTwo() { - XCTAssertTrue(4.isPowerOfTwo()) - XCTAssertFalse(3.isPowerOfTwo()) - } -} diff --git a/Tests/BeaconChainTests/Extensions/SlotTests.swift b/Tests/BeaconChainTests/Extensions/SlotTests.swift deleted file mode 100644 index 57c35a4..0000000 --- a/Tests/BeaconChainTests/Extensions/SlotTests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import XCTest -@testable import BeaconChain - -final class SlotTests: XCTestCase { - - func testToEpoch() { - XCTAssertEqual(Slot(128).toEpoch(), 2) - } -} diff --git a/Tests/BeaconChainTests/Mocks/MockStore.swift b/Tests/BeaconChainTests/Mocks/MockStore.swift deleted file mode 100644 index bb34686..0000000 --- a/Tests/BeaconChainTests/Mocks/MockStore.swift +++ /dev/null @@ -1,20 +0,0 @@ -import BeaconChain - -class MockStore: Store { - - func parent(_ block: BeaconBlock) -> BeaconBlock { - return block - } - - func children(_ block: BeaconBlock) -> [BeaconBlock] { - return [block] - } - - func latestAttestation(validator: ValidatorIndex) -> Attestation { - fatalError() - } - - func latestAttestationTarget(validator: ValidatorIndex) -> BeaconBlock { - fatalError() - } -} diff --git a/Tests/BeaconChainTests/StateTransitionTests.swift b/Tests/BeaconChainTests/StateTransitionTests.swift deleted file mode 100644 index 4b47fa7..0000000 --- a/Tests/BeaconChainTests/StateTransitionTests.swift +++ /dev/null @@ -1,224 +0,0 @@ -import XCTest -@testable import BeaconChain - -//final class StateTransitionTests: XCTestCase { -// -// func testBaseReward() { -// let tests = [ -// (UInt64(0), UInt64(0)), -// (MIN_DEPOSIT_AMOUNT, UInt64(61)), -// (MAX_DEPOSIT_AMOUNT, UInt64(1976)), -// (UInt64(40 * 1e9), UInt64(1976)) -// ] -// -// for test in tests { -// var state = BeaconChain.genesisState( -// genesisTime: 0, -// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)) -// ) -// -// state.validatorBalances.append(test.0) -// -// XCTAssertEqual(test.1, StateTransition.baseReward(state: state, index: 0, baseRewardQuotient: 3237888)) -// } -// } -// -// func testInactivityPenalty() { -// let tests = [ -// (UInt64(1), UInt64(2929)), -// (UInt64(2), UInt64(3883)), -// (UInt64(5), UInt64(6744)), -// (UInt64(10), UInt64(11512)), -// (UInt64(50), UInt64(49659)) -// ] as [(UInt64, UInt64)] -// -// for test in tests { -// let state = BeaconChain.genesisState( -// genesisTime: TimeInterval(0), -// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)) -// ) -// -// state.validatorBalances.append(MAX_DEPOSIT_AMOUNT) -// -// XCTAssertEqual( -// test.1, -// StateTransition.inactivityPenalty( -// state: state, -// index: 0, -// epochsSinceFinality: test.0, -// baseRewardQuotient: 3237888 -// ) -// ) -// } -// } -// -// func testExpectedFFGTarget() { -// // @todo check these numbers -// let tests = [ -// ([Int](), [31999427550, 31999427550, 31999427550, 31999427550]), -// ([0,1], [32000286225, 32000286225, 31999427550, 31999427550]), -// ([0,1,2,3], [32000572450, 32000572450, 32000572450, 32000572450]) -// ] as [([Int], [UInt64])] -// -// for test in tests { -// let state = BeaconChain.genesisState( -// genesisTime: TimeInterval(0), -// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)) -// ) -// -// for _ in 0..<4 { -// state.validatorBalances.append(MAX_DEPOSIT_AMOUNT) -// state.validatorRegistry.append( -// Validator( -// pubkey: Data(count: 32), -// withdrawalCredentials: Data(count: 32), -// randaoCommitment: Data(count: 32), -// randaoLayers: 0, -// activationSlot: 0, -// exitSlot: FAR_FUTURE_SLOT, -// withdrawalSlot: 0, -// penalizedSlot: 0, -// exitCount: 0, -// statusFlags: 0, -// custodyCommitment: Data(count: 32), -// latestCustodyReseedSlot: 0, -// penultimateCustodyReseedSlot: 0 -// ) -// ) -// } -// -// let totalBalance = MAX_DEPOSIT_AMOUNT * UInt64(test.1.count) -// -// let newState = StateTransition.expectedFFGTarget( -// state: state, -// previousEpochBoundaryAttesterIndices: test.0, -// activeValidators: Set([0,1,2,3]), -// previousEpochBoundaryAttestingBalance: MAX_DEPOSIT_AMOUNT * UInt64(test.0.count), -// baseRewardQuotient: StateTransition.baseRewardQuotient(totalBalance: totalBalance), -// totalBalance: totalBalance -// ) -// -// for (i, balance) in test.1.enumerated() { -// XCTAssertEqual(balance, newState.validatorBalances[i]) -// } -// } -// } -// -// func testExpectedFFGSource() { -// // @todo check these numbers -// let tests = [ -// ([Int](), [31999427550, 31999427550, 31999427550, 31999427550]), -// ([0,1], [32000286225, 32000286225, 31999427550, 31999427550]), -// ([0,1,2,3], [32000572450, 32000572450, 32000572450, 32000572450]) -// ] as [([Int], [UInt64])] -// -// for test in tests { -// let state = BeaconChain.genesisState( -// genesisTime: TimeInterval(0), -// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)) -// ) -// -// for _ in 0..<4 { -// state.validatorBalances.append(MAX_DEPOSIT_AMOUNT) -// state.validatorRegistry.append( -// Validator( -// pubkey: Data(count: 32), -// withdrawalCredentials: Data(count: 32), -// randaoCommitment: Data(count: 32), -// randaoLayers: 0, -// activationSlot: 0, -// exitSlot: FAR_FUTURE_SLOT, -// withdrawalSlot: 0, -// penalizedSlot: 0, -// exitCount: 0, -// statusFlags: 0, -// custodyCommitment: Data(count: 32), -// latestCustodyReseedSlot: 0, -// penultimateCustodyReseedSlot: 0 -// ) -// ) -// } -// -// let totalBalance = MAX_DEPOSIT_AMOUNT * UInt64(test.1.count) -// -// let newState = StateTransition.expectedFFGSource( -// state: state, -// previousEpochJustifiedAttesterIndices: test.0, -// activeValidators: Set([0,1,2,3]), -// previousEpochJustifiedAttestingBalance: MAX_DEPOSIT_AMOUNT * UInt64(test.0.count), -// baseRewardQuotient: StateTransition.baseRewardQuotient(totalBalance: totalBalance), -// totalBalance: totalBalance -// ) -// -// for (i, balance) in test.1.enumerated() { -// XCTAssertEqual(balance, newState.validatorBalances[i]) -// } -// } -// } -// -// func testExpectedBeaconChainHead() { -// // @todo check these numbers -// let tests = [ -// ([Int](), [31999427550, 31999427550, 31999427550, 31999427550]), -// ([0,1], [32000286225, 32000286225, 31999427550, 31999427550]), -// ([0,1,2,3], [32000572450, 32000572450, 32000572450, 32000572450]) -// ] as [([Int], [UInt64])] -// -// for test in tests { -// let state = BeaconChain.genesisState( -// genesisTime: TimeInterval(0), -// latestEth1Data: Eth1Data(depositRoot: Data(count: 32), blockHash: Data(count: 32)) -// ) -// -// for _ in 0..<4 { -// state.validatorBalances.append(MAX_DEPOSIT_AMOUNT) -// state.validatorRegistry.append( -// Validator( -// pubkey: Data(count: 32), -// withdrawalCredentials: Data(count: 32), -// randaoCommitment: Data(count: 32), -// randaoLayers: 0, -// activationSlot: 0, -// exitSlot: FAR_FUTURE_SLOT, -// withdrawalSlot: 0, -// penalizedSlot: 0, -// exitCount: 0, -// statusFlags: 0, -// custodyCommitment: Data(count: 32), -// latestCustodyReseedSlot: 0, -// penultimateCustodyReseedSlot: 0 -// ) -// ) -// } -// -// let totalBalance = MAX_DEPOSIT_AMOUNT * UInt64(test.1.count) -// -// let newState = StateTransition.expectedBeaconChainHead( -// state: state, -// previousEpochHeadAttesterIndices: test.0, -// activeValidators: Set([0,1,2,3]), -// previousEpochHeadAttestingBalance: MAX_DEPOSIT_AMOUNT * UInt64(test.0.count), -// baseRewardQuotient: StateTransition.baseRewardQuotient(totalBalance: totalBalance), -// totalBalance: totalBalance -// ) -// -// for (i, balance) in test.1.enumerated() { -// XCTAssertEqual(balance, newState.validatorBalances[i]) -// } -// } -// } -// -// func testBaseRewardQuotient() { -// var tests = [(UInt64, UInt64)]() -// tests.append((UInt64(0), UInt64(0))) -// tests.append((UInt64(1e6 * 1e9), UInt64(988211))) -// tests.append((UInt64(2e6 * 1e9), UInt64(1397542))) -// tests.append((UInt64(5e6 * 1e9), UInt64(2209708))) -// tests.append((UInt64(10e6 * 1e9), UInt64(3125000))) -// tests.append((UInt64(20e6 * 1e9), UInt64(4419417))) -// -// for test in tests { -// XCTAssertEqual(StateTransition.baseRewardQuotient(totalBalance: test.0), test.1) -// } -// } -//} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index dc208db..3c6f89c 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,8 +1,6 @@ import XCTest -import BeaconChainTests var tests = [XCTestCaseEntry]() -tests += BeaconChainTests.__allTests() XCTMain(tests) From 415ad73f480f8c75e432d9aaa935e4f0e086210f Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 1 Jul 2019 23:14:23 +0200 Subject: [PATCH 02/41] types --- Sources/BeaconChain/Types.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Sources/BeaconChain/Types.swift diff --git a/Sources/BeaconChain/Types.swift b/Sources/BeaconChain/Types.swift new file mode 100644 index 0000000..367b94b --- /dev/null +++ b/Sources/BeaconChain/Types.swift @@ -0,0 +1,13 @@ +import Foundation + +typealias Slot = UInt64 +typealias Epoch = UInt64 +typealias Shard = UInt64 +typealias ValidatorIndex = UInt64 +typealias Gwei = UInt64 +typealias Hash = Data +typealias Version = UInt32 +typealias DomainType = UInt32 +typealias Domain = UInt64 +typealias BLSPubKey = Data +typealias BLSSignature = Data From 433924b026ee440fd6a92a3c2857e2ba2d25f009 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 01:37:40 +0200 Subject: [PATCH 03/41] constants --- Sources/BeaconChain/Constants.swift | 8 ++++++++ Sources/BeaconChain/Operators/Power.swift | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 Sources/BeaconChain/Constants.swift create mode 100644 Sources/BeaconChain/Operators/Power.swift diff --git a/Sources/BeaconChain/Constants.swift b/Sources/BeaconChain/Constants.swift new file mode 100644 index 0000000..dc1f04d --- /dev/null +++ b/Sources/BeaconChain/Constants.swift @@ -0,0 +1,8 @@ +import Foundation + +let FAR_FUTURE_EPOCH = Epoch(UInt64.max) +let BASE_REWARDS_PER_EPOCH = 5 +let DEPOSIT_CONTRACT_TREE_DEPTH = 2**5 +let SECONDS_PER_DAY = 86400 +let JUSTIFICATION_BITS_LENGTH = 4 +let ENDIANNESS = "little" diff --git a/Sources/BeaconChain/Operators/Power.swift b/Sources/BeaconChain/Operators/Power.swift new file mode 100644 index 0000000..3ddb25e --- /dev/null +++ b/Sources/BeaconChain/Operators/Power.swift @@ -0,0 +1,18 @@ +import Foundation + +precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } +infix operator ** : PowerPrecedence + +extension UInt64 { + + static func ** (radix: UInt64, power: UInt64) -> UInt64 { + return UInt64(pow(Double(radix), Double(power))) + } +} + +extension Int { + + static func ** (radix: Int, power: Int) -> Int { + return Int(pow(Double(radix), Double(power))) + } +} From cbd4ad931a0f73d6925b1d34f2745b91dcd57171 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 01:39:16 +0200 Subject: [PATCH 04/41] cleanup --- Sources/BeaconChain/Operators/Power.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/BeaconChain/Operators/Power.swift b/Sources/BeaconChain/Operators/Power.swift index 3ddb25e..4e9bc8d 100644 --- a/Sources/BeaconChain/Operators/Power.swift +++ b/Sources/BeaconChain/Operators/Power.swift @@ -5,14 +5,14 @@ infix operator ** : PowerPrecedence extension UInt64 { - static func ** (radix: UInt64, power: UInt64) -> UInt64 { + static func **(radix: UInt64, power: UInt64) -> UInt64 { return UInt64(pow(Double(radix), Double(power))) } } extension Int { - static func ** (radix: Int, power: Int) -> Int { + static func **(radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } } From 1029bcdcd2d50edc9b62d19cb3579b04b4d9e85e Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 01:40:05 +0200 Subject: [PATCH 05/41] whitspace --- Sources/BeaconChain/Operators/Power.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/BeaconChain/Operators/Power.swift b/Sources/BeaconChain/Operators/Power.swift index 4e9bc8d..3ddb25e 100644 --- a/Sources/BeaconChain/Operators/Power.swift +++ b/Sources/BeaconChain/Operators/Power.swift @@ -5,14 +5,14 @@ infix operator ** : PowerPrecedence extension UInt64 { - static func **(radix: UInt64, power: UInt64) -> UInt64 { + static func ** (radix: UInt64, power: UInt64) -> UInt64 { return UInt64(pow(Double(radix), Double(power))) } } extension Int { - static func **(radix: Int, power: Int) -> Int { + static func ** (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } } From ce9e341f4f255924724a1d19fadcee32b1c1dade Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 01:41:11 +0200 Subject: [PATCH 06/41] cleanup lint --- .swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index c21031b..91be776 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,10 +3,10 @@ included: - Tests excluded: - Tests/BeaconChainTests/XCTestManifests.swift + - Tests/LinuxMain.swift file_name: excluded: - Package.swift - - LinuxMain.swift identifier_name: excluded: - id From 1adb58d6f1ae8f3bbbcdb8a5ea5e643a1289bdce Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 02:11:13 +0200 Subject: [PATCH 07/41] created power tests --- .../Operators/PowerTests.swift | 26 +++++ Tests/BeaconChainTests/XCTestManifests.swift | 105 +----------------- Tests/LinuxMain.swift | 2 + 3 files changed, 33 insertions(+), 100 deletions(-) create mode 100644 Tests/BeaconChainTests/Operators/PowerTests.swift diff --git a/Tests/BeaconChainTests/Operators/PowerTests.swift b/Tests/BeaconChainTests/Operators/PowerTests.swift new file mode 100644 index 0000000..b552b27 --- /dev/null +++ b/Tests/BeaconChainTests/Operators/PowerTests.swift @@ -0,0 +1,26 @@ +import XCTest +@testable import BeaconChain + +class PowerTests: XCTestCase { + + let tests: [(base: Int, exponent: Int, expected: Int)] = [ + (2, 0, 1), + (2, 1, 2), + (2, 2, 4), + (2, 3, 8), + (2, 4, 16), + ]; + + func testPowerForInt() { + for test in tests { + XCTAssert(test.base ** test.exponent == test.expected) + } + } + + func testPowerForUInt64() { + for test in tests { + XCTAssert(UInt64(test.base) ** UInt64(test.exponent) == UInt64(test.expected)) + } + } + +} diff --git a/Tests/BeaconChainTests/XCTestManifests.swift b/Tests/BeaconChainTests/XCTestManifests.swift index de3d05a..a3f307a 100644 --- a/Tests/BeaconChainTests/XCTestManifests.swift +++ b/Tests/BeaconChainTests/XCTestManifests.swift @@ -1,114 +1,19 @@ #if !canImport(ObjectiveC) import XCTest -extension ArrayAttestationTargetTests { +extension PowerTests { // DO NOT MODIFY: This is autogenerated, use: // `swift test --generate-linuxmain` // to regenerate. - static let __allTests__ArrayAttestationTargetTests = [ - ("testVotes", testVotes), - ] -} - -extension ArrayTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ArrayTests = [ - ("testSplit", testSplit), - ] -} - -extension ArrayValidatorIndexTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ArrayValidatorIndexTests = [ - ("testTotalBalance", testTotalBalance), - ] -} - -extension ArrayValidatorTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ArrayValidatorTests = [ - ("testActiveIndices", testActiveIndices), - ] -} - -extension BeaconChainTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__BeaconChainTests = [ - ("testIntegerSquareRoot", testIntegerSquareRoot), - ("testIsDoubleVote", testIsDoubleVote), - ] -} - -extension EpochTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__EpochTests = [ - ("testEntryExitEpoch", testEntryExitEpoch), - ("testStartSlot", testStartSlot), - ] -} - -extension ForkTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ForkTests = [ - ("testDomain", testDomain), - ("testVersion", testVersion), - ] -} - -extension IntTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__IntTests = [ - ("testIsPowerOfTwo", testIsPowerOfTwo), - ] -} - -extension SlotTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__SlotTests = [ - ("testToEpoch", testToEpoch), - ] -} - -extension ValidatorTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ValidatorTests = [ - ("testActivate", testActivate), - ("testExitValidator", testExitValidator), - ("testIsActive", testIsActive), - ("testPrepareForWithdrawal", testPrepareForWithdrawal), + static let __allTests__PowerTests = [ + ("testPowerForInt", testPowerForInt), + ("testPowerForUInt64", testPowerForUInt64), ] } public func __allTests() -> [XCTestCaseEntry] { return [ - testCase(ArrayAttestationTargetTests.__allTests__ArrayAttestationTargetTests), - testCase(ArrayTests.__allTests__ArrayTests), - testCase(ArrayValidatorIndexTests.__allTests__ArrayValidatorIndexTests), - testCase(ArrayValidatorTests.__allTests__ArrayValidatorTests), - testCase(BeaconChainTests.__allTests__BeaconChainTests), - testCase(EpochTests.__allTests__EpochTests), - testCase(ForkTests.__allTests__ForkTests), - testCase(IntTests.__allTests__IntTests), - testCase(SlotTests.__allTests__SlotTests), - testCase(ValidatorTests.__allTests__ValidatorTests), + testCase(PowerTests.__allTests__PowerTests), ] } #endif diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 3c6f89c..dc208db 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1,6 +1,8 @@ import XCTest +import BeaconChainTests var tests = [XCTestCaseEntry]() +tests += BeaconChainTests.__allTests() XCTMain(tests) From 8509f76105d98109224edbcd8f86b17d5b9b9144 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 02:17:48 +0200 Subject: [PATCH 08/41] disable rule --- Tests/BeaconChainTests/Operators/PowerTests.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/BeaconChainTests/Operators/PowerTests.swift b/Tests/BeaconChainTests/Operators/PowerTests.swift index b552b27..b2491d0 100644 --- a/Tests/BeaconChainTests/Operators/PowerTests.swift +++ b/Tests/BeaconChainTests/Operators/PowerTests.swift @@ -3,13 +3,14 @@ import XCTest class PowerTests: XCTestCase { + // swiftlint:disable large_tuple let tests: [(base: Int, exponent: Int, expected: Int)] = [ (2, 0, 1), (2, 1, 2), (2, 2, 4), (2, 3, 8), - (2, 4, 16), - ]; + (2, 4, 16) + ] func testPowerForInt() { for test in tests { From c004444b99f5baa5950a36a4fd2f56d171b61365 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:03:35 +0200 Subject: [PATCH 09/41] added misc --- Sources/BeaconChain/Configuration.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Sources/BeaconChain/Configuration.swift diff --git a/Sources/BeaconChain/Configuration.swift b/Sources/BeaconChain/Configuration.swift new file mode 100644 index 0000000..983004f --- /dev/null +++ b/Sources/BeaconChain/Configuration.swift @@ -0,0 +1,11 @@ +import Foundation + +// misc +let SHARD_COUNT = 2**10 +let TARGET_COMMITTEE_SIZE = 2**7 +let MAX_VALIDATORS_PER_COMMITTEE = 2**12 +let MIN_PER_EPOCH_CHURN_LIMIT = 2**2 +let CHURN_LIMIT_QUOTIENT = 2**16 +let SHUFFLE_ROUND_COUNT = 90 +let MIN_GENESIS_ACTIVE_VALIDATOR_COUNT = 2**16 +let MIN_GENESIS_TIME = 1578009600 From 453b05accd879219d6a419163f68cdfd02b77196 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:04:53 +0200 Subject: [PATCH 10/41] gwei --- Sources/BeaconChain/Configuration.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/BeaconChain/Configuration.swift b/Sources/BeaconChain/Configuration.swift index 983004f..d2d490e 100644 --- a/Sources/BeaconChain/Configuration.swift +++ b/Sources/BeaconChain/Configuration.swift @@ -9,3 +9,9 @@ let CHURN_LIMIT_QUOTIENT = 2**16 let SHUFFLE_ROUND_COUNT = 90 let MIN_GENESIS_ACTIVE_VALIDATOR_COUNT = 2**16 let MIN_GENESIS_TIME = 1578009600 + +// gwei values +let MIN_DEPOSIT_AMOUNT = Gwei(2**0 * 10**9) +let MAX_EFFECTIVE_BALANCE = Gwei(2**5 * 10**9) +let EJECTION_BALANCE = Gwei(2**4 * 10**9) +let EFFECTIVE_BALANCE_INCREMENT = Gwei(2**0 * 10**9) From 8a44388b6a022695dabe22ecacd540f9bf06a363 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:05:53 +0200 Subject: [PATCH 11/41] initial values --- Sources/BeaconChain/Configuration.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/BeaconChain/Configuration.swift b/Sources/BeaconChain/Configuration.swift index d2d490e..04721db 100644 --- a/Sources/BeaconChain/Configuration.swift +++ b/Sources/BeaconChain/Configuration.swift @@ -15,3 +15,8 @@ let MIN_DEPOSIT_AMOUNT = Gwei(2**0 * 10**9) let MAX_EFFECTIVE_BALANCE = Gwei(2**5 * 10**9) let EJECTION_BALANCE = Gwei(2**4 * 10**9) let EFFECTIVE_BALANCE_INCREMENT = Gwei(2**0 * 10**9) + +// initial values +let GENESIS_SLOT = Slot(0) +let GENESIS_EPOCH = Epoch(0) +let BLS_WITHDRAWAL_PREFIX = 0b00 From 825cdf8111a7cf30ec9572f686b3bbc9faf44100 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:12:06 +0200 Subject: [PATCH 12/41] time, state, reward and penalties --- Sources/BeaconChain/Configuration.swift | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Sources/BeaconChain/Configuration.swift b/Sources/BeaconChain/Configuration.swift index 04721db..71684dc 100644 --- a/Sources/BeaconChain/Configuration.swift +++ b/Sources/BeaconChain/Configuration.swift @@ -20,3 +20,28 @@ let EFFECTIVE_BALANCE_INCREMENT = Gwei(2**0 * 10**9) let GENESIS_SLOT = Slot(0) let GENESIS_EPOCH = Epoch(0) let BLS_WITHDRAWAL_PREFIX = 0b00 + +// time parameters +let MIN_ATTESTATION_INCLUSION_DELAY = 2**0 +let SLOTS_PER_EPOCH = 2**6 +let MIN_SEED_LOOKAHEAD = 2**0 +let ACTIVATION_EXIT_DELAY = 2**2 +let SLOTS_PER_ETH1_VOTING_PERIOD = 2**10 +let SLOTS_PER_HISTORICAL_ROOT = 2**13 +let MIN_VALIDATOR_WITHDRAWABILITY_DELAY = 2**8 +let PERSISTENT_COMMITTEE_PERIOD = 2**11 +let MAX_EPOCHS_PER_CROSSLINK = 2**6 +let MIN_EPOCHS_TO_INACTIVITY_PENALTY = 2**2 + +// state list lengths +let EPOCHS_PER_HISTORICAL_VECTOR = 2**16 +let EPOCHS_PER_SLASHINGS_VECTOR = 2**13 +let HISTORICAL_ROOTS_LIMIT = 2**14 +let VALIDATOR_REGISTRY_LIMIT = 2**40 + +// rewards and penalties +let BASE_REWARD_FACTOR = 2**6 +let WHISTLEBLOWER_REWARD_QUOTIENT = 2**9 +let PROPOSER_REWARD_QUOTIENT = 2**3 +let INACTIVITY_PENALTY_QUOTIENT = 2**25 +let MIN_SLASHING_PENALTY_QUOTIENT = 2**5 From c4c3439086167f43b267bacd0c94402e6beeee89 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:13:47 +0200 Subject: [PATCH 13/41] max values --- Sources/BeaconChain/Configuration.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/BeaconChain/Configuration.swift b/Sources/BeaconChain/Configuration.swift index 71684dc..8dd48b3 100644 --- a/Sources/BeaconChain/Configuration.swift +++ b/Sources/BeaconChain/Configuration.swift @@ -45,3 +45,11 @@ let WHISTLEBLOWER_REWARD_QUOTIENT = 2**9 let PROPOSER_REWARD_QUOTIENT = 2**3 let INACTIVITY_PENALTY_QUOTIENT = 2**25 let MIN_SLASHING_PENALTY_QUOTIENT = 2**5 + +// max operations per block +let MAX_PROPOSER_SLASHINGS = 2**4 +let MAX_ATTESTER_SLASHINGS = 2**0 +let MAX_ATTESTATIONS = 2**7 +let MAX_DEPOSITS = 2**4 +let MAX_VOLUNTARY_EXITS = 2**4 +let MAX_TRANSFERS = 0 From 4ec6cda3261c60f1bbdbfcc8c9ea93a28da1660e Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:16:21 +0200 Subject: [PATCH 14/41] domain type --- Sources/BeaconChain/Types.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/BeaconChain/Types.swift b/Sources/BeaconChain/Types.swift index 367b94b..c9ad2a2 100644 --- a/Sources/BeaconChain/Types.swift +++ b/Sources/BeaconChain/Types.swift @@ -7,7 +7,6 @@ typealias ValidatorIndex = UInt64 typealias Gwei = UInt64 typealias Hash = Data typealias Version = UInt32 -typealias DomainType = UInt32 typealias Domain = UInt64 typealias BLSPubKey = Data typealias BLSSignature = Data From a8b58f6afd865852d1ca507aa4fb5baaddc4aa6a Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 03:25:51 +0200 Subject: [PATCH 15/41] domain --- Sources/BeaconChain/Enums/DomainType.swift | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Sources/BeaconChain/Enums/DomainType.swift diff --git a/Sources/BeaconChain/Enums/DomainType.swift b/Sources/BeaconChain/Enums/DomainType.swift new file mode 100644 index 0000000..337bab1 --- /dev/null +++ b/Sources/BeaconChain/Enums/DomainType.swift @@ -0,0 +1,5 @@ +import Foundation + +enum DomainType: UInt32 { + case beaconProposer, randao, attestation, deposit, voluntaryExit, transfer +} From 7f4bdba61f62a7a18d21af1e56306d50f0a10561 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 05:28:55 +0200 Subject: [PATCH 16/41] started working on data types --- .../BeaconChain/Attestation/AttestationData.swift | 8 ++++++++ .../Attestation/AttestationDataAndCustodyBit.swift | 6 ++++++ .../BeaconChain/Attestation/IndexedAttestation.swift | 8 ++++++++ .../BeaconChain/Attestation/PendingAttestation.swift | 8 ++++++++ Sources/BeaconChain/Checkpoint.swift | 6 ++++++ Sources/BeaconChain/Crosslink.swift | 9 +++++++++ Sources/BeaconChain/Fork.swift | 7 +++++++ Sources/BeaconChain/Validator.swift | 12 ++++++++++++ 8 files changed, 64 insertions(+) create mode 100644 Sources/BeaconChain/Attestation/AttestationData.swift create mode 100644 Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift create mode 100644 Sources/BeaconChain/Attestation/IndexedAttestation.swift create mode 100644 Sources/BeaconChain/Attestation/PendingAttestation.swift create mode 100644 Sources/BeaconChain/Checkpoint.swift create mode 100644 Sources/BeaconChain/Crosslink.swift create mode 100644 Sources/BeaconChain/Fork.swift create mode 100644 Sources/BeaconChain/Validator.swift diff --git a/Sources/BeaconChain/Attestation/AttestationData.swift b/Sources/BeaconChain/Attestation/AttestationData.swift new file mode 100644 index 0000000..6ca7245 --- /dev/null +++ b/Sources/BeaconChain/Attestation/AttestationData.swift @@ -0,0 +1,8 @@ +import Foundation + +struct AttestationData { + let beaconBlockRoot: Hash + let source: Checkpoint + let target: Checkpoint + let crosslink: Crosslink +} diff --git a/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift b/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift new file mode 100644 index 0000000..8e81b1f --- /dev/null +++ b/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift @@ -0,0 +1,6 @@ +import Foundation + +struct AttestationDataAndCustodyBit { + let data: AttestationData + let custodyBit: Bool // @todo probably not the best? +} diff --git a/Sources/BeaconChain/Attestation/IndexedAttestation.swift b/Sources/BeaconChain/Attestation/IndexedAttestation.swift new file mode 100644 index 0000000..39f0a51 --- /dev/null +++ b/Sources/BeaconChain/Attestation/IndexedAttestation.swift @@ -0,0 +1,8 @@ +import Foundation + +struct IndexedAttestation { + let custodyBit0Indices: [ValidatorIndex] + let custodyBit1Indices: [ValidatorIndex] + let data: AttestationData + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/Attestation/PendingAttestation.swift b/Sources/BeaconChain/Attestation/PendingAttestation.swift new file mode 100644 index 0000000..20b66ef --- /dev/null +++ b/Sources/BeaconChain/Attestation/PendingAttestation.swift @@ -0,0 +1,8 @@ +import Foundation + +struct PendingAttestation { + let aggregationBits: [Bool] + let data: AttestationData + let inclusionDelay: Slot + let proposerIndex: ValidatorIndex +} diff --git a/Sources/BeaconChain/Checkpoint.swift b/Sources/BeaconChain/Checkpoint.swift new file mode 100644 index 0000000..10c7a3d --- /dev/null +++ b/Sources/BeaconChain/Checkpoint.swift @@ -0,0 +1,6 @@ +import Foundation + +struct Checkpoint { + let epoch: Epoch + let root: Hash +} diff --git a/Sources/BeaconChain/Crosslink.swift b/Sources/BeaconChain/Crosslink.swift new file mode 100644 index 0000000..887f5c1 --- /dev/null +++ b/Sources/BeaconChain/Crosslink.swift @@ -0,0 +1,9 @@ +import Foundation + +struct Crosslink { + let shard: Shard + let parentRoot: Hash + let startEpoch: Epoch + let endEpoch: Epoch + let dataRoot: Hash +} diff --git a/Sources/BeaconChain/Fork.swift b/Sources/BeaconChain/Fork.swift new file mode 100644 index 0000000..322d619 --- /dev/null +++ b/Sources/BeaconChain/Fork.swift @@ -0,0 +1,7 @@ +import Foundation + +struct Fork { + let previousVersion: Version + let currentVersion: Version + let epoch: Epoch +} diff --git a/Sources/BeaconChain/Validator.swift b/Sources/BeaconChain/Validator.swift new file mode 100644 index 0000000..66f970c --- /dev/null +++ b/Sources/BeaconChain/Validator.swift @@ -0,0 +1,12 @@ +import Foundation + +struct Validator { + let pubkey: BLSPubKey + let withdrawalCredentials: Hash + let effectiveBalance: Gwei + let slashed: Bool + let activationEligibilityEpoch: Epoch + let activationEpoch: Epoch + let exitEpoch: Epoch + let withdrawableEpoch: Epoch +} From 50641e221e9dd1a9771579603b527dc06e309a8b Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 05:34:05 +0200 Subject: [PATCH 17/41] updated --- Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift | 9 +++++++++ Sources/BeaconChain/CompactCommittee.swift | 6 ++++++ Sources/BeaconChain/Eth1Data.swift | 7 +++++++ Sources/BeaconChain/HistoricalBatch.swift | 6 ++++++ 4 files changed, 28 insertions(+) create mode 100644 Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift create mode 100644 Sources/BeaconChain/CompactCommittee.swift create mode 100644 Sources/BeaconChain/Eth1Data.swift create mode 100644 Sources/BeaconChain/HistoricalBatch.swift diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift new file mode 100644 index 0000000..b0be78e --- /dev/null +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift @@ -0,0 +1,9 @@ +import Foundation + +struct BeaconBlockHeader { + let slot: Slot + let parentRoot: Hash + let stateRoot: Hash + let bodyRoot: Hash + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/CompactCommittee.swift b/Sources/BeaconChain/CompactCommittee.swift new file mode 100644 index 0000000..5d7820e --- /dev/null +++ b/Sources/BeaconChain/CompactCommittee.swift @@ -0,0 +1,6 @@ +import Foundation + +struct CompactCommittee { + let pubkeys: [BLSPubKey] + let compactValidators: [UInt64] +} diff --git a/Sources/BeaconChain/Eth1Data.swift b/Sources/BeaconChain/Eth1Data.swift new file mode 100644 index 0000000..e1fa4a7 --- /dev/null +++ b/Sources/BeaconChain/Eth1Data.swift @@ -0,0 +1,7 @@ +import Foundation + +struct Eth1Data { + let depositRoot: Hash + let depositCount: UInt64 + let blockHash: Hash +} diff --git a/Sources/BeaconChain/HistoricalBatch.swift b/Sources/BeaconChain/HistoricalBatch.swift new file mode 100644 index 0000000..d2c42a0 --- /dev/null +++ b/Sources/BeaconChain/HistoricalBatch.swift @@ -0,0 +1,6 @@ +import Foundation + +struct HistoricalBatch { + let blockRoots: [Hash] + let stateRoots: [Hash] +} From 13ccbe33fcd84d1162e54ed870159682826bd254 Mon Sep 17 00:00:00 2001 From: decanus Date: Tue, 2 Jul 2019 16:06:35 -0400 Subject: [PATCH 18/41] operations --- Sources/BeaconChain/DepositData.swift | 8 ++++++++ Sources/BeaconChain/Operations/Attestation.swift | 8 ++++++++ Sources/BeaconChain/Operations/AttesterSlashing.swift | 6 ++++++ Sources/BeaconChain/Operations/Deposit.swift | 6 ++++++ Sources/BeaconChain/Operations/ProposerSlashing.swift | 7 +++++++ Sources/BeaconChain/Operations/Transfer.swift | 11 +++++++++++ Sources/BeaconChain/Operations/VoluntaryExit.swift | 7 +++++++ 7 files changed, 53 insertions(+) create mode 100644 Sources/BeaconChain/DepositData.swift create mode 100644 Sources/BeaconChain/Operations/Attestation.swift create mode 100644 Sources/BeaconChain/Operations/AttesterSlashing.swift create mode 100644 Sources/BeaconChain/Operations/Deposit.swift create mode 100644 Sources/BeaconChain/Operations/ProposerSlashing.swift create mode 100644 Sources/BeaconChain/Operations/Transfer.swift create mode 100644 Sources/BeaconChain/Operations/VoluntaryExit.swift diff --git a/Sources/BeaconChain/DepositData.swift b/Sources/BeaconChain/DepositData.swift new file mode 100644 index 0000000..e4313bc --- /dev/null +++ b/Sources/BeaconChain/DepositData.swift @@ -0,0 +1,8 @@ +import Foundation + +struct DepositData { + let pubkey: BLSPubKey + let withdrawalCredentials: Hash + let amount: Gwei + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/Operations/Attestation.swift b/Sources/BeaconChain/Operations/Attestation.swift new file mode 100644 index 0000000..4bbef22 --- /dev/null +++ b/Sources/BeaconChain/Operations/Attestation.swift @@ -0,0 +1,8 @@ +import Foundation + +struct Attestation { + let aggregationBits: [Bool] + let data: AttestationData + let custodyBits: [Bool] + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/Operations/AttesterSlashing.swift b/Sources/BeaconChain/Operations/AttesterSlashing.swift new file mode 100644 index 0000000..b806728 --- /dev/null +++ b/Sources/BeaconChain/Operations/AttesterSlashing.swift @@ -0,0 +1,6 @@ +import Foundation + +struct AttesterSlashing { + let attestation1: IndexedAttestation + let attestation2: IndexedAttestation +} diff --git a/Sources/BeaconChain/Operations/Deposit.swift b/Sources/BeaconChain/Operations/Deposit.swift new file mode 100644 index 0000000..837f362 --- /dev/null +++ b/Sources/BeaconChain/Operations/Deposit.swift @@ -0,0 +1,6 @@ +import Foundation + +struct Deposit { + let proof: [Hash] + let data: DepositData +} diff --git a/Sources/BeaconChain/Operations/ProposerSlashing.swift b/Sources/BeaconChain/Operations/ProposerSlashing.swift new file mode 100644 index 0000000..93adf2b --- /dev/null +++ b/Sources/BeaconChain/Operations/ProposerSlashing.swift @@ -0,0 +1,7 @@ +import Foundation + +struct ProposerSlashing { + let proposerIndex: ValidatorIndex + let header1: BeaconBlockHeader + let header2: BeaconBlockHeader +} diff --git a/Sources/BeaconChain/Operations/Transfer.swift b/Sources/BeaconChain/Operations/Transfer.swift new file mode 100644 index 0000000..2e25acf --- /dev/null +++ b/Sources/BeaconChain/Operations/Transfer.swift @@ -0,0 +1,11 @@ +import Foundation + +struct Transfer { + let sender: ValidatorIndex + let recipient: ValidatorIndex + let amount: Gwei + let fee: Gwei + let slot: Slot + let pubkey: BLSPubKey + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/Operations/VoluntaryExit.swift b/Sources/BeaconChain/Operations/VoluntaryExit.swift new file mode 100644 index 0000000..452a273 --- /dev/null +++ b/Sources/BeaconChain/Operations/VoluntaryExit.swift @@ -0,0 +1,7 @@ +import Foundation + +struct VoluntaryExit { + let epoch: Epoch + let validatorIndex: ValidatorIndex + let signature: BLSSignature +} From ccc8079e69350fc7bdf04f3f5c2098e30657fb8a Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 10:12:46 -0400 Subject: [PATCH 19/41] BeaconBLock --- Sources/BeaconChain/BeaconBlock/BeaconBlock.swift | 9 +++++++++ .../BeaconChain/BeaconBlock/BeaconBlockBody.swift | 13 +++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 Sources/BeaconChain/BeaconBlock/BeaconBlock.swift create mode 100644 Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift new file mode 100644 index 0000000..6de493e --- /dev/null +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift @@ -0,0 +1,9 @@ +import Foundation + +struct BeaconBlock { + let slot: Slot + let parentRoot: Hash + let stateRoot: Hash + let body: BeaconBlockBody + let signature: BLSSignature +} diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift new file mode 100644 index 0000000..92ab6a8 --- /dev/null +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift @@ -0,0 +1,13 @@ +import Foundation + +struct BeaconBlockBody { + let randaoReveal: BLSSignature + let eth1Data: Eth1Data + let graffiti: Data + let proposerSlashings: [ProposerSlashing] + let attesterSlashings: [AttesterSlashing] + let attestations: [Attestation] + let deposits: [Deposit] + let voluntaryExits: [VoluntaryExit] + let transfers: [Transfer] +} From a262c5004d6a74bee34f840e8df3e20408eeec07 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 11:08:12 -0400 Subject: [PATCH 20/41] updated --- Sources/BeaconChain/BeaconChain.swift | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Sources/BeaconChain/BeaconChain.swift b/Sources/BeaconChain/BeaconChain.swift index e237141..86ae815 100644 --- a/Sources/BeaconChain/BeaconChain.swift +++ b/Sources/BeaconChain/BeaconChain.swift @@ -1,4 +1,29 @@ import Foundation -class BeaconChain { +struct BeaconChain { + let genesisTime: UInt64 + let slot: Slot + let fork: Fork + let latestBlockHeader: BeaconBlockHeader + let blockRoots: [Hash] + let stateRoots: [Hash] + let historicalRoots: [Hash] + let eth1Data: Eth1Data + let eth1DataVotes: [Eth1Data] + let eth1DepositIndex: UInt64 + let validators: [Validator] + let balances: [Gwei] + let startShard: Shard + let randaoMixes: [Hash] + let activeIndexRoots: [Hash] + let compactCommitteesRoots: [Hash] + let slashings: [Gwei] + let previousEpochAttestations: [PendingAttestation] + let currentEpochAttestations: [PendingAttestation] + let previousCrosslinks: [Crosslink] + let currentCrosslinks: [Crosslink] + let justificationBits: [Bool] + let previousJustifiedCheckpoint: Checkpoint + let currentJustifiedCheckpoint: Checkpoint + let finalizedCheckpoint: Checkpoint } From 2de241549dcb67f7c092c2af01cbeb6af36e0c85 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 15:08:14 -0400 Subject: [PATCH 21/41] docs --- Makefile | 2 +- .../Attestation/AttestationData.swift | 19 +++++++++--- .../AttestationDataAndCustodyBit.swift | 7 +++-- .../Attestation/IndexedAttestation.swift | 2 +- .../BeaconChain/BeaconBlock/BeaconBlock.swift | 23 ++++++++++---- .../BeaconBlock/BeaconBlockBody.swift | 28 +++++++++++------ .../BeaconBlock/BeaconBlockHeader.swift | 21 ++++++++++--- Sources/BeaconChain/Checkpoint.swift | 2 +- Sources/BeaconChain/Crosslink.swift | 2 +- Sources/BeaconChain/DepositData.swift | 12 ++++++- Sources/BeaconChain/Eth1Data.swift | 17 +++++++--- .../BeaconChain/Operations/Attestation.swift | 20 +++++++++--- .../Operations/AttesterSlashing.swift | 12 +++++-- Sources/BeaconChain/Operations/Deposit.swift | 11 +++++-- .../Operations/ProposerSlashing.swift | 16 +++++++--- Sources/BeaconChain/Operations/Transfer.swift | 31 ++++++++++++++----- .../Operations/VoluntaryExit.swift | 15 ++++++--- Sources/BeaconChain/Types.swift | 20 ++++++------ 18 files changed, 185 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index 03575da..3f3e11c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ lint: swiftlint documentation: - jazzy --author "yeeth" --author_url https://yeeth.af --github_url https://github.com/yeeth/BeaconChain.swift + jazzy --author "yeeth" --author_url https://yeeth.af --github_url https://github.com/yeeth/BeaconChain.swift rm -rf build/ xcode: diff --git a/Sources/BeaconChain/Attestation/AttestationData.swift b/Sources/BeaconChain/Attestation/AttestationData.swift index 6ca7245..fa2b280 100644 --- a/Sources/BeaconChain/Attestation/AttestationData.swift +++ b/Sources/BeaconChain/Attestation/AttestationData.swift @@ -1,8 +1,17 @@ import Foundation -struct AttestationData { - let beaconBlockRoot: Hash - let source: Checkpoint - let target: Checkpoint - let crosslink: Crosslink +/// AttestationData is the main component that is signed by each validator. +public struct AttestationData { + + /// Block root of the beacon block seen as the head of the chain at the assigned slot. + public let beaconBlockRoot: Hash + + /// The most recent justified checkpoint in the BeaconState at the assigned slot. + public let source: Checkpoint + + /// The checkpoint attempting to be justified (the current epoch and epoch boundary block). + public let target: Checkpoint + + /// The crosslink attemping to be formed for the assigned shard. + public let crosslink: Crosslink } diff --git a/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift b/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift index 8e81b1f..0a7b5de 100644 --- a/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift +++ b/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift @@ -1,6 +1,7 @@ import Foundation -struct AttestationDataAndCustodyBit { - let data: AttestationData - let custodyBit: Bool // @todo probably not the best? +/// The actual message signed by validators. +public struct AttestationDataAndCustodyBit { + public let data: AttestationData + public let custodyBit: Bool // @todo probably not the best? } diff --git a/Sources/BeaconChain/Attestation/IndexedAttestation.swift b/Sources/BeaconChain/Attestation/IndexedAttestation.swift index 39f0a51..ef39a97 100644 --- a/Sources/BeaconChain/Attestation/IndexedAttestation.swift +++ b/Sources/BeaconChain/Attestation/IndexedAttestation.swift @@ -1,6 +1,6 @@ import Foundation -struct IndexedAttestation { +public struct IndexedAttestation { let custodyBit0Indices: [ValidatorIndex] let custodyBit1Indices: [ValidatorIndex] let data: AttestationData diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift index 6de493e..cbb853e 100644 --- a/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift @@ -1,9 +1,20 @@ import Foundation -struct BeaconBlock { - let slot: Slot - let parentRoot: Hash - let stateRoot: Hash - let body: BeaconBlockBody - let signature: BLSSignature +/// This can be thought of as the main container/header for a beacon block. +public struct BeaconBlock { + + /// The slot for which this block is created. Must be greater than the slot of the block defined by `parentRoot`. + public let slot: Slot + + /// The block root of the parent block, forming a block chain. + public let parentRoot: Hash + + /// The hash root of the post state of running the state transition through this block. + public let stateRoot: Hash + + /// Contains all of the aforementioned beacon operations objects as well as a few supplemental fields. + public let body: BeaconBlockBody + + /// Signature of the block by the block proposer. + public let signature: BLSSignature } diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift index 92ab6a8..5fcc309 100644 --- a/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift @@ -1,13 +1,21 @@ import Foundation -struct BeaconBlockBody { - let randaoReveal: BLSSignature - let eth1Data: Eth1Data - let graffiti: Data - let proposerSlashings: [ProposerSlashing] - let attesterSlashings: [AttesterSlashing] - let attestations: [Attestation] - let deposits: [Deposit] - let voluntaryExits: [VoluntaryExit] - let transfers: [Transfer] +public struct BeaconBlockBody { + + /// The signature of the current epoch (by the block proposer) and, + /// when mixed in with the other validators’ reveals, consitutes the seed for randomness. + public let randaoReveal: BLSSignature + + /// A vote on recent data the Eth1 chain. + public let eth1Data: Eth1Data + + /// This is a space for validators to decorate as they choose. It has no define in-protocol use. + public let graffiti: Data + + public let proposerSlashings: [ProposerSlashing] + public let attesterSlashings: [AttesterSlashing] + public let attestations: [Attestation] + public let deposits: [Deposit] + public let voluntaryExits: [VoluntaryExit] + public let transfers: [Transfer] } diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift b/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift index b0be78e..36c8935 100644 --- a/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift +++ b/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift @@ -1,9 +1,20 @@ import Foundation -struct BeaconBlockHeader { - let slot: Slot - let parentRoot: Hash - let stateRoot: Hash +/// The Header of a Beacon Block. +public struct BeaconBlockHeader { + + /// The slot for which this block is created. Must be greater than the slot of the block defined by `parentRoot`. + public let slot: Slot + + /// The block root of the parent block, forming a block chain. + public let parentRoot: Hash + + /// The hash root of the post state of running the state transition through this block. + public let stateRoot: Hash + + /// The hash root of the block body. let bodyRoot: Hash - let signature: BLSSignature + + /// Signature of the block by the block proposer. + public let signature: BLSSignature } diff --git a/Sources/BeaconChain/Checkpoint.swift b/Sources/BeaconChain/Checkpoint.swift index 10c7a3d..0af9e49 100644 --- a/Sources/BeaconChain/Checkpoint.swift +++ b/Sources/BeaconChain/Checkpoint.swift @@ -1,6 +1,6 @@ import Foundation -struct Checkpoint { +public struct Checkpoint { let epoch: Epoch let root: Hash } diff --git a/Sources/BeaconChain/Crosslink.swift b/Sources/BeaconChain/Crosslink.swift index 887f5c1..1bf7a50 100644 --- a/Sources/BeaconChain/Crosslink.swift +++ b/Sources/BeaconChain/Crosslink.swift @@ -1,6 +1,6 @@ import Foundation -struct Crosslink { +public struct Crosslink { let shard: Shard let parentRoot: Hash let startEpoch: Epoch diff --git a/Sources/BeaconChain/DepositData.swift b/Sources/BeaconChain/DepositData.swift index e4313bc..4ae07cb 100644 --- a/Sources/BeaconChain/DepositData.swift +++ b/Sources/BeaconChain/DepositData.swift @@ -1,8 +1,18 @@ import Foundation -struct DepositData { +/// The DepositData submit to the deposit contract to be verified using the proof against the deposit root. +public struct DepositData { + + /// BLS12-381 pubkey to be used to sign messages by the validator. let pubkey: BLSPubKey + + /// The hash of an offline pubkey to be used to withdraw the staked funds after exiting. + /// This key is not used actively in validation and can be kept in cold storage. let withdrawalCredentials: Hash + + /// Amount in Gwei that was deposited. let amount: Gwei + + /// This is used as a one-time “proof of custody” required for securely using BLS keys. let signature: BLSSignature } diff --git a/Sources/BeaconChain/Eth1Data.swift b/Sources/BeaconChain/Eth1Data.swift index e1fa4a7..7eacaab 100644 --- a/Sources/BeaconChain/Eth1Data.swift +++ b/Sources/BeaconChain/Eth1Data.swift @@ -1,7 +1,16 @@ import Foundation -struct Eth1Data { - let depositRoot: Hash - let depositCount: UInt64 - let blockHash: Hash +/// A vote on recent data the Eth1 chain. +public struct Eth1Data { + + /// The SSZ List hash_tree_root of the deposits in the deposit contract. + public let depositRoot: Hash + + /// The number of deposits that have occured thusfar. + public let depositCount: UInt64 + + /// The eth1 block hash that contained the deposit_root. This block_hash + /// might be used for finalization of the Eth1 chain in the future (similar to how the FFG contract was going to + /// be used to finalize the eth1 chain). + public let blockHash: Hash } diff --git a/Sources/BeaconChain/Operations/Attestation.swift b/Sources/BeaconChain/Operations/Attestation.swift index 4bbef22..d83bc25 100644 --- a/Sources/BeaconChain/Operations/Attestation.swift +++ b/Sources/BeaconChain/Operations/Attestation.swift @@ -1,8 +1,18 @@ import Foundation -struct Attestation { - let aggregationBits: [Bool] - let data: AttestationData - let custodyBits: [Bool] - let signature: BLSSignature +/// Primary message type that validators create for consensus. +public struct Attestation { + + /// Stores a single bit for each member of the committee assigning a value of 1 to each validator that participated + /// in this aggregate signature. + public let aggregationBits: [Bool] + + /// The AttestationData that was signed by the validator or committee of validators. + public let data: AttestationData + + /// Represents each committee member’s “proof of custody” bit (0 if non-participating). + public let custodyBits: [Bool] + + /// The aggregate BLS signature of the data. + public let signature: BLSSignature } diff --git a/Sources/BeaconChain/Operations/AttesterSlashing.swift b/Sources/BeaconChain/Operations/AttesterSlashing.swift index b806728..cfe53ea 100644 --- a/Sources/BeaconChain/Operations/AttesterSlashing.swift +++ b/Sources/BeaconChain/Operations/AttesterSlashing.swift @@ -1,6 +1,12 @@ import Foundation -struct AttesterSlashing { - let attestation1: IndexedAttestation - let attestation2: IndexedAttestation +/// Beacon attesters can be slashed if they sign two conflicting attestations where conflicting is defined by +/// is_slashable_attestation_data which checks for the Casper FFG “double” and “surround” vote conditions. +public struct AttesterSlashing { + + /// The first of the two slashable attestations. Note that this is in “indexed” form. + public let attestation1: IndexedAttestation + + /// The first of the two slashable attestations. Note that this is in “indexed” form. + public let attestation2: IndexedAttestation } diff --git a/Sources/BeaconChain/Operations/Deposit.swift b/Sources/BeaconChain/Operations/Deposit.swift index 837f362..c102b1c 100644 --- a/Sources/BeaconChain/Operations/Deposit.swift +++ b/Sources/BeaconChain/Operations/Deposit.swift @@ -1,6 +1,11 @@ import Foundation -struct Deposit { - let proof: [Hash] - let data: DepositData +/// Represents incoming validator deposits from the eth1 chain deposit contract. +public struct Deposit { + + /// The merkle proof against the BeaconState current Eth1Data.root + public let proof: [Hash] + + /// The DepositData submit to the deposit contract to be verified using the proof against the deposit root. + public let data: DepositData } diff --git a/Sources/BeaconChain/Operations/ProposerSlashing.swift b/Sources/BeaconChain/Operations/ProposerSlashing.swift index 93adf2b..bedfe8f 100644 --- a/Sources/BeaconChain/Operations/ProposerSlashing.swift +++ b/Sources/BeaconChain/Operations/ProposerSlashing.swift @@ -1,7 +1,15 @@ import Foundation -struct ProposerSlashing { - let proposerIndex: ValidatorIndex - let header1: BeaconBlockHeader - let header2: BeaconBlockHeader +/// Beacon block proposers can be slashed if they signed two different beacon blocks for the same epoch. +/// ProposerSlashing contains proof that such a slashable offense has occurred. +public struct ProposerSlashing { + + /// `ValidatorIndex` of the validator to be slashed for double proposing. + public let proposerIndex: ValidatorIndex + + /// The header of the first of the two slashable beacon blocks. + public let header1: BeaconBlockHeader + + /// The header of the second of the two slashable beacon blocks. + public let header2: BeaconBlockHeader } diff --git a/Sources/BeaconChain/Operations/Transfer.swift b/Sources/BeaconChain/Operations/Transfer.swift index 2e25acf..0d6f0dd 100644 --- a/Sources/BeaconChain/Operations/Transfer.swift +++ b/Sources/BeaconChain/Operations/Transfer.swift @@ -1,11 +1,26 @@ import Foundation -struct Transfer { - let sender: ValidatorIndex - let recipient: ValidatorIndex - let amount: Gwei - let fee: Gwei - let slot: Slot - let pubkey: BLSPubKey - let signature: BLSSignature +/// Allows validators to transfer balances. +public struct Transfer { + + /// Validator index of the sender of funds. + public let sender: ValidatorIndex + + /// Validator index of the recipient of funds. + public let recipient: ValidatorIndex + + /// Amount in Gwei to send. + public let amount: Gwei + + /// Fee in Gwei to be paid to the block proposer for including the transfer. + public let fee: Gwei + + /// The specific slot that this signed `Transfer` can be included on chain. prevents replay attacks. + public let slot: Slot + + /// The withdrawal pubkey of the sender. The hash of this pubkey must match the senders withdrawalCredentials. + public let pubkey: BLSPubKey + + /// The signature of the `Transfer` signed by the `transfer.pubkey`. + public let signature: BLSSignature } diff --git a/Sources/BeaconChain/Operations/VoluntaryExit.swift b/Sources/BeaconChain/Operations/VoluntaryExit.swift index 452a273..923bd36 100644 --- a/Sources/BeaconChain/Operations/VoluntaryExit.swift +++ b/Sources/BeaconChain/Operations/VoluntaryExit.swift @@ -1,7 +1,14 @@ import Foundation -struct VoluntaryExit { - let epoch: Epoch - let validatorIndex: ValidatorIndex - let signature: BLSSignature +/// Message type that allows a validator to voluntarily exit validation duties. +public struct VoluntaryExit { + + /// Minimum epoch at which this exit can be included on chain. Helps prevent accidental/nefarious use in chain reorgs/forks. + public let epoch: Epoch + + /// Index of validator exiting. + public let validatorIndex: ValidatorIndex + + /// Signature of the `VoluntaryExit` by the pubkey associated with the + public let signature: BLSSignature } diff --git a/Sources/BeaconChain/Types.swift b/Sources/BeaconChain/Types.swift index c9ad2a2..cb4345f 100644 --- a/Sources/BeaconChain/Types.swift +++ b/Sources/BeaconChain/Types.swift @@ -1,12 +1,12 @@ import Foundation -typealias Slot = UInt64 -typealias Epoch = UInt64 -typealias Shard = UInt64 -typealias ValidatorIndex = UInt64 -typealias Gwei = UInt64 -typealias Hash = Data -typealias Version = UInt32 -typealias Domain = UInt64 -typealias BLSPubKey = Data -typealias BLSSignature = Data +public typealias Slot = UInt64 +public typealias Epoch = UInt64 +public typealias Shard = UInt64 +public typealias ValidatorIndex = UInt64 +public typealias Gwei = UInt64 +public typealias Hash = Data +public typealias Version = UInt32 +public typealias Domain = UInt64 +public typealias BLSPubKey = Data +public typealias BLSSignature = Data From 06b72840c6d4461923cb7cc7dddc28ec0664b696 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 15:14:05 -0400 Subject: [PATCH 22/41] stuff added --- Sources/BeaconChain/DomainType.swift | 6 ++++++ Sources/BeaconChain/Types.swift | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 Sources/BeaconChain/DomainType.swift diff --git a/Sources/BeaconChain/DomainType.swift b/Sources/BeaconChain/DomainType.swift new file mode 100644 index 0000000..9677795 --- /dev/null +++ b/Sources/BeaconChain/DomainType.swift @@ -0,0 +1,6 @@ +import Foundation + +/// A signature domain type +public enum DomainType: UInt64 { + case beaconProposer, randao, attestation, deposit, voluntaryExit, transfer +} diff --git a/Sources/BeaconChain/Types.swift b/Sources/BeaconChain/Types.swift index cb4345f..728512c 100644 --- a/Sources/BeaconChain/Types.swift +++ b/Sources/BeaconChain/Types.swift @@ -1,12 +1,31 @@ import Foundation +/// A slot number. public typealias Slot = UInt64 + +/// An epoch number. public typealias Epoch = UInt64 + +/// A shard number. public typealias Shard = UInt64 + +/// A validator registry index. public typealias ValidatorIndex = UInt64 + +/// An amount in Gwei. public typealias Gwei = UInt64 + +/// A hash. public typealias Hash = Data + +/// A fork version number. public typealias Version = UInt32 + +/// A signature domain. public typealias Domain = UInt64 + +/// A BLS12-381 public key. public typealias BLSPubKey = Data + +/// A BLS12-381 signature. public typealias BLSSignature = Data From f55ff2297b89ac30b4cee5500b3bb8c27142b271 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 15:33:24 -0400 Subject: [PATCH 23/41] added docs --- Sources/BeaconChain/Enums/DomainType.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/BeaconChain/Enums/DomainType.swift b/Sources/BeaconChain/Enums/DomainType.swift index 337bab1..981d683 100644 --- a/Sources/BeaconChain/Enums/DomainType.swift +++ b/Sources/BeaconChain/Enums/DomainType.swift @@ -1,5 +1,6 @@ import Foundation -enum DomainType: UInt32 { +/// A signature domain type. +public enum DomainType: UInt32 { case beaconProposer, randao, attestation, deposit, voluntaryExit, transfer } From 9b881811f80d2ac60e68aec4814f112d8a734257 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 15:34:52 -0400 Subject: [PATCH 24/41] public --- Sources/BeaconChain/DepositData.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/BeaconChain/DepositData.swift b/Sources/BeaconChain/DepositData.swift index 4ae07cb..7f26969 100644 --- a/Sources/BeaconChain/DepositData.swift +++ b/Sources/BeaconChain/DepositData.swift @@ -4,15 +4,15 @@ import Foundation public struct DepositData { /// BLS12-381 pubkey to be used to sign messages by the validator. - let pubkey: BLSPubKey + public let pubkey: BLSPubKey /// The hash of an offline pubkey to be used to withdraw the staked funds after exiting. /// This key is not used actively in validation and can be kept in cold storage. - let withdrawalCredentials: Hash + public let withdrawalCredentials: Hash /// Amount in Gwei that was deposited. - let amount: Gwei + public let amount: Gwei /// This is used as a one-time “proof of custody” required for securely using BLS keys. - let signature: BLSSignature + public let signature: BLSSignature } From bf342160e018d2c7754c0169f003ba5b6085b782 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 15:48:55 -0400 Subject: [PATCH 25/41] rm --- Sources/BeaconChain/DomainType.swift | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 Sources/BeaconChain/DomainType.swift diff --git a/Sources/BeaconChain/DomainType.swift b/Sources/BeaconChain/DomainType.swift deleted file mode 100644 index 9677795..0000000 --- a/Sources/BeaconChain/DomainType.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -/// A signature domain type -public enum DomainType: UInt64 { - case beaconProposer, randao, attestation, deposit, voluntaryExit, transfer -} From 0ce32eb697ac53cf1c94bfa1793241523efabb66 Mon Sep 17 00:00:00 2001 From: Dean Eigenmann Date: Wed, 3 Jul 2019 15:59:28 -0400 Subject: [PATCH 26/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cac716c..3d08e4d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.com/yeeth/BeaconChain.swift.svg?branch=master)](https://travis-ci.com/yeeth/BeaconChain.swift) [![License](https://img.shields.io/github/license/yeeth/BeaconChain.swift.svg)](LICENSE) -Ethereum 2.0 beacon chain implementation based on the official [specification](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md). The implemented specification version is [bed88](https://github.com/ethereum/eth2.0-specs/tree/bed888810d5c99cd114adc9907c16268a2a285a9). +Ethereum 2.0 beacon chain implementation based on the official [specification](https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md). The implemented specification version is [4ea79](https://github.com/ethereum/eth2.0-specs/tree/4ea79ee13b48c405c5a86cb3766af3ca0d3f6633). ## Contributing From dd219a9c6d03ddbb62a7cb6336a029c9604bd120 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 3 Jul 2019 16:26:21 -0400 Subject: [PATCH 27/41] type --- Sources/BeaconChain/Attestation/AttestationData.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/BeaconChain/Attestation/AttestationData.swift b/Sources/BeaconChain/Attestation/AttestationData.swift index fa2b280..f104908 100644 --- a/Sources/BeaconChain/Attestation/AttestationData.swift +++ b/Sources/BeaconChain/Attestation/AttestationData.swift @@ -12,6 +12,6 @@ public struct AttestationData { /// The checkpoint attempting to be justified (the current epoch and epoch boundary block). public let target: Checkpoint - /// The crosslink attemping to be formed for the assigned shard. + /// The crosslink attempting to be formed for the assigned shard. public let crosslink: Crosslink } From b85a3004b6f42b1d20a614aa9994e52a3de98634 Mon Sep 17 00:00:00 2001 From: decanus Date: Wed, 10 Jul 2019 13:19:41 -0400 Subject: [PATCH 28/41] xor, integer_squareroot --- Sources/BeaconChain/Extensions/UInt64.swift | 18 ++++++++++++++++++ Sources/BeaconChain/Operators/XOR.swift | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 Sources/BeaconChain/Extensions/UInt64.swift create mode 100644 Sources/BeaconChain/Operators/XOR.swift diff --git a/Sources/BeaconChain/Extensions/UInt64.swift b/Sources/BeaconChain/Extensions/UInt64.swift new file mode 100644 index 0000000..16a097f --- /dev/null +++ b/Sources/BeaconChain/Extensions/UInt64.swift @@ -0,0 +1,18 @@ +import Foundation + +extension UInt64 { + + /// Return the largest integer ``x`` such that ``x**2 <= n``. + func sqrt() -> UInt64 { + var x = self + var y = (x + 1) / 2 + + while y < x { + x = y + y = (x + self / x) / 2 + } + + return x + } + +} diff --git a/Sources/BeaconChain/Operators/XOR.swift b/Sources/BeaconChain/Operators/XOR.swift new file mode 100644 index 0000000..6771c4c --- /dev/null +++ b/Sources/BeaconChain/Operators/XOR.swift @@ -0,0 +1,15 @@ +import Foundation + +extension Data { + + /// Return the exclusive-or of two byte strings. + static func ^(left: Data, right: Data) -> Data { + var temp = left + + for i in 0.. Date: Sat, 13 Jul 2019 19:56:18 +0200 Subject: [PATCH 29/41] moved structures --- Sources/BeaconChain/BeaconChain.swift | 26 +---------------- .../Attestation/AttestationData.swift | 0 .../AttestationDataAndCustodyBit.swift | 0 .../Attestation/IndexedAttestation.swift | 0 .../Attestation/PendingAttestation.swift | 0 .../BeaconBlock/BeaconBlock.swift | 0 .../BeaconBlock/BeaconBlockBody.swift | 0 .../BeaconBlock/BeaconBlockHeader.swift | 0 .../DataStructures/BeaconState.swift | 29 +++++++++++++++++++ .../{ => DataStructures}/Checkpoint.swift | 0 .../CompactCommittee.swift | 0 .../{ => DataStructures}/Crosslink.swift | 0 .../{ => DataStructures}/DepositData.swift | 0 .../{ => DataStructures}/Eth1Data.swift | 0 .../{ => DataStructures}/Fork.swift | 0 .../HistoricalBatch.swift | 0 .../Operations/Attestation.swift | 0 .../Operations/AttesterSlashing.swift | 0 .../Operations/Deposit.swift | 0 .../Operations/ProposerSlashing.swift | 0 .../Operations/Transfer.swift | 0 .../Operations/VoluntaryExit.swift | 0 .../{ => DataStructures}/Validator.swift | 0 23 files changed, 30 insertions(+), 25 deletions(-) rename Sources/BeaconChain/{ => DataStructures}/Attestation/AttestationData.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Attestation/AttestationDataAndCustodyBit.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Attestation/IndexedAttestation.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Attestation/PendingAttestation.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/BeaconBlock/BeaconBlock.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/BeaconBlock/BeaconBlockBody.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/BeaconBlock/BeaconBlockHeader.swift (100%) create mode 100644 Sources/BeaconChain/DataStructures/BeaconState.swift rename Sources/BeaconChain/{ => DataStructures}/Checkpoint.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/CompactCommittee.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Crosslink.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/DepositData.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Eth1Data.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Fork.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/HistoricalBatch.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/Attestation.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/AttesterSlashing.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/Deposit.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/ProposerSlashing.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/Transfer.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Operations/VoluntaryExit.swift (100%) rename Sources/BeaconChain/{ => DataStructures}/Validator.swift (100%) diff --git a/Sources/BeaconChain/BeaconChain.swift b/Sources/BeaconChain/BeaconChain.swift index 86ae815..c4a1350 100644 --- a/Sources/BeaconChain/BeaconChain.swift +++ b/Sources/BeaconChain/BeaconChain.swift @@ -1,29 +1,5 @@ import Foundation struct BeaconChain { - let genesisTime: UInt64 - let slot: Slot - let fork: Fork - let latestBlockHeader: BeaconBlockHeader - let blockRoots: [Hash] - let stateRoots: [Hash] - let historicalRoots: [Hash] - let eth1Data: Eth1Data - let eth1DataVotes: [Eth1Data] - let eth1DepositIndex: UInt64 - let validators: [Validator] - let balances: [Gwei] - let startShard: Shard - let randaoMixes: [Hash] - let activeIndexRoots: [Hash] - let compactCommitteesRoots: [Hash] - let slashings: [Gwei] - let previousEpochAttestations: [PendingAttestation] - let currentEpochAttestations: [PendingAttestation] - let previousCrosslinks: [Crosslink] - let currentCrosslinks: [Crosslink] - let justificationBits: [Bool] - let previousJustifiedCheckpoint: Checkpoint - let currentJustifiedCheckpoint: Checkpoint - let finalizedCheckpoint: Checkpoint + } diff --git a/Sources/BeaconChain/Attestation/AttestationData.swift b/Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift similarity index 100% rename from Sources/BeaconChain/Attestation/AttestationData.swift rename to Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift diff --git a/Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift b/Sources/BeaconChain/DataStructures/Attestation/AttestationDataAndCustodyBit.swift similarity index 100% rename from Sources/BeaconChain/Attestation/AttestationDataAndCustodyBit.swift rename to Sources/BeaconChain/DataStructures/Attestation/AttestationDataAndCustodyBit.swift diff --git a/Sources/BeaconChain/Attestation/IndexedAttestation.swift b/Sources/BeaconChain/DataStructures/Attestation/IndexedAttestation.swift similarity index 100% rename from Sources/BeaconChain/Attestation/IndexedAttestation.swift rename to Sources/BeaconChain/DataStructures/Attestation/IndexedAttestation.swift diff --git a/Sources/BeaconChain/Attestation/PendingAttestation.swift b/Sources/BeaconChain/DataStructures/Attestation/PendingAttestation.swift similarity index 100% rename from Sources/BeaconChain/Attestation/PendingAttestation.swift rename to Sources/BeaconChain/DataStructures/Attestation/PendingAttestation.swift diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlock.swift b/Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlock.swift similarity index 100% rename from Sources/BeaconChain/BeaconBlock/BeaconBlock.swift rename to Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlock.swift diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift b/Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlockBody.swift similarity index 100% rename from Sources/BeaconChain/BeaconBlock/BeaconBlockBody.swift rename to Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlockBody.swift diff --git a/Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift b/Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlockHeader.swift similarity index 100% rename from Sources/BeaconChain/BeaconBlock/BeaconBlockHeader.swift rename to Sources/BeaconChain/DataStructures/BeaconBlock/BeaconBlockHeader.swift diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift new file mode 100644 index 0000000..86ae815 --- /dev/null +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -0,0 +1,29 @@ +import Foundation + +struct BeaconChain { + let genesisTime: UInt64 + let slot: Slot + let fork: Fork + let latestBlockHeader: BeaconBlockHeader + let blockRoots: [Hash] + let stateRoots: [Hash] + let historicalRoots: [Hash] + let eth1Data: Eth1Data + let eth1DataVotes: [Eth1Data] + let eth1DepositIndex: UInt64 + let validators: [Validator] + let balances: [Gwei] + let startShard: Shard + let randaoMixes: [Hash] + let activeIndexRoots: [Hash] + let compactCommitteesRoots: [Hash] + let slashings: [Gwei] + let previousEpochAttestations: [PendingAttestation] + let currentEpochAttestations: [PendingAttestation] + let previousCrosslinks: [Crosslink] + let currentCrosslinks: [Crosslink] + let justificationBits: [Bool] + let previousJustifiedCheckpoint: Checkpoint + let currentJustifiedCheckpoint: Checkpoint + let finalizedCheckpoint: Checkpoint +} diff --git a/Sources/BeaconChain/Checkpoint.swift b/Sources/BeaconChain/DataStructures/Checkpoint.swift similarity index 100% rename from Sources/BeaconChain/Checkpoint.swift rename to Sources/BeaconChain/DataStructures/Checkpoint.swift diff --git a/Sources/BeaconChain/CompactCommittee.swift b/Sources/BeaconChain/DataStructures/CompactCommittee.swift similarity index 100% rename from Sources/BeaconChain/CompactCommittee.swift rename to Sources/BeaconChain/DataStructures/CompactCommittee.swift diff --git a/Sources/BeaconChain/Crosslink.swift b/Sources/BeaconChain/DataStructures/Crosslink.swift similarity index 100% rename from Sources/BeaconChain/Crosslink.swift rename to Sources/BeaconChain/DataStructures/Crosslink.swift diff --git a/Sources/BeaconChain/DepositData.swift b/Sources/BeaconChain/DataStructures/DepositData.swift similarity index 100% rename from Sources/BeaconChain/DepositData.swift rename to Sources/BeaconChain/DataStructures/DepositData.swift diff --git a/Sources/BeaconChain/Eth1Data.swift b/Sources/BeaconChain/DataStructures/Eth1Data.swift similarity index 100% rename from Sources/BeaconChain/Eth1Data.swift rename to Sources/BeaconChain/DataStructures/Eth1Data.swift diff --git a/Sources/BeaconChain/Fork.swift b/Sources/BeaconChain/DataStructures/Fork.swift similarity index 100% rename from Sources/BeaconChain/Fork.swift rename to Sources/BeaconChain/DataStructures/Fork.swift diff --git a/Sources/BeaconChain/HistoricalBatch.swift b/Sources/BeaconChain/DataStructures/HistoricalBatch.swift similarity index 100% rename from Sources/BeaconChain/HistoricalBatch.swift rename to Sources/BeaconChain/DataStructures/HistoricalBatch.swift diff --git a/Sources/BeaconChain/Operations/Attestation.swift b/Sources/BeaconChain/DataStructures/Operations/Attestation.swift similarity index 100% rename from Sources/BeaconChain/Operations/Attestation.swift rename to Sources/BeaconChain/DataStructures/Operations/Attestation.swift diff --git a/Sources/BeaconChain/Operations/AttesterSlashing.swift b/Sources/BeaconChain/DataStructures/Operations/AttesterSlashing.swift similarity index 100% rename from Sources/BeaconChain/Operations/AttesterSlashing.swift rename to Sources/BeaconChain/DataStructures/Operations/AttesterSlashing.swift diff --git a/Sources/BeaconChain/Operations/Deposit.swift b/Sources/BeaconChain/DataStructures/Operations/Deposit.swift similarity index 100% rename from Sources/BeaconChain/Operations/Deposit.swift rename to Sources/BeaconChain/DataStructures/Operations/Deposit.swift diff --git a/Sources/BeaconChain/Operations/ProposerSlashing.swift b/Sources/BeaconChain/DataStructures/Operations/ProposerSlashing.swift similarity index 100% rename from Sources/BeaconChain/Operations/ProposerSlashing.swift rename to Sources/BeaconChain/DataStructures/Operations/ProposerSlashing.swift diff --git a/Sources/BeaconChain/Operations/Transfer.swift b/Sources/BeaconChain/DataStructures/Operations/Transfer.swift similarity index 100% rename from Sources/BeaconChain/Operations/Transfer.swift rename to Sources/BeaconChain/DataStructures/Operations/Transfer.swift diff --git a/Sources/BeaconChain/Operations/VoluntaryExit.swift b/Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift similarity index 100% rename from Sources/BeaconChain/Operations/VoluntaryExit.swift rename to Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift diff --git a/Sources/BeaconChain/Validator.swift b/Sources/BeaconChain/DataStructures/Validator.swift similarity index 100% rename from Sources/BeaconChain/Validator.swift rename to Sources/BeaconChain/DataStructures/Validator.swift From 8674f921dd42375dd26ecb2117dda5d310940cf0 Mon Sep 17 00:00:00 2001 From: decanus Date: Sat, 13 Jul 2019 19:58:06 +0200 Subject: [PATCH 30/41] renamed --- Sources/BeaconChain/DataStructures/BeaconState.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift index 86ae815..3a01377 100644 --- a/Sources/BeaconChain/DataStructures/BeaconState.swift +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -1,6 +1,6 @@ import Foundation -struct BeaconChain { +struct BeaconState { let genesisTime: UInt64 let slot: Slot let fork: Fork From 1cf2ad91fbf36c30a510c63aa0e4b9c5a5ce0a9b Mon Sep 17 00:00:00 2001 From: decanus Date: Fri, 19 Jul 2019 14:19:49 -0500 Subject: [PATCH 31/41] stubs --- Sources/BeaconChain/BLS.swift | 18 ++++++++++++++++++ Sources/BeaconChain/Crypto.swift | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 Sources/BeaconChain/BLS.swift create mode 100644 Sources/BeaconChain/Crypto.swift diff --git a/Sources/BeaconChain/BLS.swift b/Sources/BeaconChain/BLS.swift new file mode 100644 index 0000000..00088ff --- /dev/null +++ b/Sources/BeaconChain/BLS.swift @@ -0,0 +1,18 @@ +import Foundation + +// @todo this will be in a seperate library + +class BLS { + + func verify(pubkey: Data, hash: Hash, signature: Data, domain: UInt64) -> Bool { + return false + } + + func verify(pubkeys: [Data], hashes: [Hash], signature: Data, domain: UInt64) -> Bool { + return false + } + + func aggregate(pubkeys: [Data]) -> Data { + fatalError("not yet implemented") + } +} diff --git a/Sources/BeaconChain/Crypto.swift b/Sources/BeaconChain/Crypto.swift new file mode 100644 index 0000000..b5ee6d9 --- /dev/null +++ b/Sources/BeaconChain/Crypto.swift @@ -0,0 +1,18 @@ +import Foundation + +// @todo this will be in a seperate library + +class SSZ { + + func hash(_ data: Data) -> Hash { + fatalError("not yet implemented") + } + + func hashTreeRoot(_ data: Data) -> Hash { + fatalError("not yet implemented") + } + + func signingRoot(_ data: Any) -> Hash { + fatalError("not yet implemented") + } +} From e9cf06e9a754a6e8f0ae34b8ff40dd6e352e8131 Mon Sep 17 00:00:00 2001 From: decanus Date: Fri, 19 Jul 2019 14:25:22 -0500 Subject: [PATCH 32/41] validator predicates --- .../BeaconChain/DataStructures/Validator.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Sources/BeaconChain/DataStructures/Validator.swift b/Sources/BeaconChain/DataStructures/Validator.swift index 66f970c..ad17440 100644 --- a/Sources/BeaconChain/DataStructures/Validator.swift +++ b/Sources/BeaconChain/DataStructures/Validator.swift @@ -1,6 +1,7 @@ import Foundation struct Validator { + let pubkey: BLSPubKey let withdrawalCredentials: Hash let effectiveBalance: Gwei @@ -9,4 +10,20 @@ struct Validator { let activationEpoch: Epoch let exitEpoch: Epoch let withdrawableEpoch: Epoch + + /// Checks if a `validator` is active. + /// + /// - Parameters: + /// - epoch: The given epoch to check activation for. + func isActive(epoch: Epoch) -> Bool { + return activationEpoch <= epoch && epoch < exitEpoch + } + + /// Checks if a `validator` is slashable. + /// + /// - Parameters: + /// - epoch: The given epoch to check slashability for. + func isSlashable(epoch: Epoch) -> Bool { + return !slashed && activationEpoch <= epoch && epoch < withdrawableEpoch + } } From 36f271b796c474c17bd1dfac3779e568e85dfd30 Mon Sep 17 00:00:00 2001 From: decanus Date: Fri, 19 Jul 2019 14:37:51 -0500 Subject: [PATCH 33/41] added test --- .swiftlint.yml | 2 + .../DataStructures/ValidatorTests.swift | 46 +++++++++++++++++++ .../Operators/PowerTests.swift | 1 + Tests/BeaconChainTests/XCTestManifests.swift | 11 +++++ 4 files changed, 60 insertions(+) create mode 100644 Tests/BeaconChainTests/DataStructures/ValidatorTests.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 91be776..eac9a91 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -11,3 +11,5 @@ identifier_name: excluded: - id - to + - x + - y diff --git a/Tests/BeaconChainTests/DataStructures/ValidatorTests.swift b/Tests/BeaconChainTests/DataStructures/ValidatorTests.swift new file mode 100644 index 0000000..8655aa4 --- /dev/null +++ b/Tests/BeaconChainTests/DataStructures/ValidatorTests.swift @@ -0,0 +1,46 @@ +import XCTest +@testable import BeaconChain + +class ValidatorTests: XCTestCase { + + func testIsActive() { + let validator = Validator( + pubkey: BLSPubKey(repeating: 0, count: 0), + withdrawalCredentials: Hash(repeating: 0, count: 0), + effectiveBalance: 0, + slashed: false, + activationEligibilityEpoch: 0, + activationEpoch: 10, + exitEpoch: 15, + withdrawableEpoch: 10 + ) + + XCTAssertTrue(validator.isActive(epoch: 11)) + } + + func testIsSlashable() { + + let tests: [(slashed: Bool, activationEpoch: Epoch, withdrawalEpoch: Epoch, epoch: Epoch, expected: Bool)] = [ + (false, 10, 10, 11, false), + (true, 10, 10, 11, false), + (false, 10, 12, 10, true) + ] + + for test in tests { + let validator = Validator( + pubkey: BLSPubKey(repeating: 0, count: 0), + withdrawalCredentials: Hash(repeating: 0, count: 0), + effectiveBalance: 0, + slashed: test.slashed, + activationEligibilityEpoch: 0, + activationEpoch: test.activationEpoch, + exitEpoch: 10, + withdrawableEpoch: test.withdrawalEpoch + ) + + XCTAssertEqual(test.expected, validator.isSlashable(epoch: test.epoch)) + } + + } + +} diff --git a/Tests/BeaconChainTests/Operators/PowerTests.swift b/Tests/BeaconChainTests/Operators/PowerTests.swift index b2491d0..afcb8a9 100644 --- a/Tests/BeaconChainTests/Operators/PowerTests.swift +++ b/Tests/BeaconChainTests/Operators/PowerTests.swift @@ -11,6 +11,7 @@ class PowerTests: XCTestCase { (2, 3, 8), (2, 4, 16) ] + // swiftlint:enable large_tuple func testPowerForInt() { for test in tests { diff --git a/Tests/BeaconChainTests/XCTestManifests.swift b/Tests/BeaconChainTests/XCTestManifests.swift index a3f307a..cfb3be8 100644 --- a/Tests/BeaconChainTests/XCTestManifests.swift +++ b/Tests/BeaconChainTests/XCTestManifests.swift @@ -11,9 +11,20 @@ extension PowerTests { ] } +extension ValidatorTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__ValidatorTests = [ + ("testIsActive", testIsActive), + ("testIsSlashable", testIsSlashable), + ] +} + public func __allTests() -> [XCTestCaseEntry] { return [ testCase(PowerTests.__allTests__PowerTests), + testCase(ValidatorTests.__allTests__ValidatorTests), ] } #endif From d5db2323485d0623a98cc392140c0a475210d642 Mon Sep 17 00:00:00 2001 From: decanus Date: Fri, 19 Jul 2019 14:42:51 -0500 Subject: [PATCH 34/41] added comment --- Sources/BeaconChain/DataStructures/Validator.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/BeaconChain/DataStructures/Validator.swift b/Sources/BeaconChain/DataStructures/Validator.swift index ad17440..fddccdc 100644 --- a/Sources/BeaconChain/DataStructures/Validator.swift +++ b/Sources/BeaconChain/DataStructures/Validator.swift @@ -1,5 +1,6 @@ import Foundation +/// A validator is an entity that participates in the consensus of the Ethereum 2.0 protocol. struct Validator { let pubkey: BLSPubKey From 3a41ddab96f54a799bd254eda537f3651a770841 Mon Sep 17 00:00:00 2001 From: decanus Date: Fri, 19 Jul 2019 14:51:15 -0500 Subject: [PATCH 35/41] added isSlashahble for attestation data, further cleanup --- .swiftlint.yml | 1 + .../DataStructures/Attestation/AttestationData.swift | 11 ++++++++++- Sources/BeaconChain/DataStructures/Checkpoint.swift | 2 +- Sources/BeaconChain/DataStructures/Crosslink.swift | 2 +- .../DataStructures/Operations/VoluntaryExit.swift | 3 ++- Sources/BeaconChain/Operators/XOR.swift | 2 +- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index eac9a91..fbffd5d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -13,3 +13,4 @@ identifier_name: - to - x - y + - i diff --git a/Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift b/Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift index f104908..55883b2 100644 --- a/Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift +++ b/Sources/BeaconChain/DataStructures/Attestation/AttestationData.swift @@ -1,7 +1,7 @@ import Foundation /// AttestationData is the main component that is signed by each validator. -public struct AttestationData { +public struct AttestationData: Equatable { /// Block root of the beacon block seen as the head of the chain at the assigned slot. public let beaconBlockRoot: Hash @@ -14,4 +14,13 @@ public struct AttestationData { /// The crosslink attempting to be formed for the assigned shard. public let crosslink: Crosslink + + /// Check if ``self`` and ``data`` are slashable according to Casper FFG rules. + /// + /// - Parameters + /// - data: `AttestationData` to compare to. + func isSlashable(_ data: AttestationData) -> Bool { + return (self != data && target.epoch == data.target.epoch) + && (source.epoch < data.source.epoch && data.target.epoch < target.epoch) + } } diff --git a/Sources/BeaconChain/DataStructures/Checkpoint.swift b/Sources/BeaconChain/DataStructures/Checkpoint.swift index 0af9e49..2608461 100644 --- a/Sources/BeaconChain/DataStructures/Checkpoint.swift +++ b/Sources/BeaconChain/DataStructures/Checkpoint.swift @@ -1,6 +1,6 @@ import Foundation -public struct Checkpoint { +public struct Checkpoint: Equatable { let epoch: Epoch let root: Hash } diff --git a/Sources/BeaconChain/DataStructures/Crosslink.swift b/Sources/BeaconChain/DataStructures/Crosslink.swift index 1bf7a50..06f6415 100644 --- a/Sources/BeaconChain/DataStructures/Crosslink.swift +++ b/Sources/BeaconChain/DataStructures/Crosslink.swift @@ -1,6 +1,6 @@ import Foundation -public struct Crosslink { +public struct Crosslink: Equatable { let shard: Shard let parentRoot: Hash let startEpoch: Epoch diff --git a/Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift b/Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift index 923bd36..1c52057 100644 --- a/Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift +++ b/Sources/BeaconChain/DataStructures/Operations/VoluntaryExit.swift @@ -3,7 +3,8 @@ import Foundation /// Message type that allows a validator to voluntarily exit validation duties. public struct VoluntaryExit { - /// Minimum epoch at which this exit can be included on chain. Helps prevent accidental/nefarious use in chain reorgs/forks. + /// Minimum epoch at which this exit can be included on chain. + /// Helps prevent accidental/nefarious use in chain reorgs/forks. public let epoch: Epoch /// Index of validator exiting. diff --git a/Sources/BeaconChain/Operators/XOR.swift b/Sources/BeaconChain/Operators/XOR.swift index 6771c4c..d38e733 100644 --- a/Sources/BeaconChain/Operators/XOR.swift +++ b/Sources/BeaconChain/Operators/XOR.swift @@ -3,7 +3,7 @@ import Foundation extension Data { /// Return the exclusive-or of two byte strings. - static func ^(left: Data, right: Data) -> Data { + static func ^ (left: Data, right: Data) -> Data { var temp = left for i in 0.. Date: Fri, 19 Jul 2019 14:52:43 -0500 Subject: [PATCH 36/41] made public --- Sources/BeaconChain/DataStructures/Validator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/BeaconChain/DataStructures/Validator.swift b/Sources/BeaconChain/DataStructures/Validator.swift index fddccdc..965d7a3 100644 --- a/Sources/BeaconChain/DataStructures/Validator.swift +++ b/Sources/BeaconChain/DataStructures/Validator.swift @@ -1,7 +1,7 @@ import Foundation /// A validator is an entity that participates in the consensus of the Ethereum 2.0 protocol. -struct Validator { +public struct Validator { let pubkey: BLSPubKey let withdrawalCredentials: Hash From 8b314079f70934328157d14e4c7e3f091cff7466 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 22 Jul 2019 13:45:02 -0500 Subject: [PATCH 37/41] is_valid_indexed_attestation --- Sources/BeaconChain/BLS.swift | 6 +-- Sources/BeaconChain/Crypto.swift | 6 +-- .../DataStructures/BeaconState.swift | 49 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Sources/BeaconChain/BLS.swift b/Sources/BeaconChain/BLS.swift index 00088ff..2e06bcb 100644 --- a/Sources/BeaconChain/BLS.swift +++ b/Sources/BeaconChain/BLS.swift @@ -4,15 +4,15 @@ import Foundation class BLS { - func verify(pubkey: Data, hash: Hash, signature: Data, domain: UInt64) -> Bool { + static func verify(pubkey: Data, hash: Hash, signature: Data, domain: UInt64) -> Bool { return false } - func verify(pubkeys: [Data], hashes: [Hash], signature: Data, domain: UInt64) -> Bool { + static func verify(pubkeys: [Data], hashes: [Hash], signature: Data, domain: UInt64) -> Bool { return false } - func aggregate(pubkeys: [Data]) -> Data { + static func aggregate(pubkeys: [Data]) -> Data { fatalError("not yet implemented") } } diff --git a/Sources/BeaconChain/Crypto.swift b/Sources/BeaconChain/Crypto.swift index b5ee6d9..e605d4a 100644 --- a/Sources/BeaconChain/Crypto.swift +++ b/Sources/BeaconChain/Crypto.swift @@ -4,15 +4,15 @@ import Foundation class SSZ { - func hash(_ data: Data) -> Hash { + static func hash(_ data: Data) -> Hash { fatalError("not yet implemented") } - func hashTreeRoot(_ data: Data) -> Hash { + static func hashTreeRoot(_ data: Any) -> Hash { fatalError("not yet implemented") } - func signingRoot(_ data: Any) -> Hash { + static func signingRoot(_ data: Any) -> Hash { fatalError("not yet implemented") } } diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift index 3a01377..639d1e4 100644 --- a/Sources/BeaconChain/DataStructures/BeaconState.swift +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -26,4 +26,53 @@ struct BeaconState { let previousJustifiedCheckpoint: Checkpoint let currentJustifiedCheckpoint: Checkpoint let finalizedCheckpoint: Checkpoint + + /// Check if `indexed_attestation` has valid indices and signature. + /// + /// - Parameters: + /// - indexedAttestation: The attestation to check. + func isValid(indexedAttestation attestation: IndexedAttestation) -> Bool { + + let bit0Indices = attestation.custodyBit0Indices + let bit1Indices = attestation.custodyBit1Indices + + if bit1Indices.count == 0 { + return false + } + + if !(bit0Indices.count + bit1Indices.count <= MAX_VALIDATORS_PER_COMMITTEE) { + return false + } + + if Set(bit0Indices).intersection(Set(bit1Indices)).count != 0 { + return false + } + + if bit0Indices != bit0Indices.sorted() || bit1Indices != bit1Indices.sorted() { + return false + } + + return BLS.verify( + pubkeys: BLS.aggregate( + pubkeys: bit0Indices.map { (i) in + return validators[Int(i)].pubkey + } + ), + BLS.aggregate( + pubkeys: bit1Indices.map { (i) in + return validators[Int(i)].pubkey + } + ), + hashes: [ + SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: false)), + SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: true)), + ], + signature: attestation.signature, + domain: getDomain(type: DomainType.attestation, epoch: attestation.data.target.epoch) + ) + } + + func getDomain(type: DomainType, epoch: Epoch) -> Domain { + + } } From f88775838660c711ed5fc60495da076ff9db3182 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 22 Jul 2019 13:45:57 -0500 Subject: [PATCH 38/41] update --- Sources/BeaconChain/BLS.swift | 4 ++-- Sources/BeaconChain/DataStructures/BeaconState.swift | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/BeaconChain/BLS.swift b/Sources/BeaconChain/BLS.swift index 2e06bcb..c5ffd14 100644 --- a/Sources/BeaconChain/BLS.swift +++ b/Sources/BeaconChain/BLS.swift @@ -4,11 +4,11 @@ import Foundation class BLS { - static func verify(pubkey: Data, hash: Hash, signature: Data, domain: UInt64) -> Bool { + static func verify(pubkey: Data, hash: Hash, signature: Data, domain: Domain) -> Bool { return false } - static func verify(pubkeys: [Data], hashes: [Hash], signature: Data, domain: UInt64) -> Bool { + static func verify(pubkeys: [Data], hashes: [Hash], signature: Data, domain: Domain) -> Bool { return false } diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift index 639d1e4..2a3f1b9 100644 --- a/Sources/BeaconChain/DataStructures/BeaconState.swift +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -32,7 +32,6 @@ struct BeaconState { /// - Parameters: /// - indexedAttestation: The attestation to check. func isValid(indexedAttestation attestation: IndexedAttestation) -> Bool { - let bit0Indices = attestation.custodyBit0Indices let bit1Indices = attestation.custodyBit1Indices From fa177e3f0013e89785f95c07f3337b487c000146 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 22 Jul 2019 13:48:24 -0500 Subject: [PATCH 39/41] updated --- .../DataStructures/BeaconState.swift | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift index 2a3f1b9..16b8343 100644 --- a/Sources/BeaconChain/DataStructures/BeaconState.swift +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -52,22 +52,24 @@ struct BeaconState { } return BLS.verify( - pubkeys: BLS.aggregate( - pubkeys: bit0Indices.map { (i) in - return validators[Int(i)].pubkey - } + pubkeys: [ + BLS.aggregate( + pubkeys: bit0Indices.map { (i) in + return validators[Int(i)].pubkey + } ), BLS.aggregate( - pubkeys: bit1Indices.map { (i) in - return validators[Int(i)].pubkey - } + pubkeys: bit1Indices.map { (i) in + return validators[Int(i)].pubkey + } ), - hashes: [ - SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: false)), - SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: true)), - ], - signature: attestation.signature, - domain: getDomain(type: DomainType.attestation, epoch: attestation.data.target.epoch) + ], + hashes: [ + SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: false)), + SSZ.hashTreeRoot(AttestationDataAndCustodyBit(data: attestation.data, custodyBit: true)), + ], + signature: attestation.signature, + domain: getDomain(type: DomainType.attestation, epoch: attestation.data.target.epoch) ) } From 832aaa090adf8bd61491361fff6678b0bae61057 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 22 Jul 2019 14:05:01 -0500 Subject: [PATCH 40/41] isValidMerkleBranch --- .../DataStructures/BeaconState.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Sources/BeaconChain/DataStructures/BeaconState.swift b/Sources/BeaconChain/DataStructures/BeaconState.swift index 16b8343..3389193 100644 --- a/Sources/BeaconChain/DataStructures/BeaconState.swift +++ b/Sources/BeaconChain/DataStructures/BeaconState.swift @@ -73,6 +73,28 @@ struct BeaconState { ) } + /// Check if ``leaf`` at ``index`` verifies against the Merkle ``root`` and ``branch``. + /// + /// - Parameters + /// - leaf: The leaf to check for. + /// - branch: The merkle branch. + /// - depth: The depth of the tree. + /// - index: The index of the leaf. + /// - root: The merkle root. + static func isValidMerkleBranch(leaf: Hash, branch: [Hash], depth: Int, index: Int, root: Hash) -> Bool { + var value = leaf + + for i in stride(from: 0, through: depth, by: 1) { + if index / (2**i) % 2 == 0 { + value = SSZ.hash(value + branch[i]) + } else { + value = SSZ.hash(branch[i] + value) + } + } + + return value == root + } + func getDomain(type: DomainType, epoch: Epoch) -> Domain { } From 5e26157afbf08f0af508084524797121394c1a17 Mon Sep 17 00:00:00 2001 From: decanus Date: Mon, 22 Jul 2019 14:11:15 -0500 Subject: [PATCH 41/41] updated --- Sources/BeaconChain/Extensions/Domain.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Sources/BeaconChain/Extensions/Domain.swift diff --git a/Sources/BeaconChain/Extensions/Domain.swift b/Sources/BeaconChain/Extensions/Domain.swift new file mode 100644 index 0000000..e7d9c82 --- /dev/null +++ b/Sources/BeaconChain/Extensions/Domain.swift @@ -0,0 +1,13 @@ +import Foundation + +extension Domain { + + /// Return the domain for the `DomainType` and `Version`. + /// + /// - Parameters + /// - type: The domain type. + /// - fork: The fork version. + init(type: DomainType, fork: Version) { + self.init(UInt64(type.rawValue + fork)) + } +}