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_requestorproof_responsethe 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
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.