Skip to content

Commit 41b703d

Browse files
committed
assets: add basic swap out struct
1 parent 1a73d66 commit 41b703d

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed

assets/interfaces.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package assets
2+
3+
import (
4+
"context"
5+
6+
"github.com/btcsuite/btcd/btcutil"
7+
"github.com/btcsuite/btcd/btcutil/psbt"
8+
"github.com/btcsuite/btcd/chaincfg"
9+
"github.com/btcsuite/btcd/chaincfg/chainhash"
10+
"github.com/btcsuite/btcd/wire"
11+
"github.com/lightninglabs/lndclient"
12+
"github.com/lightninglabs/loop/fsm"
13+
"github.com/lightninglabs/taproot-assets/asset"
14+
"github.com/lightninglabs/taproot-assets/proof"
15+
"github.com/lightninglabs/taproot-assets/tappsbt"
16+
"github.com/lightninglabs/taproot-assets/taprpc"
17+
"github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
18+
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
19+
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
20+
"github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
21+
"github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
22+
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
23+
"github.com/lightningnetwork/lnd/chainntnfs"
24+
"github.com/lightningnetwork/lnd/keychain"
25+
"github.com/lightningnetwork/lnd/lntypes"
26+
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
27+
)
28+
29+
const (
30+
// DefaultSwapCSVExpiry is the default expiry for a swap in blocks.
31+
DefaultSwapCSVExpiry = int32(24)
32+
33+
defaultHtlcFeeConfTarget = 3
34+
defaultHtlcConfRequirement = 2
35+
36+
AssetKeyFamily = 696969
37+
)
38+
39+
// TapdClient is an interface that groups the methods required to interact with
40+
// the taproot-assets server and the wallet.
41+
type AssetClient interface {
42+
taprpc.TaprootAssetsClient
43+
wrpc.AssetWalletClient
44+
mintrpc.MintClient
45+
universerpc.UniverseClient
46+
tapdevrpc.TapDevClient
47+
48+
// FundAndSignVpacket funds ands signs a vpacket.
49+
FundAndSignVpacket(ctx context.Context,
50+
vpkt *tappsbt.VPacket) (*tappsbt.VPacket, error)
51+
52+
// PrepareAndCommitVirtualPsbts prepares and commits virtual psbts.
53+
PrepareAndCommitVirtualPsbts(ctx context.Context,
54+
vpkt *tappsbt.VPacket, feeRateSatPerKVByte chainfee.SatPerVByte,
55+
changeKeyDesc *keychain.KeyDescriptor, params *chaincfg.Params) (
56+
*psbt.Packet, []*tappsbt.VPacket, []*tappsbt.VPacket,
57+
*assetwalletrpc.CommitVirtualPsbtsResponse, error)
58+
59+
// LogAndPublish logs and publishes the virtual psbts.
60+
LogAndPublish(ctx context.Context, btcPkt *psbt.Packet,
61+
activeAssets []*tappsbt.VPacket, passiveAssets []*tappsbt.VPacket,
62+
commitResp *wrpc.CommitVirtualPsbtsResponse) (*taprpc.SendAssetResponse,
63+
error)
64+
65+
// GetAssetBalance returns the balance of the given asset.
66+
GetAssetBalance(ctx context.Context, assetId []byte) (
67+
uint64, error)
68+
69+
// DeriveNewKeys derives a new internal and script key.
70+
DeriveNewKeys(ctx context.Context) (asset.ScriptKey,
71+
keychain.KeyDescriptor, error)
72+
73+
// AddHoldInvoice adds a new hold invoice.
74+
AddHoldInvoice(ctx context.Context, pHash lntypes.Hash,
75+
assetId []byte, assetAmt uint64, memo string) (
76+
*tapchannelrpc.AddInvoiceResponse, error)
77+
78+
// ImportProofFile imports the proof file and returns the last proof.
79+
ImportProofFile(ctx context.Context, rawProofFile []byte) (
80+
*proof.Proof, error)
81+
}
82+
83+
// SwapStore is an interface that groups the methods required to store swap
84+
// information.
85+
type SwapStore interface {
86+
// CreateAssetSwapOut creates a new swap out in the store.
87+
CreateAssetSwapOut(ctx context.Context, swap *SwapOut) error
88+
89+
// UpdateAssetSwapHtlcOutpoint updates the htlc outpoint of a swap out.
90+
UpdateAssetSwapHtlcOutpoint(ctx context.Context, swapHash lntypes.Hash,
91+
outpoint *wire.OutPoint, confirmationHeight int32) error
92+
93+
// UpdateAssetSwapOutProof updates the proof of a swap out.
94+
UpdateAssetSwapOutProof(ctx context.Context, swapHash lntypes.Hash,
95+
rawProof []byte) error
96+
97+
// UpdateAssetSwapOutSweepTx updates the sweep tx of a swap out.
98+
UpdateAssetSwapOutSweepTx(ctx context.Context,
99+
swapHash lntypes.Hash, sweepTxid chainhash.Hash,
100+
confHeight int32, sweepPkscript []byte) error
101+
102+
// InsertAssetSwapUpdate inserts a new swap update in the store.
103+
InsertAssetSwapUpdate(ctx context.Context,
104+
swapHash lntypes.Hash, state fsm.StateType) error
105+
106+
UpdateAssetSwapOutPreimage(ctx context.Context,
107+
swapHash lntypes.Hash, preimage lntypes.Preimage) error
108+
}
109+
110+
// BlockHeightSubscriber is responsible for subscribing to the expiry height
111+
// of a swap, as well as getting the current block height.
112+
type BlockHeightSubscriber interface {
113+
// SubscribeExpiry subscribes to the expiry of a swap. It returns true
114+
// if the expiry is already past. Otherwise, it returns false and calls
115+
// the expiryFunc when the expiry height is reached.
116+
SubscribeExpiry(swapHash [32]byte,
117+
expiryHeight int32, expiryFunc func()) bool
118+
// GetBlockHeight returns the current block height.
119+
GetBlockHeight() int32
120+
}
121+
122+
// InvoiceSubscriber is responsible for subscribing to an invoice.
123+
type InvoiceSubscriber interface {
124+
// SubscribeInvoice subscribes to an invoice. The update callback is
125+
// called when the invoice is updated and the error callback is called
126+
// when an error occurs.
127+
SubscribeInvoice(ctx context.Context, invoiceHash lntypes.Hash,
128+
updateCallback func(lndclient.InvoiceUpdate, error)) error
129+
}
130+
131+
// TxConfirmationSubscriber is responsible for subscribing to the confirmation
132+
// of a transaction.
133+
type TxConfirmationSubscriber interface {
134+
135+
// SubscribeTxConfirmation subscribes to the confirmation of a
136+
// pkscript on the chain. The callback is called when the pkscript is
137+
// confirmed or when an error occurs.
138+
SubscribeTxConfirmation(ctx context.Context, swapHash lntypes.Hash,
139+
txid *chainhash.Hash, pkscript []byte, numConfs int32,
140+
eightHint int32, cb func(*chainntnfs.TxConfirmation, error)) error
141+
}
142+
143+
// ExchangeRateProvider is responsible for providing the exchange rate between
144+
// assets.
145+
type ExchangeRateProvider interface {
146+
// GetSatsPerAssetUnit returns the amount of satoshis per asset unit.
147+
GetSatsPerAssetUnit(assetId []byte) (btcutil.Amount, error)
148+
}

