Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jackstar12 committed Nov 4, 2024
1 parent e972412 commit 121c682
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 503 deletions.
64 changes: 35 additions & 29 deletions boltz/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,27 @@ type OutputResult struct {
Fee uint64
}

type Results map[string]OutputResult
type ConstructResult struct {
Transaction Transaction
Details map[string]OutputResult
Err error
TransactionId string
}

func (results Results) SetErr(id string, err error) {
if results[id].Err == nil {
results[id] = OutputResult{Err: err}
func (result ConstructResult) SwapResult(id string) OutputResult {
details := result.Details[id]
if result.Err != nil && details.Err == nil {
return OutputResult{Err: result.Err}
}
return details
}

func ConstructTransaction(network *Network, currency Currency, outputs []OutputDetails, satPerVbyte float64, boltzApi *Api) (Transaction, Results, error) {
func ConstructTransaction(network *Network, currency Currency, outputs []OutputDetails, satPerVbyte float64, boltzApi *Api) ConstructResult {
construct := constructBtcTransaction
if currency == CurrencyLiquid {
construct = constructLiquidTransaction
}
results := make(Results, len(outputs))
swapErrors := make(map[string]OutputResult, len(outputs))

getOutValues := func(fee uint64) map[string]uint64 {
outValues := make(map[string]uint64)
Expand All @@ -104,31 +111,32 @@ func ConstructTransaction(network *Network, currency Currency, outputs []OutputD
feeRemainder = 0

value, err := output.LockupTransaction.VoutValue(output.Vout)
if err != nil {
results.SetErr(output.SwapId, err)
continue
if err == nil {
if value < output.Fee {
err = fmt.Errorf("value less than fee: %d < %d", value, output.Fee)
}
}
if value < output.Fee {
results.SetErr(output.SwapId, fmt.Errorf("value less than fee: %d < %d", value, output.Fee))
continue
if err != nil {
swapErrors[output.SwapId] = OutputResult{Err: err}
} else {
swapErrors[output.SwapId] = OutputResult{Fee: output.Fee}
outValues[output.Address] += value - output.Fee
}

results[output.SwapId] = OutputResult{Fee: output.Fee}
outValues[output.Address] += value - output.Fee
}
return outValues
}

noFeeTransaction, err := construct(network, outputs, getOutValues(0))
if err != nil {
return nil, nil, err
return ConstructResult{Err: err}
}

fee := uint64(math.Ceil(float64(noFeeTransaction.VSize()) * satPerVbyte))

transaction, err := construct(network, outputs, getOutValues(fee))
if err != nil {
return nil, nil, err
return ConstructResult{Err: err}
}

var valid []OutputDetails
Expand Down Expand Up @@ -209,7 +217,7 @@ func ConstructTransaction(network *Network, currency Currency, outputs []OutputD
}()
if err != nil {
if output.IsRefund() {
results[output.SwapId] = OutputResult{Err: err}
swapErrors[output.SwapId] = OutputResult{Err: err}
reconstruct = true
} else {
nonCoop := outputs[i]
Expand All @@ -222,20 +230,18 @@ func ConstructTransaction(network *Network, currency Currency, outputs []OutputD
}
}

if len(valid) == 0 {
return nil, results, fmt.Errorf("all outputs invalid")
}

if reconstruct {
transaction, newResults, err := ConstructTransaction(network, currency, valid, satPerVbyte, boltzApi)
if err != nil {
return nil, nil, err
if reconstruct && len(valid) > 0 {
newResult := ConstructTransaction(network, currency, valid, satPerVbyte, boltzApi)
if newResult.Err != nil {
return newResult
}
for id, result := range newResults {
results[id] = result
for id, result := range swapErrors {
if _, ok := newResult.Details[id]; !ok {
newResult.Details[id] = result
}
}
return transaction, results, nil
return newResult
}

return transaction, results, err
return ConstructResult{Transaction: transaction, Details: swapErrors, TransactionId: transaction.Hash()}
}
268 changes: 134 additions & 134 deletions boltzrpc/boltzrpc.pb.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions boltzrpc/boltzrpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ service Boltz {
Claim swaps manually.
This is only required when no claim address has been set and the swap does not have an associated wallet.
*/
rpc ClaimSwaps (ClaimSwapsRequest) returns (ClaimSwapsResponse);
rpc ClaimSwaps (ClaimSwapsRequest) returns (ClaimSwapsResponse) {option deprecated = true;};

/*
Claim swaps manually.
Sweep swaps manually.
This is only required when no claim address has been set and the swap does not have an associated wallet.
*/
rpc SweepSwaps (SweepSwapsRequest) returns (SweepSwapsResponse);
Expand Down
9 changes: 7 additions & 2 deletions boltzrpc/boltzrpc_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions boltzrpc/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ func (boltz *Boltz) RefundSwap(request *boltzrpc.RefundSwapRequest) (*boltzrpc.G
return boltz.Client.RefundSwap(boltz.Ctx, request)
}

func (boltz *Boltz) ClaimSwaps(request *boltzrpc.ClaimSwapsRequest) (*boltzrpc.ClaimSwapsResponse, error) {
return boltz.Client.ClaimSwaps(boltz.Ctx, request)
}

func (boltz *Boltz) SweepSwaps(currency boltzrpc.Currency) (*boltzrpc.SweepSwapsResponse, error) {
return boltz.Client.SweepSwaps(boltz.Ctx, &boltzrpc.SweepSwapsRequest{Currency: currency})
}
Expand Down
1 change: 0 additions & 1 deletion cmd/boltzcli/boltzcli.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ func main() {
createReverseSwapCommand,
createChainSwapCommand,
refundSwapCommand,
claimSwapsCommand,

autoSwapCommands,

Expand Down
26 changes: 0 additions & 26 deletions cmd/boltzcli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -1329,32 +1329,6 @@ func refundSwap(ctx *cli.Context) error {
return nil
}

var claimSwapsCommand = &cli.Command{
Name: "claimswaps",
Category: "Swaps",
Usage: "Claim x-to-chain swaps manually",
ArgsUsage: "addresss|wallet ids...",
Action: requireNArgs(2, claimSwaps),
}

func claimSwaps(ctx *cli.Context) error {
client := getClient(ctx)
request := &boltzrpc.ClaimSwapsRequest{SwapIds: ctx.Args().Tail()}
address := ctx.Args().First()
walletId, err := getWalletId(ctx, address)
if err == nil {
request.Destination = &boltzrpc.ClaimSwapsRequest_WalletId{WalletId: *walletId}
} else {
request.Destination = &boltzrpc.ClaimSwapsRequest_Address{Address: address}
}
response, err := client.ClaimSwaps(request)
if err != nil {
return err
}
fmt.Println("Claim transaction ID: " + response.TransactionId)
return nil
}

var createReverseSwapCommand = &cli.Command{
Name: "createreverseswap",
Category: "Swaps",
Expand Down
2 changes: 1 addition & 1 deletion docs/grpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Claim swaps manually. This is only required when no claim address has been set a

#### SweepSwaps

Claim swaps manually. This is only required when no claim address has been set and the swap does not have an associated wallet.
Sweep swaps manually. This is only required when no claim address has been set and the swap does not have an associated wallet.

| Request | Response |
| ------- | -------- |
Expand Down
10 changes: 4 additions & 6 deletions nursery/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b
break
}

nursery.checkSweep(nursery.getChainSwapClaimOutput(swap))
if nursery.checkSweep(nursery.getChainSwapClaimOutput(swap)) {
return
}
}

logger.Debugf("Updating status of Chain Swap %s to %s", swap.Id, parsedStatus)
Expand Down Expand Up @@ -226,14 +228,10 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b
}

if swap.FromData.LockupTransactionId != "" {
if err := nursery.checkSweep(nursery.getChainSwapRefundOutput(swap)); err != nil {
handleError("Could not refund Swap " + swap.Id + ": " + err.Error())
if nursery.checkSweep(nursery.getChainSwapRefundOutput(swap)) {
return
}
}

return
}
nursery.sendChainSwapUpdate(*swap)

}
57 changes: 34 additions & 23 deletions nursery/claimer.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,16 @@ type CheckedOutput struct {
outputResult *onchain.OutputResult
}

func (nursery *Nursery) checkOutput(output *Output) *CheckedOutput {
result, err := nursery.onchain.FindOutput(output.findArgs)
func (claimer *Claimer) checkOutput(output *Output) *CheckedOutput {
if output.Address == "" {
verb := "claimed"
if output.IsRefund() {
verb = "refunded"
}
output.setError(fmt.Errorf("swap %s can not be %s, no address set", output.SwapId, verb))
return nil
}
result, err := claimer.onchain.FindOutput(output.findArgs)
if err != nil {
output.setError(err)
return nil
Expand All @@ -67,14 +75,15 @@ func (nursery *Nursery) checkOutput(output *Output) *CheckedOutput {
return &CheckedOutput{Output: output, outputResult: result}
}

func (nursery *Nursery) checkSweep(output *Output) (err error) {
if checked := nursery.checkOutput(output); checked != nil {
func (nursery *Nursery) checkSweep(output *Output) bool {
if checked := nursery.claimer.checkOutput(output); checked != nil {
if reason := nursery.claimer.shouldSweep(checked); reason != ReasonNone {
_, err := nursery.sweep(reason, nil, output.findArgs.Currency)
return err
result := nursery.sweep(reason, output.findArgs.Currency)
return result.SwapResult(output.SwapId).Err != nil
}
return false
}
return nil
return true
}

type SweepReason string
Expand Down Expand Up @@ -120,8 +129,8 @@ func (claimer *Claimer) shouldSweep(output *CheckedOutput) SweepReason {

func (nursery *Nursery) SweepAll(reason SweepReason, symbols []boltz.Currency) {
for _, currency := range symbols {
if _, err := nursery.sweep(reason, nil, currency); err != nil {
logger.Errorf("could not sweep %s: %s", currency, err)
if result := nursery.sweep(reason, currency); result.Err != nil {
logger.Errorf("could not sweep %s: %s", currency, result.Err)
}
}
}
Expand Down Expand Up @@ -152,45 +161,47 @@ func (nursery *Nursery) getAllOutputs(tenantId *database.Id, currency boltz.Curr
for _, swap := range refundableChain {
outputs = append(outputs, nursery.getChainSwapRefundOutput(swap))
}
var checked []*CheckedOutput
var result []*CheckedOutput
for _, output := range outputs {
checked = append(checked, nursery.checkOutput(output))
if checked := nursery.claimer.checkOutput(output); checked != nil {
result = append(result, checked)
}
}
return checked, nil
return result, nil
}

func (nursery *Nursery) Sweep(tenantId *database.Id, currency boltz.Currency) (string, error) {
func (nursery *Nursery) Sweep(currency boltz.Currency) (string, error) {
outputs, err := nursery.getAllOutputs(nil, currency)
if err != nil {
return "", fmt.Errorf("could not query claimable outputs: %w", err)
}
nursery.claimer.outputs[currency] = outputs
return nursery.sweep(ReasonForced, tenantId, currency)
result := nursery.sweep(ReasonForced, currency)
return result.TransactionId, result.Err
}

func (nursery *Nursery) sweep(reason SweepReason, tenantId *database.Id, currency boltz.Currency) (string, error) {
func (nursery *Nursery) sweep(reason SweepReason, currency boltz.Currency) boltz.ConstructResult {
outputs := nursery.claimer.outputs[currency]
currentHeight, err := nursery.onchain.GetBlockHeight(currency)
if err != nil {
return "", fmt.Errorf("could not get block height: %w", err)
logger.Warnf("Could not get block height for %s sweep, assuming all outputs to be non-coop: %s", currency, err)
}
for _, output := range outputs {
output.Cooperative = output.TimeoutBlockHeight > currentHeight
output.Cooperative = currentHeight != 0 && output.TimeoutBlockHeight > currentHeight
logger.Debugf(
"Output for swap %s cooperative: %t (%d > %d)",
output.SwapId, output.Cooperative, output.TimeoutBlockHeight, currentHeight,
)
}
if len(outputs) > 0 {
logger.Infof("Sweeping %d outputs for currency %s (reason: %s)", len(outputs), currency, reason)
txId, err := nursery.createTransaction(currency, outputs)
if err != nil {
return "", err
result := nursery.createTransaction(currency, outputs)
if result.Err == nil {
nursery.claimer.outputs[currency] = nil
}
nursery.claimer.outputs[currency] = nil
return txId, nil
return result
}
return "", nil
return boltz.ConstructResult{}
}

func (claimer *Claimer) SweepableBalance(currency boltz.Currency, walletId *database.Id) uint64 {
Expand Down
Loading

0 comments on commit 121c682

Please sign in to comment.