mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 12:44:19 +01:00
[Client] Add vtxo expiration details to balance & Fix coin selection
* add expiry details in balance command * coin selection: sort vtxos by olderFirst * rename type * balance: add next expiration * add next expiration in offchain_balance json * print duration in nextExpiration * fix dust coin selection * refactor sort
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ark-network/ark/common/tree"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
@@ -12,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
type RedeemBranch interface {
|
||||
// UpdatePath checks for transactions of the branch onchain and updates the branch accordingly
|
||||
UpdatePath() error
|
||||
// Redeem will sign the branch of the tree and return the associated signed pset + the vtxo input
|
||||
// RedeemPath returns the list of transactions to broadcast in order to access the vtxo output
|
||||
RedeemPath() ([]string, error)
|
||||
// AddInput adds the vtxo input created by the branch
|
||||
AddVtxoInput(updater *psetv2.Updater) error
|
||||
// ExpireAt returns the expiration time of the branch
|
||||
ExpireAt() (*time.Time, error)
|
||||
}
|
||||
|
||||
type redeemBranch struct {
|
||||
@@ -25,10 +26,22 @@ type redeemBranch struct {
|
||||
branch []*psetv2.Pset
|
||||
internalKey *secp256k1.PublicKey
|
||||
sweepClosure *taproot.TapElementsLeaf
|
||||
lifetime time.Duration
|
||||
explorer Explorer
|
||||
}
|
||||
|
||||
func newRedeemBranch(ctx *cli.Context, congestionTree tree.CongestionTree, vtxo vtxo) (RedeemBranch, error) {
|
||||
sweepClosure, _, err := findSweepClosure(congestionTree)
|
||||
func newRedeemBranch(
|
||||
ctx *cli.Context,
|
||||
explorer Explorer,
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxo vtxo,
|
||||
) (RedeemBranch, error) {
|
||||
sweepClosure, seconds, err := findSweepClosure(congestionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lifetime, err := time.ParseDuration(fmt.Sprintf("%ds", seconds))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,43 +71,21 @@ func newRedeemBranch(ctx *cli.Context, congestionTree tree.CongestionTree, vtxo
|
||||
branch: branch,
|
||||
internalKey: internalKey,
|
||||
sweepClosure: sweepClosure,
|
||||
lifetime: lifetime,
|
||||
explorer: explorer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdatePath checks for transactions of the branch onchain and updates the branch accordingly
|
||||
func (r *redeemBranch) UpdatePath() error {
|
||||
for i := len(r.branch) - 1; i >= 0; i-- {
|
||||
pset := r.branch[i]
|
||||
unsignedTx, err := pset.UnsignedTx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txHash := unsignedTx.TxHash().String()
|
||||
|
||||
_, err = getTxHex(txHash)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// if no error, the tx exists onchain, so we can remove it (+ the parents) from the branch
|
||||
if i == len(r.branch)-1 {
|
||||
r.branch = []*psetv2.Pset{}
|
||||
} else {
|
||||
r.branch = r.branch[i+1:]
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RedeemPath returns the list of transactions to broadcast in order to access the vtxo output
|
||||
func (r *redeemBranch) RedeemPath() ([]string, error) {
|
||||
transactions := make([]string, 0, len(r.branch))
|
||||
|
||||
for _, pset := range r.branch {
|
||||
offchainPath, err := r.offchainPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pset := range offchainPath {
|
||||
for i, input := range pset.Inputs {
|
||||
if len(input.TapLeafScript) == 0 {
|
||||
return nil, fmt.Errorf("tap leaf script not found on input #%d", i)
|
||||
@@ -183,3 +174,68 @@ func (r *redeemBranch) AddVtxoInput(updater *psetv2.Updater) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redeemBranch) ExpireAt() (*time.Time, error) {
|
||||
lastKnownBlocktime := int64(0)
|
||||
|
||||
confirmed, blocktime, _ := getTxBlocktime(r.vtxo.poolTxid)
|
||||
|
||||
if confirmed {
|
||||
lastKnownBlocktime = blocktime
|
||||
} else {
|
||||
expirationFromNow := time.Now().Add(time.Minute).Add(r.lifetime)
|
||||
return &expirationFromNow, nil
|
||||
}
|
||||
|
||||
for _, pset := range r.branch {
|
||||
utx, _ := pset.UnsignedTx()
|
||||
txid := utx.TxHash().String()
|
||||
|
||||
confirmed, blocktime, err := getTxBlocktime(txid)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if confirmed {
|
||||
lastKnownBlocktime = blocktime
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
t := time.Unix(lastKnownBlocktime, 0).Add(r.lifetime)
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
// offchainPath checks for transactions of the branch onchain and returns only the offchain part
|
||||
func (r *redeemBranch) offchainPath() ([]*psetv2.Pset, error) {
|
||||
offchainPath := append([]*psetv2.Pset{}, r.branch...)
|
||||
|
||||
for i := len(r.branch) - 1; i >= 0; i-- {
|
||||
pset := r.branch[i]
|
||||
unsignedTx, err := pset.UnsignedTx()
|
||||
if err != nil {
|
||||
fmt.Println("error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txHash := unsignedTx.TxHash().String()
|
||||
|
||||
_, err = r.explorer.GetTxHex(txHash)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// if no error, the tx exists onchain, so we can remove it (+ the parents) from the branch
|
||||
if i == len(r.branch)-1 {
|
||||
offchainPath = []*psetv2.Pset{}
|
||||
} else {
|
||||
offchainPath = r.branch[i+1:]
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
return offchainPath, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user