assets/log.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package assets
2+
3+
import (
4+
"github.com/btcsuite/btclog/v2"
5+
"github.com/lightningnetwork/lnd/build"
6+
)
7+
8+
// Subsystem defines the sub system name of this package.
9+
const Subsystem = "ASSETS"
10+
11+
// log is a logger that is initialized with no output filters. This
12+
// means the package will not perform any logging by default until the caller
13+
// requests it.
14+
var log btclog.Logger
15+
16+
// The default amount of logging is none.
17+
func init() {
18+
UseLogger(build.NewSubLogger(Subsystem, nil))
19+
}
20+
21+
// UseLogger uses a specified Logger to output package logging info.
22+
// This should be used in preference to SetLogWriter if the caller is also
23+
// using btclog.
24+
func UseLogger(logger btclog.Logger) {
25+
log = logger
26+
}

assets/swap_out.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package assets
2+
3+
import (
4+
"github.com/btcsuite/btcd/btcec/v2"
5+
"github.com/btcsuite/btcd/txscript"
6+
"github.com/btcsuite/btcd/wire"
7+
"github.com/lightninglabs/loop/assets/htlc"
8+
"github.com/lightninglabs/loop/fsm"
9+
"github.com/lightninglabs/taproot-assets/commitment"
10+
"github.com/lightninglabs/taproot-assets/proof"
11+
12+
"github.com/lightningnetwork/lnd/keychain"
13+
"github.com/lightningnetwork/lnd/lntypes"
14+
)
15+
16+
// SwapOut is a struct that represents a swap out. It contains all the
17+
// information needed to perform a swap out.
18+
type SwapOut struct {
19+
// We embed swapkit for all script related helpers.
20+
*htlc.SwapKit
21+
22+
// SwapPreimage is the preimage of the swap, that enables spending
23+
// the success path, it's hash is the main identifier of the swap.
24+
SwapPreimage lntypes.Preimage
25+
26+
// State is the current state of the swap.
27+
State fsm.StateType
28+
29+
// InitiationHeight is the height at which the swap was initiated.
30+
InitiationHeight uint32
31+
32+
// ClientKeyLocator is the key locator of the clients key.
33+
ClientKeyLocator keychain.KeyLocator
34+
35+
// HtlcOutPoint is the outpoint of the htlc that was created to
36+
// perform the swap.
37+
HtlcOutPoint *wire.OutPoint
38+
39+
// HtlcConfirmationHeight is the height at which the htlc was
40+
// confirmed.
41+
HtlcConfirmationHeight uint32
42+
43+
// SweepOutpoint is the outpoint of the htlc that was swept.
44+
SweepOutpoint *wire.OutPoint
45+
46+
// SweepConfirmationHeight is the height at which the sweep was
47+
// confirmed.
48+
SweepConfirmationHeight uint32
49+
50+
// SweepPkscript is the pkscript of the sweep transaction.
51+
SweepPkscript []byte
52+
53+
// RawHtlcProof is the raw htlc proof that we need to send to the
54+
// receiver. We only keep this in the OutFSM struct as we don't want
55+
// to save it in the store.
56+
RawHtlcProof []byte
57+
}
58+
59+
// NewSwapOut creates a new swap out.
60+
func NewSwapOut(swapHash lntypes.Hash, amt uint64,
61+
assetId []byte, clientKeyDesc *keychain.KeyDescriptor,
62+
senderPubkey *btcec.PublicKey, csvExpiry, initiationHeight uint32,
63+
) *SwapOut {
64+
65+
return &SwapOut{
66+
SwapKit: &htlc.SwapKit{
67+
SwapHash: swapHash,
68+
Amount: amt,
69+
SenderPubKey: senderPubkey,
70+
ReceiverPubKey: clientKeyDesc.PubKey,
71+
CsvExpiry: csvExpiry,
72+
AssetID: assetId,
73+
},
74+
State: Init,
75+
InitiationHeight: initiationHeight,
76+
ClientKeyLocator: clientKeyDesc.KeyLocator,
77+
}
78+
}
79+
80+
// genTaprootAssetRootFromProof generates the taproot asset root from the proof
81+
// of the swap.
82+
func (s *SwapOut) genTaprootAssetRootFromProof(proof *proof.Proof) ([]byte,
83+
error) {
84+
85+
assetCpy := proof.Asset.Copy()
86+
assetCpy.PrevWitnesses[0].SplitCommitment = nil
87+
sendCommitment, err := commitment.NewAssetCommitment(
88+
assetCpy,
89+
)
90+
if err != nil {
91+
return nil, err
92+
}
93+
94+
version := commitment.TapCommitmentV2
95+
assetCommitment, err := commitment.NewTapCommitment(
96+
&version, sendCommitment,
97+
)
98+
if err != nil {
99+
return nil, err
100+
}
101+
taprootAssetRoot := txscript.AssembleTaprootScriptTree(
102+
assetCommitment.TapLeaf(),
103+
).RootNode.TapHash()
104+
105+
return taprootAssetRoot[:], nil
106+
}

0 commit comments

Comments
 (0)