{.push raises: [].} import chronicles, std/options, chronos, results, metrics import libp2p/crypto/curve25519, libp2p/crypto/crypto, libp2p/protocols/mix, libp2p/protocols/mix/mix_node, libp2p/protocols/mix/mix_protocol, libp2p/protocols/mix/mix_metrics, libp2p/protocols/mix/delay_strategy, libp2p/[multiaddress, peerid], eth/common/keys import waku/node/peer_manager, waku/waku_core, waku/waku_enr, waku/node/peer_manager/waku_peer_store logScope: topics = "waku mix" const minMixPoolSize = 4 type WakuMix* = ref object of MixProtocol peerManager*: PeerManager clusterId: uint16 pubKey*: Curve25519Key WakuMixResult*[T] = Result[T, string] MixNodePubInfo* = object multiAddr*: string pubKey*: Curve25519Key proc processBootNodes( bootnodes: seq[MixNodePubInfo], peermgr: PeerManager, mix: WakuMix ) = var count = 0 for node in bootnodes: let pInfo = parsePeerInfo(node.multiAddr).valueOr: error "Failed to get peer id from multiaddress: ", error = error, multiAddr = $node.multiAddr continue let peerId = pInfo.peerId var peerPubKey: crypto.PublicKey if not peerId.extractPublicKey(peerPubKey): warn "Failed to extract public key from peerId, skipping node", peerId = peerId continue if peerPubKey.scheme != PKScheme.Secp256k1: warn "Peer public key is not Secp256k1, skipping node", peerId = peerId, scheme = peerPubKey.scheme continue let multiAddr = MultiAddress.init(node.multiAddr).valueOr: error "Failed to parse multiaddress", multiAddr = node.multiAddr, error = error continue let mixPubInfo = MixPubInfo.init(peerId, multiAddr, node.pubKey, peerPubKey.skkey) mix.nodePool.add(mixPubInfo) count.inc() peermgr.addPeer( RemotePeerInfo.init(peerId, @[multiAddr], mixPubKey = some(node.pubKey)) ) mix_pool_size.set(count) info "using mix bootstrap nodes ", count = count proc new*( T: typedesc[WakuMix], nodeAddr: string, peermgr: PeerManager, clusterId: uint16, mixPrivKey: Curve25519Key, bootnodes: seq[MixNodePubInfo], ): WakuMixResult[T] = let mixPubKey = public(mixPrivKey) info "mixPubKey", mixPubKey = mixPubKey let nodeMultiAddr = MultiAddress.init(nodeAddr).valueOr: return err("failed to parse mix node address: " & $nodeAddr & ", error: " & error) let localMixNodeInfo = initMixNodeInfo( peermgr.switch.peerInfo.peerId, nodeMultiAddr, mixPubKey, mixPrivKey, peermgr.switch.peerInfo.publicKey.skkey, peermgr.switch.peerInfo.privateKey.skkey, ) var m = WakuMix(peerManager: peermgr, clusterId: clusterId, pubKey: mixPubKey) procCall MixProtocol(m).init( localMixNodeInfo, peermgr.switch, delayStrategy = ExponentialDelayStrategy.new(meanDelayMs = 50, rng = crypto.newRng()), ) processBootNodes(bootnodes, peermgr, m) if m.nodePool.len < minMixPoolSize: warn "publishing with mix won't work until atleast 3 mix nodes in node pool" return ok(m) proc poolSize*(mix: WakuMix): int = mix.nodePool.len # Mix Protocol