Add support for Out Of Round txs (#359)

* [common] rework address encoding

* new address encoding

* replace offchain address by vtxo output key in DB

* merge migrations files into init one

* fix txbuilder fixtures

* fix transaction events

* OOR scheme

* fix conflicts

* [sdk] OOR

* update WASM wrappers

* revert renaming

* revert API changes

* update parser.go

* fix vtxosToTxsCovenantless

* add settled and spent in Utxo and Transaction

* Fixes (#5)

* Revert unneeded changes and rename claim to settle

* Revert changes to wasm and rename claim to settle

---------

Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com>
This commit is contained in:
Louis Singer
2024-10-24 17:43:27 +02:00
committed by GitHub
parent b536a9e652
commit bcb2b2075f
41 changed files with 1103 additions and 1390 deletions

View File

@@ -51,10 +51,7 @@ type covenantlessService struct {
currentRoundLock sync.Mutex
currentRound *domain.Round
treeSigningSessions map[string]*musigSigningSession
asyncPaymentsCache map[string]struct { // redeem txid -> receivers
receivers []domain.Receiver
expireAt int64
}
asyncPaymentsCache map[string]asyncPaymentData
}
func NewCovenantlessService(
@@ -69,11 +66,6 @@ func NewCovenantlessService(
return nil, fmt.Errorf("failed to fetch pubkey: %s", err)
}
asyncPaymentsCache := make(map[string]struct {
receivers []domain.Receiver
expireAt int64
})
svc := &covenantlessService{
network: network,
pubkey: pubkey,
@@ -90,7 +82,7 @@ func NewCovenantlessService(
eventsCh: make(chan domain.RoundEvent),
transactionEventsCh: make(chan TransactionEvent),
currentRoundLock: sync.Mutex{},
asyncPaymentsCache: asyncPaymentsCache,
asyncPaymentsCache: make(map[string]asyncPaymentData),
treeSigningSessions: make(map[string]*musigSigningSession),
boardingExitDelay: boardingExitDelay,
}
@@ -269,19 +261,16 @@ func (s *covenantlessService) CompleteAsyncPayment(
vtxoPubkey := hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey))
// all pending except the last one
isPending := outIndex < len(asyncPayData.receivers)-1
vtxos = append(vtxos, domain.Vtxo{
VtxoKey: domain.VtxoKey{
Txid: redeemTxid,
VOut: uint32(outIndex),
},
Pubkey: vtxoPubkey,
Amount: uint64(out.Value),
ExpireAt: asyncPayData.expireAt,
RedeemTx: redeemTx,
Pending: isPending,
Pubkey: vtxoPubkey,
Amount: uint64(out.Value),
ExpireAt: asyncPayData.expireAt,
RoundTxid: asyncPayData.roundTxid,
RedeemTx: redeemTx,
})
}
@@ -338,6 +327,8 @@ func (s *covenantlessService) CreateAsyncPayment(
vtxosInputs := make([]domain.Vtxo, 0, len(inputs))
expiration := vtxos[0].ExpireAt
roundTxid := vtxos[0].RoundTxid
for _, vtxo := range vtxos {
if vtxo.Spent {
return "", fmt.Errorf("all vtxos must be unspent")
@@ -350,11 +341,9 @@ func (s *covenantlessService) CreateAsyncPayment(
if vtxo.Swept {
return "", fmt.Errorf("all vtxos must be swept")
}
if vtxo.Pending {
return "", fmt.Errorf("all vtxos must be claimed")
}
if vtxo.ExpireAt < expiration {
roundTxid = vtxo.RoundTxid
expiration = vtxo.ExpireAt
}
@@ -373,12 +362,10 @@ func (s *covenantlessService) CreateAsyncPayment(
return "", fmt.Errorf("failed to parse redeem tx: %s", err)
}
s.asyncPaymentsCache[redeemPtx.UnsignedTx.TxID()] = struct {
receivers []domain.Receiver
expireAt int64
}{
s.asyncPaymentsCache[redeemPtx.UnsignedTx.TxID()] = asyncPaymentData{
receivers: receivers,
expireAt: expiration,
roundTxid: roundTxid,
}
return redeemTx, nil
@@ -1588,6 +1575,12 @@ func findForfeitTxBitcoin(
return "", fmt.Errorf("forfeit tx not found")
}
type asyncPaymentData struct {
receivers []domain.Receiver
expireAt int64
roundTxid string
}
// musigSigningSession holds the state of ephemeral nonces and signatures in order to coordinate the signing of the tree
type musigSigningSession struct {
lock sync.Mutex