Arquitetura Mesh Offline


Visão geral da solução

  • Rede offline: dispositivos formam uma mesh P2P via BLE/libp2p (até ~50 nodes em área).

  • Transações: criações P2P entre sender→receiver via BLE.

  • Validação local: um subset dinâmica de dispositivos na mesh (eleitos automaticamente) assina a tx. Requer k assinaturas (p.ex. k=5).

  • Agregação + bloco local: validadores agregam txs num Local Block (LB) e produzem um agg_sig (BLS threshold).

  • Sync para online: assim que qualquer nó da mesh encontra internet, submete o LB (merkle_root + agg_sig) à blockchain global.

  • Blockchain global: recomenda-se PoS (menos custo energético, finalidades rápidas) ou usar uma L1 compatível/EVM/Substrate para facilidade.


Componentes e tecnologias recomendadas

  • BLE + libp2p (mesh).

  • Chaves efêmeras + ED25519 (assinatura local) + BLS threshold para agregação on-chain.

  • Wallet local com local_nonce e cache de locks.

  • Mini-node (VL) leve em Rust/Go para validar e submeter LBs.

  • Chain de destino: PoS L1 ou L2 (submeter merkle_root/agg_sig).


Fluxo (alto nível — 7 passos)

  1. Sender gera TX (tx_hash = H(sender_pub || nonce || amount || ts || meta)) e envia ao Receiver via BLE.

  2. Receiver broadcast na mesh um sign request com tx_hash + local_nonce.

  3. N dispositivos automáticos checam regras (saldo provisório, rate-limit, prova proximidade) e, se OK, assinam com chave efêmera e respondem com sig_meta (device_hash, rssi, ts, sig).

  4. Quando Receiver coleta ≥k sig_meta válidas e distintas, forma LB (insere TX) e cria agg_sig (threshold BLS) — LB tem merkle_root. Gera temporary_lock.

  5. LB fica salvo localmente; todos os nodes da mesh sincronizam LB entre si (gossip).

  6. Quando um node obtém internet, ele pega LBs não-sincronizados e submete (merkle_root + agg_sig + validator_commitments) à blockchain global via API.

  7. Rede global verifica agg_sig, valida nonces contra ledger e abre challenge window. Se tudo ok, grava hash do LB e confirma txs globalmente.


Como eleger validadores entre 50 usuários (permissionless, justo)

  • Eleição automática por VRF (verifiable random function) + peso por Trust Score:

    • Cada nó gera uma saída VRF em cada epoch; se VRF < threshold(node_TS, epoch), o nó é candidato validador.

    • Isso distribui validação ao acaso, mas favorece quem provou honestidade.

  • Alternativa simples: seleção randômica por shuffle determinístico da lista de peers + pick first k.


Mitigações essenciais (Sybil, replay, colusão)

  • Nonce monotônico na wallet + checagem local.

  • k assinaturas distintas + device_id_hash diversity check (não aceitar múltiplos sigs do mesmo device).

  • Rate-limits por device e limitação de recompensa.

  • Locks temporários (TTL curto) publicados em batch para chain (reduz double-spend).

  • Janela de challenge (p.ex. 48 h) e slashing/reputational penalty se prova.

  • Heurísticas anti-bot (assinaturas em massa do mesmo coordenador/geo-hash).

  • BLS threshold para reduzir footprint on-chain.


Recomendação sobre PoW vs PoS

  • PoS é melhor aqui: menor custo, confirmações mais rápidas e mais fácil integrar slashing/reputação.

  • PoW adiciona barreira energética e latência — não ajuda o offline use-case.

  • Ideal: submeter LBs a uma PoS L1 (ou L2 rollup) que aceite provas compactas (merkle_root + agg_sig).


Pseudocódigo compacto (mensagens BLE, assinatura, criação de LB e sync)

// --- on Sender ---
tx = {sender_pub, receiver_pub, amount, local_nonce, ts}
tx_hash = H(tx)
send_ble(receiver_id, {type: "TX_OFFER", tx, tx_hash})

// --- on Receiver ---
on_receive(TX_OFFER):
  if wallet.provisional_balance >= amount and nonce_ok:
    broadcast_mesh({type:"SIGN_REQUEST", tx_hash, nonce})
    sigs = []
    while sigs.count < k and timeout not reached:
      wait incoming SIGN_RESPONSE
      if valid_sig(response): sigs.append(response)
    if sigs.count >= k:
      agg_sig = BLS_aggregate(sigs)
      LB = create_local_block([tx], merkle_root(...), agg_sig, validators_meta)
      store_local(LB)
      create_temporary_lock(tx.sender, tx.amount, TTL)
      gossip_mesh({type:"NEW_LB", LB})

// --- on any Node with Internet ---
periodic_sync():
  for each LB in local_storage not yet submitted:
    payload = {merkle_root: LB.merkle_root, agg_sig: LB.agg_sig, meta: LB.validators_meta}
    resp = submit_to_chain(payload)
    if resp.accepted:
      mark_confirmed(LB)
    else if resp.dispute:
      open_challenge_procedure(LB)

// --- Validator auto-signing (BLE listener) ---
on_receive(SIGN_REQUEST):
  if passes_checks(nonce, rate_limit, proximity, local_cache):
    sig = sign_with_ephemeral_key(tx_hash)
    send_ble(originator, {type:"SIGN_RESPONSE", device_hash, rssi, ts, sig})

Parâmetros práticos sugeridos (iniciar)

  • network size target: 50 nodes (ok).

  • k (assinaturas) padrão urbano = 5.

  • rate-limit por device = 20 assinaturas recompensadas/dia.

  • temporary_lock TTL = 30–90 minutos.

  • challenge window = 48 horas.

  • stake opcional para acelerar reputação; mas permissionless por padrão.


Próximos passos práticos se queres protótipo

  1. Prototipar wallet mobile (React Native) que cria txs e faz BLE gossip.

  2. Implementar listener simples (NodeJS/Go) que age como validator e testa coleta de k sigs.

  3. Testnet local: montar uma L1 Substrate/PoS local para submeter merkle_roots.

  4. Simular ataques Sybil/colusão para ajustar parâmetros.