Skip to content

Commit 151be05

Browse files
committed
tapgarden: add README that describes Custodian flow
1 parent dd85d50 commit 151be05

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

tapgarden/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Asset Custodian
2+
3+
The `Custodian` is a core component within the `tapgarden` package responsible
4+
for managing the lifecycle of incoming Taproot Assets. It operates as an
5+
event-driven system that listens for various triggers, tracks the state of each
6+
incoming asset transfer, and ensures that assets are securely and verifiably
7+
received into the wallet.
8+
9+
## Core Responsibilities
10+
11+
- **Address Management**: Imports new addresses into the underlying `lnd`
12+
wallet for on-chain detection (for V0/V1 addresses) or subscribes to an
13+
authentication mailbox for message-based notifications from the sender (for
14+
V2+ addresses).
15+
- **On-Chain Event Monitoring**: Watches for new transactions that match managed
16+
Taproot output keys.
17+
- **Proof Retrieval**: Coordinates with `ProofCourier` services to fetch asset
18+
provenance proofs from senders.
19+
- **Proof Validation & Storage**: Verifies the integrity and validity of
20+
incoming proofs and stores them in the `ProofArchive`.
21+
- **State Management**: Tracks the status of each inbound asset transfer through
22+
a series of states, from detection to final completion.
23+
24+
## Event Triggers and State Flow
25+
26+
The Custodian's logic is driven by four primary event triggers. Each trigger
27+
initiates a series of actions that advance an asset transfer through its
28+
lifecycle.
29+
30+
### Asset State Transitions
31+
32+
The lifecycle of an incoming asset transfer is tracked by the `address.Status`
33+
field of an `address.Event`. The diagram below illustrates the possible state
34+
transitions.
35+
36+
```mermaid
37+
stateDiagram-v2
38+
direction LR
39+
[*] --> CREATED: New Address
40+
CREATED --> DETECTED: On-chain TX detected (V0/V1)
41+
CREATED --> CONFIRMED: Mailbox message received (V2)
42+
DETECTED --> CONFIRMED: On-chain TX confirmed
43+
CONFIRMED --> PROOF_RECEIVED: Proof retrieval successful
44+
PROOF_RECEIVED --> COMPLETED: All proofs for transfer validated
45+
COMPLETED --> [*]
46+
47+
state "Event States" as States {
48+
DETECTED: StatusTransactionDetected
49+
CONFIRMED: StatusTransactionConfirmed
50+
PROOF_RECEIVED: StatusProofReceived
51+
COMPLETED: StatusCompleted
52+
}
53+
```
54+
55+
---
56+
57+
### Trigger 1: New Address Creation
58+
59+
When a new Taproot Asset address is created and added to the `AddrBook`, the
60+
Custodian is notified. Its behavior depends on the address version.
61+
62+
- **V0/V1 Addresses**: The Custodian takes the `TaprootOutputKey` from the
63+
address and imports it into the `lnd` wallet. This allows the wallet to scan
64+
the blockchain for transactions paying to this specific key.
65+
- **V2+ Addresses**: The Custodian subscribes to a `ProofCourier` of type
66+
`AuthMailbox` using the address's unique script key. It does not import any
67+
keys into the on-chain wallet, as V2 transfers are communicated as separate
68+
messages sent through the authenticated mailbox system.
69+
70+
### Trigger 2: New Wallet Transaction (V0/V1 Addresses)
71+
72+
When the `WalletAnchor` detects a new transaction, the Custodian inspects it.
73+
74+
1. It checks if the transaction has a Taproot output that belongs to the
75+
internal wallet.
76+
2. If a match is found, it queries the `AddrBook` to see if this output key
77+
corresponds to a known Taproot Asset address.
78+
3. If it's a match, a new `address.Event` is created with the status
79+
`StatusTransactionDetected`.
80+
4. When the transaction receives its first confirmation, the event's status is
81+
updated to `StatusTransactionConfirmed`. This triggers the proof retrieval
82+
process.
83+
84+
```mermaid
85+
sequenceDiagram
86+
participant User
87+
participant AddrBook
88+
participant Custodian
89+
participant WalletAnchor
90+
participant ProofCourier
91+
participant ProofArchive
92+
93+
User->>AddrBook: Create New Address (V0/V1)
94+
AddrBook->>Custodian: Notify(New Address)
95+
Custodian->>WalletAnchor: ImportTaprootOutput(key)
96+
note right of Custodian: Custodian now watches for on-chain TXs
97+
98+
WalletAnchor->>Custodian: Notify(New TX)
99+
Custodian->>AddrBook: GetOrCreateEvent(StatusTransactionDetected)
100+
WalletAnchor->>Custodian: Notify(TX Confirmed)
101+
Custodian->>AddrBook: UpdateEvent(StatusTransactionConfirmed)
102+
activate Custodian
103+
Custodian->>ProofCourier: ReceiveProof()
104+
ProofCourier-->>Custodian: Return Proof
105+
deactivate Custodian
106+
Custodian->>ProofArchive: ImportProofs()
107+
ProofArchive->>Custodian: Notify(New Proof)
108+
Custodian->>AddrBook: UpdateEvent(StatusProofReceived)
109+
Custodian->>AddrBook: CompleteEvent(StatusCompleted)
110+
```
111+
112+
### Trigger 3: New Mailbox Message (V2+ Addresses)
113+
114+
For V2 addresses, the process is initiated by an incoming authenticated mailbox
115+
message.
116+
117+
1. The Custodian receives an encrypted message from the `AuthMailbox` server
118+
it's subscribed to.
119+
2. It decrypts the message using the address's script key to reveal a
120+
`SendFragment`. This fragment contains the outpoint of the on-chain anchor
121+
transaction.
122+
3. Using the information from the fragment, the Custodian creates a new
123+
`address.Event` directly with the status `StatusTransactionConfirmed`, as the
124+
fragment is only sent after the transaction is confirmed.
125+
4. This immediately triggers the proof retrieval process.
126+
127+
```mermaid
128+
sequenceDiagram
129+
participant User
130+
participant AddrBook
131+
participant Custodian
132+
participant MailboxServer
133+
participant ProofCourier
134+
participant ProofArchive
135+
136+
User->>AddrBook: Create New Address (V2)
137+
AddrBook->>Custodian: Notify(New Address)
138+
Custodian->>MailboxServer: Subscribe(script_key)
139+
note right of Custodian: Custodian now listens for mailbox messages
140+
141+
MailboxServer->>Custodian: Notify(New Message)
142+
activate Custodian
143+
Custodian->>Custodian: Decrypt Message (SendFragment)
144+
Custodian->>AddrBook: GetOrCreateEvent(StatusTransactionConfirmed)
145+
deactivate Custodian
146+
147+
activate Custodian
148+
Custodian->>ProofCourier: ReceiveProof()
149+
ProofCourier-->>Custodian: Return Proof
150+
deactivate Custodian
151+
Custodian->>ProofArchive: ImportProofs()
152+
ProofArchive->>Custodian: Notify(New Proof)
153+
Custodian->>AddrBook: UpdateEvent(StatusProofReceived)
154+
Custodian->>AddrBook: CompleteEvent(StatusCompleted)
155+
```
156+
157+
### Trigger 4: New Proof Received
158+
159+
This trigger is the final step in the process, common to all address versions.
160+
161+
1. After a transaction is confirmed (either on-chain or via mailbox), the
162+
`receiveProofs` function is called. It uses the `ProofCourier` specified in
163+
the address to fetch the asset proof.
164+
2. The fetched proof is sent to the `ProofArchive` for validation and storage.
165+
3. Importing a proof into the `ProofArchive` will make sure it is imported into
166+
both the file-based local proof archive and the database-backed proof store.
167+
Both those stores will trigger a notification (via the `ProofNotifier`) for
168+
received proofs, so the below might be invoked multiple times
169+
4. The Custodian finds the corresponding `address.Event` and updates its status
170+
to `StatusProofReceived`.
171+
5. It then calls `setReceiveCompleted`, which verifies that all required proofs
172+
for the transfer have been received.
173+
6. Finally, the event status is set to `StatusCompleted`, marking the end of the
174+
asset custody process. The asset is now considered fully received and
175+
settled.

0 commit comments

Comments
 (0)