ProofP2PAdapter class

Asks a counterparty for a fresh merkle proof, and answers when one asks us (bead libspiffy-a2v3).

Why

A reorganization can take an ancestor's block off the active chain. The proof row is kept (a reorganization can put the block back) but no longer counts, so the walk back from a received transaction runs off the end of what we store: the outputs it gave us cannot go into a BEEF and cannot be spent. ReadModelStorage.getOutputsAwaitingAncestorProof lists them.

There are exactly two recoveries and neither is a lookup service. The block comes back, or the counterparty who handed us the payment supplies a fresh BEEF with a fresh BUMP. This adapter is the second. There is no block scanning and no address monitoring (spv-understanding.md, Critical Implementation Note 2), and ARC is not asked: an ARC instance answers for what was submitted through it and nothing else, so it has no standing to prove a counterparty's transaction and a NOT_FOUND from it means nothing.

Who is asked

The counterparty of the transaction we received, named by BitcoinTransaction.counterpartyMarker on its row (bead libspiffy-cq16) — not the orphaned ancestor's counterparty, who is almost always a stranger we never dealt with and have no marker for. The sender of a payment owes us the proofs its ancestry needs; they handed us a BEEF that has since become incomplete, and they are the ones who can complete it.

Transport

libspiffy owns no transport, exactly as with payment channels (ChannelP2PAdapter). Outbound messages are emitted as P2PMessageToSendEvents for the app to deliver; inbound ones arrive as P2PMessageReceived and the coordinator routes them here by message type. No socket, no HTTP client, no peer address book.

Identity

fromPeerId and the counterparty marker are both opaque strings the app chooses; this adapter compares them with == and gives them no meaning of its own. An app whose peer ids and markers come from the same identity scheme (an Ed25519 key, an account id, a peer id) gets an enforced check out of it; an app that mixes schemes gets a refusal, which is the safe direction.

Constructors

ProofP2PAdapter({required ReadModelStorage storage, required ActorRef spvActor, required void emitEvent(CoordinatorEvent), Duration receiveTimeout = const Duration(seconds: 60)})

Properties

hashCode → int
The hash code for this object.
no setterinherited
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

dispose() → void
Forget in-flight requests (the coordinator is stopping).
handleP2PMessage(String fromPeerId, String messageType, Map<String, dynamic> payload) → Future<void>
Handle a proof_request or proof_response the app delivered.
handleReceiveResult(SPVValidationResult result) → bool
Take the receive path's verdict on a BEEF this adapter delivered.
handleRequestProof(RequestAncestorProofCommand cmd) → Future<void>
Ask RequestAncestorProofCommand.txid's counterparty for a fresh proof.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited
updateReplyTo(ActorRef replyTo) → void
The actor SPVActor should reply to (the coordinator). Set once the coordinator has a context; the adapter is built in its constructor.

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

handles(String messageType) → bool
Whether messageType belongs to this protocol.

Constants

proofRequestType → const String
Message type of a request for a fresh proof.
proofResponseType → const String
Message type of the answer to one.
refusalOnTheWire → const String
What a refused request says on the wire.