Skip to content

Commit

Permalink
Implement the latest networking spec
Browse files Browse the repository at this point in the history
  • Loading branch information
zah committed Aug 7, 2019
1 parent 398ea55 commit 5ce50b3
Show file tree
Hide file tree
Showing 17 changed files with 387 additions and 862 deletions.
6 changes: 4 additions & 2 deletions beacon_chain/attestation_pool.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ proc combine*(tgt: var Attestation, src: Attestation, flags: UpdateFlags) =

if skipValidation notin flags:
tgt.signature.combine(src.signature)
else:
debug "Ignoring overlapping attestations"

proc validate(
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
Expand Down Expand Up @@ -61,11 +63,11 @@ proc validate(
finalizedEpoch = humaneEpochNum(state.finalized_checkpoint.epoch)
return

if not allIt(attestation.custody_bits.bytes, it == 0):
if not attestation.custody_bits.BitSeq.isZeros:
notice "Invalid custody bitfield for phase 0"
return false

if not anyIt(attestation.aggregation_bits.bytes, it != 0):
if attestation.aggregation_bits.BitSeq.isZeros:
notice "Empty aggregation bitfield"
return false

Expand Down
4 changes: 4 additions & 0 deletions beacon_chain/beacon_chain_db.nim
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ proc get(db: BeaconChainDB, key: auto, T: typedesc): Option[T] =
proc getBlock*(db: BeaconChainDB, key: Eth2Digest): Option[BeaconBlock] =
db.get(subkey(BeaconBlock, key), BeaconBlock)

proc getBlock*(db: BeaconChainDB, slot: Slot): Option[BeaconBlock] =
# TODO implement this
discard

proc getState*(db: BeaconChainDB, key: Eth2Digest): Option[BeaconState] =
db.get(subkey(BeaconState, key), BeaconState)

Expand Down
48 changes: 24 additions & 24 deletions beacon_chain/beacon_node.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import
sync_protocol, request_manager, genesis

const
topicBeaconBlocks = "ethereum/2.1/beacon_chain/blocks"
topicAttestations = "ethereum/2.1/beacon_chain/attestations"
topicBeaconBlocks = "/eth2/beacon_block/ssz"
topicAttestations = "/eth2/beacon_attestation/ssz"
topicVoluntaryExits = "/eth2/voluntary_exit/ssz"
topicProposerSlashings = "/eth2/proposer_slashing/ssz"
topicAttesterSlashings = "/eth2/attester_slashing/ssz"

dataDirValidators = "validators"
networkMetadataFile = "network.json"
Expand Down Expand Up @@ -101,6 +104,7 @@ proc initGenesis(node: BeaconNode) {.async.} =
quit 1

info "Got genesis state", hash = hash_tree_root(tailState)
node.forkVersion = tailState.fork.current_version

try:
let tailBlock = get_initial_beacon_block(tailState)
Expand Down Expand Up @@ -159,6 +163,20 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
if metadataErrorMsg.len > 0:
fail "To connect to the ", conf.network, " network, please compile with", metadataErrorMsg

for bootNode in result.networkMetadata.bootstrapNodes:
if bootNode.isSameNode(result.networkIdentity):
result.isBootstrapNode = true
else:
result.bootstrapNodes.add bootNode

for bootNode in conf.bootstrapNodes:
result.bootstrapNodes.add BootstrapAddr.init(bootNode)

let bootstrapFile = string conf.bootstrapNodesFile
if bootstrapFile.len > 0:
for ln in lines(bootstrapFile):
result.bootstrapNodes.add BootstrapAddr.init(string ln)

result.attachedValidators = ValidatorPool.init
init result.mainchainMonitor, "", Port(0) # TODO: specify geth address and port

Expand All @@ -176,14 +194,12 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
result.blockPool = BlockPool.init(result.db)
result.attestationPool = AttestationPool.init(result.blockPool)

result.network = await createEth2Node(conf)
result.network = await createEth2Node(conf, result.bootstrapNodes)
result.requestManager.init result.network

# TODO sync is called when a remote peer is connected - is that the right
# time to do so?
let sync = result.network.protocolState(BeaconSync)
sync.chainId = 0 # TODO specify chainId
sync.networkId = result.networkMetadata.networkId
sync.node = result
sync.db = result.db

Expand Down Expand Up @@ -211,28 +227,12 @@ template withState(
body

proc connectToNetwork(node: BeaconNode) {.async.} =
var bootstrapNodes = newSeq[BootstrapAddr]()

for bootNode in node.networkMetadata.bootstrapNodes:
if bootNode.isSameNode(node.networkIdentity):
node.isBootstrapNode = true
else:
bootstrapNodes.add bootNode

for bootNode in node.config.bootstrapNodes:
bootstrapNodes.add BootstrapAddr.init(bootNode)

let bootstrapFile = string node.config.bootstrapNodesFile
if bootstrapFile.len > 0:
for ln in lines(bootstrapFile):
bootstrapNodes.add BootstrapAddr.init(string ln)

if bootstrapNodes.len > 0:
info "Connecting to bootstrap nodes", bootstrapNodes
if node.bootstrapNodes.len > 0:
info "Connecting to bootstrap nodes", bootstrapNodes = node.bootstrapNodes
else:
info "Waiting for connections"

await node.network.connectToNetwork(bootstrapNodes)
await node.network.connectToNetwork(node.bootstrapNodes)

template findIt(s: openarray, predicate: untyped): int =
var res = -1
Expand Down
2 changes: 2 additions & 0 deletions beacon_chain/beacon_node_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ type
BeaconNode* = ref object
nickname*: string
network*: Eth2Node
forkVersion*: array[4, byte]
networkIdentity*: Eth2NodeIdentity
networkMetadata*: NetworkMetadata
requestManager*: RequestManager
isBootstrapNode*: bool
bootstrapNodes*: seq[BootstrapAddr]
db*: BeaconChainDB
config*: BeaconNodeConf
attachedValidators*: ValidatorPool
Expand Down
53 changes: 34 additions & 19 deletions beacon_chain/eth2_network.nim
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ when networkBackend == rlpxBackend:
proc readValue*(reader: var JsonReader, value: var BootstrapAddr) {.inline.} =
value = initENode reader.readValue(string)

proc createEth2Node*(conf: BeaconNodeConf): Future[EthereumNode] {.async.} =
proc createEth2Node*(conf: BeaconNodeConf,
bootstrapNodes: seq[BootstrapAddr]): Future[EthereumNode] {.async.} =
let
keys = getPersistentNetIdentity(conf)
(ip, tcpPort, udpPort) = setupNat(conf)
Expand All @@ -125,25 +126,19 @@ else:
import
os, random, stew/io,
libp2p/crypto/crypto, libp2p/daemon/daemonapi, eth/async_utils,
ssz
ssz, libp2p_backend

when networkBackend == libp2pSpecBackend:
import libp2p_spec_backend
export libp2p_spec_backend
const netBackendName* = "libp2p_spec"
export
libp2p_backend

else:
import libp2p_backend
export libp2p_backend
const netBackendName* = "libp2p_native"
const
netBackendName* = "libp2p"
networkKeyFilename = "privkey.protobuf"

type
BootstrapAddr* = PeerInfo
Eth2NodeIdentity* = PeerInfo

const
networkKeyFilename = "privkey.protobuf"

proc init*(T: type BootstrapAddr, str: string): T =
Json.decode(str, PeerInfo)

Expand All @@ -168,19 +163,39 @@ else:

var mainDaemon: DaemonAPI

proc createEth2Node*(conf: BeaconNodeConf): Future[Eth2Node] {.async.} =
proc allMultiAddresses(nodes: seq[BootstrapAddr]): seq[string] =
for node in nodes:
for a in node.addresses:
result.add $a & "/ipfs/" & node.peer.pretty()

proc createEth2Node*(conf: BeaconNodeConf,
bootstrapNodes: seq[BootstrapAddr]): Future[Eth2Node] {.async.} =
var
(extIp, extTcpPort, extUdpPort) = setupNat(conf)
hostAddress = tcpEndPoint(globalListeningAddr, Port conf.tcpPort)
announcedAddresses = if extIp != globalListeningAddr: @[]
else: @[tcpEndPoint(extIp, extTcpPort)]
keyFile = conf.ensureNetworkIdFile

info "Starting the LibP2P daemon", hostAddress, announcedAddresses, keyFile
mainDaemon = await newDaemonApi({PSGossipSub},
id = keyFile,
hostAddresses = @[hostAddress],
announcedAddresses = announcedAddresses)
info "Starting the LibP2P daemon", hostAddress, announcedAddresses,
keyFile, bootstrapNodes

var daemonFut = if bootstrapNodes.len == 0:
newDaemonApi({DHTFull, PSGossipSub},
id = keyFile,
hostAddresses = @[hostAddress],
announcedAddresses = announcedAddresses)
else:
newDaemonApi({DHTFull, PSGossipSub, WaitBootstrap},
id = keyFile,
hostAddresses = @[hostAddress],
announcedAddresses = announcedAddresses,
bootstrapNodes = allMultiAddresses(bootstrapNodes),
peersRequired = 1)

info "Deamon started"

mainDaemon = await daemonFut

proc closeDaemon() {.noconv.} =
info "Shutting down the LibP2P daemon"
Expand Down
6 changes: 4 additions & 2 deletions beacon_chain/genesis.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import conf, chronos, web3, json,
spec/[bitfield, datatypes, digest, crypto, beaconstate, helpers, validator], extras
import
chronos, web3, json,
spec/[datatypes, digest, crypto, beaconstate, helpers, validator],
conf, extras

contract(DepositContract):
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96)
Expand Down
Loading

0 comments on commit 5ce50b3

Please sign in to comment.