Skip to content

assets swap deposits [5/N]: add asset deposit manager #983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
53aa089
assets: add asset HTLC helpers
bhandras Jul 14, 2025
83c66fd
assets: add no-csv option to the asset HTLC to support package relay
bhandras Jul 14, 2025
0e7e413
assets: extend the tapd client and add high-level TAP helpers
bhandras Jul 14, 2025
070b2a9
swapserverrpc: add proto definitions for server asset deposit RPCs
bhandras Jul 14, 2025
9420ee6
assets: add deposit kit encapsulating TAP deposit interactions
bhandras Jul 15, 2025
2d516e9
looprpc: add client side asset deposit service proto stubs
bhandras Jul 15, 2025
204a98e
loop: add stubs and CLI commands for the asset deposit subserver
bhandras Jul 15, 2025
3a213d0
loopd: add profiler to the Loop daemon
bhandras Jul 15, 2025
606efa3
assets: add asset deposit sweeper
bhandras Jul 15, 2025
b10f049
loopdb: add basic schema for asset deposits
bhandras Jul 15, 2025
40ceaf0
assets+loopd: add scaffolding for the asset deposit manager
bhandras Jul 15, 2025
607c6e0
assets+loopdb: implement new asset deposit functionality
bhandras Jul 15, 2025
16259a2
assets+loopdb: implement functionality to list asset deposits
bhandras Jul 15, 2025
cfdf064
assets+loopdb: handle asset deposit expiry and timeout sweep
bhandras Jul 15, 2025
ad9074d
assets+loopdb: recover active deposits on startup
bhandras Jul 15, 2025
c90c45f
assets+loopdb: implement asset deposit withdrawal
bhandras Jul 15, 2025
bdc2606
assets+loopdb: publish cooperative deposit withdrawal transaction
bhandras Jul 15, 2025
554485c
assets: implement asset deposit key reveal
bhandras Jul 15, 2025
392fc0d
assets: add support for co-signing a zero-fee deposit HTLC spend
bhandras Jul 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
656 changes: 627 additions & 29 deletions assets/client.go

Large diffs are not rendered by default.

202 changes: 202 additions & 0 deletions assets/deposit/deposit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package deposit

import (
"encoding/hex"
"fmt"
"time"

"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcwallet/wtxmgr"
"github.com/lightninglabs/taproot-assets/proof"
)

// State is the enum used for deposit states.
type State uint8

const (
// StateInitiated indicates that the deposit has been initiated by the
// client.
StateInitiated State = 0

// StatePending indicates that the deposit is pending confirmation on
// the blockchain.
StatePending State = 1

// StateConfirmed indicates that the deposit has been confirmed on the
// blockchain.
StateConfirmed State = 2

// StateExpired indicates that the deposit has expired.
StateExpired State = 3

// StateTimeoutSweepPublished indicates that the timeout sweep has been
// published.
StateTimeoutSweepPublished State = 4

// StateWithdrawn indicates that the deposit has been withdrawn.
StateWithdrawn State = 5

// StateCooperativeSweepPublished indicates that the cooperative sweep
// withdrawing the deposit has been published.
StateCooperativeSweepPublished State = 6

// StateKeyRevealed indicates that the client has revealed a valid key
// for the deposit which is now ready to be swept.
StateKeyRevealed State = 7

// StateSpent indicates that the deposit has been spent.
StateSpent State = 8

// StateSwept indicates that the deposit has been swept, either by a
// timeout sweep or a cooperative (ie withdrawal) sweep.
StateSwept State = 9
)

// String coverts a deposit state to human readable string.
func (s State) String() string {
switch s {
case StateInitiated:
return "Initiated"

case StatePending:
return "Pending"

case StateConfirmed:
return "Confirmed"

case StateExpired:
return "Expired"

case StateTimeoutSweepPublished:
return "TimeoutSweepPublished"

case StateWithdrawn:
return "Withdrawn"

case StateCooperativeSweepPublished:
return "CooperativeSweepPublished"

case StateKeyRevealed:
return "KeyRevealed"

case StateSpent:
return "Spent"

case StateSwept:
return "Swept"

default:
return "Unknown"
}
}

// IsFinal returns true if the deposit state is final, meaning that no further
// actions can be taken on the deposit.
func (s State) IsFinal() bool {
return s == StateSpent || s == StateSwept
}

// DepositInfo holds publicly available information about an asset deposit.
// It is used to communicate deposit details to clients of the deposit Manager.
type DepositInfo struct {
// ID is the unique identifier for this deposit which will also be used
// to store the deposit in both the server and client databases.
ID string

// Verison is the protocol version of the deposit.
Version AssetDepositProtocolVersion

// CreatedAt is the time when the deposit was created (on the client).
CreatedAt time.Time

// Amount is the amount of asset to be deposited.
Amount uint64

// Addr is the TAP deposit address where the asset will be sent.
Addr string

// State is the deposit state.
State State

// ConfirmationHeight is the block height at which the deposit was
// confirmed.
ConfirmationHeight uint32

// Outpoint is the anchor outpoint of the deposit. It is only set if the
// deposit has been confirmed.
Outpoint *wire.OutPoint

// Expiry is the block height at which the deposit will expire. It is
// only set if the deposit has been confirmed.
Expiry uint32

// SweepAddr is the address we'll use to sweep the deposit back after
// timeout or if cooperatively withdrawing.
SweepAddr string
}

// Copy creates a copy of the DepositInfo struct.
func (d *DepositInfo) Copy() *DepositInfo {
info := &DepositInfo{
ID: d.ID,
Version: d.Version,
CreatedAt: d.CreatedAt,
Amount: d.Amount,
Addr: d.Addr,
State: d.State,
ConfirmationHeight: d.ConfirmationHeight,
Expiry: d.Expiry,
SweepAddr: d.SweepAddr,
}

if d.Outpoint != nil {
info.Outpoint = &wire.OutPoint{
Hash: d.Outpoint.Hash,
Index: d.Outpoint.Index,
}
}

return info
}

// Deposit is the struct that holds all the information about an asset deposit.
type Deposit struct {
*Kit

*DepositInfo

// PkScript is the pkscript of the deposit anchor output.
PkScript []byte

// Proof is the proof of the deposit transfer.
Proof *proof.Proof

// AnchorRootHash is the root hash of the deposit anchor output.
AnchorRootHash []byte
}

// label returns a string label that we can use for marking a transfer funding
// the deposit. This is useful if we need to filter deposits.
func (d *Deposit) label() string {
return fmt.Sprintf("deposit %v", d.ID)
}

// lockID converts a deposit ID to a lock ID. The lock ID is used to lock inputs
// used for the deposit sweep transaction. Note that we assume that the deposit
// ID is a hex-encoded string of the same length as the lock ID.
func (d *Deposit) lockID() (wtxmgr.LockID, error) {
var lockID wtxmgr.LockID
depositIDBytes, err := hex.DecodeString(d.ID)
if err != nil {
return wtxmgr.LockID{}, err
}

if len(depositIDBytes) != len(lockID) {
return wtxmgr.LockID{}, fmt.Errorf("invalid deposit ID "+
"length: %d", len(depositIDBytes))
}

copy(lockID[:], depositIDBytes)

return lockID, nil
}
Loading