Skip to content

Commit

Permalink
Add forfeit address in GetInfo (ark-network#326)
Browse files Browse the repository at this point in the history
* keep track of forfeit transaction funds

* [btc-embedded] use p2wpkh address

* [sdk] fix clients

* use script as argument of BuildForfeitTxs
  • Loading branch information
louisinger authored Sep 25, 2024
1 parent 877b7d3 commit 2be78b0
Show file tree
Hide file tree
Showing 33 changed files with 507 additions and 306 deletions.
3 changes: 3 additions & 0 deletions api-spec/openapi/swagger/ark/v1/service.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@
},
"boardingDescriptorTemplate": {
"type": "string"
},
"forfeitAddress": {
"type": "string"
}
}
},
Expand Down
1 change: 1 addition & 0 deletions api-spec/protobuf/ark/v1/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ message GetInfoResponse {
string network = 5;
int64 dust = 6;
string boarding_descriptor_template = 7;
string forfeit_address = 8;
}

// EVENT TYPES
Expand Down
485 changes: 248 additions & 237 deletions api-spec/protobuf/gen/ark/v1/service.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ func config(ctx *cli.Context) error {
"dust": cfgData.Dust,
"boarding_descriptor_template": cfgData.BoardingDescriptorTemplate,
"explorer_url": cfgData.ExplorerURL,
"forfeit_address": cfgData.ForfeitAddress,
}

return printJSON(cfg)
Expand Down
11 changes: 2 additions & 9 deletions common/bitcointree/forfeit.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package bitcointree

import (
"github.com/ark-network/ark/common"
"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)

func BuildForfeitTxs(
Expand All @@ -14,14 +12,9 @@ func BuildForfeitTxs(
vtxoAmount,
connectorAmount,
feeAmount uint64,
vtxoScript []byte,
aspPubKey *secp256k1.PublicKey,
vtxoScript,
aspScript []byte,
) (forfeitTxs []*psbt.Packet, err error) {
aspScript, err := common.P2TRScript(aspPubKey)
if err != nil {
return nil, err
}

connectors, prevouts := getConnectorInputs(connectorTx, int64(connectorAmount))

for i, connectorInput := range connectors {
Expand Down
24 changes: 22 additions & 2 deletions common/fees.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package common

import (
"fmt"

"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcwallet/waddrmgr"
Expand All @@ -24,7 +26,11 @@ var ConnectorTxSize = (&input.TxWeightEstimator{}).
AddP2WKHOutput().
VSize()

func ComputeForfeitMinRelayFee(feeRate chainfee.SatPerKVByte, vtxoScriptTapTree TaprootTree) (uint64, error) {
func ComputeForfeitMinRelayFee(
feeRate chainfee.SatPerKVByte,
vtxoScriptTapTree TaprootTree,
aspScriptClass txscript.ScriptClass,
) (uint64, error) {
txWeightEstimator := &input.TxWeightEstimator{}

biggestVtxoLeafProof, err := BiggestLeafMerkleProof(vtxoScriptTapTree)
Expand All @@ -45,7 +51,21 @@ func ComputeForfeitMinRelayFee(feeRate chainfee.SatPerKVByte, vtxoScriptTapTree
ControlBlock: ctrlBlock,
},
)
txWeightEstimator.AddP2TROutput() // asp output

switch aspScriptClass {
case txscript.PubKeyHashTy:
txWeightEstimator.AddP2PKHOutput()
case txscript.ScriptHashTy:
txWeightEstimator.AddP2SHOutput()
case txscript.WitnessV0PubKeyHashTy:
txWeightEstimator.AddP2WKHOutput()
case txscript.WitnessV0ScriptHashTy:
txWeightEstimator.AddP2WSHOutput()
case txscript.WitnessV1TaprootTy:
txWeightEstimator.AddP2TROutput()
default:
return 0, fmt.Errorf("unknown asp script class: %v", aspScriptClass)
}

return uint64(feeRate.FeeForVSize(lntypes.VByte(txWeightEstimator.VSize())).ToUnit(btcutil.AmountSatoshi)), nil
}
11 changes: 2 additions & 9 deletions common/tree/forfeit.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package tree

import (
"github.com/ark-network/ark/common"
"github.com/btcsuite/btcd/txscript"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/vulpemventures/go-elements/elementsutil"
"github.com/vulpemventures/go-elements/psetv2"
"github.com/vulpemventures/go-elements/transaction"
Expand All @@ -15,8 +13,8 @@ func BuildForfeitTxs(
vtxoAmount,
connectorAmount,
feeAmount uint64,
vtxoScript []byte,
aspPubKey *secp256k1.PublicKey,
vtxoScript,
aspScript []byte,
) (forfeitTxs []*psetv2.Pset, err error) {
connectors, prevouts := getConnectorInputs(connectorTx, connectorAmount)

Expand Down Expand Up @@ -61,11 +59,6 @@ func BuildForfeitTxs(
return nil, err
}

aspScript, err := common.P2TRScript(aspPubKey)
if err != nil {
return nil, err
}

err = updater.AddOutputs([]psetv2.OutputArgs{
{
Asset: asset,
Expand Down
2 changes: 2 additions & 0 deletions pkg/client-sdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func (a *arkClient) InitWithWallet(
UnilateralExitDelay: info.UnilateralExitDelay,
Dust: info.Dust,
BoardingDescriptorTemplate: info.BoardingDescriptorTemplate,
ForfeitAddress: info.ForfeitAddress,
}
if err := a.store.AddData(ctx, storeData); err != nil {
return err
Expand Down Expand Up @@ -181,6 +182,7 @@ func (a *arkClient) Init(
Dust: info.Dust,
BoardingDescriptorTemplate: info.BoardingDescriptorTemplate,
ExplorerURL: args.ExplorerURL,
ForfeitAddress: info.ForfeitAddress,
}
walletSvc, err := getWallet(a.store, &storeData, supportedWallets)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type Info struct {
Network string
Dust uint64
BoardingDescriptorTemplate string
ForfeitAddress string
}

type RoundEventChannel struct {
Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/client/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (a *grpcClient) GetInfo(ctx context.Context) (*client.Info, error) {
Network: resp.GetNetwork(),
Dust: uint64(resp.GetDust()),
BoardingDescriptorTemplate: resp.GetBoardingDescriptorTemplate(),
ForfeitAddress: resp.GetForfeitAddress(),
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/client/rest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func (a *restClient) GetInfo(
Network: resp.Payload.Network,
Dust: uint64(dust),
BoardingDescriptorTemplate: resp.Payload.BoardingDescriptorTemplate,
ForfeitAddress: resp.Payload.ForfeitAddress,
}, nil
}

Expand Down

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

10 changes: 8 additions & 2 deletions pkg/client-sdk/covenant_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/ark-network/ark/pkg/client-sdk/wallet"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -1311,6 +1312,11 @@ func (a *covenantArkClient) createAndSignForfeits(
signedForfeits := make([]string, 0)
connectorsPsets := make([]*psetv2.Pset, 0, len(connectors))

forfeitPkScript, err := address.ToOutputScript(a.ForfeitAddress)
if err != nil {
return nil, err
}

for _, connector := range connectors {
p, err := psetv2.NewPsetFromBase64(connector)
if err != nil {
Expand All @@ -1331,7 +1337,7 @@ func (a *covenantArkClient) createAndSignForfeits(
return nil, err
}

feeAmount, err := common.ComputeForfeitMinRelayFee(feeRate, vtxoTapTree)
feeAmount, err := common.ComputeForfeitMinRelayFee(feeRate, vtxoTapTree, txscript.WitnessV0PubKeyHashTy)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1373,7 +1379,7 @@ func (a *covenantArkClient) createAndSignForfeits(

for _, connectorPset := range connectorsPsets {
forfeits, err := tree.BuildForfeitTxs(
connectorPset, vtxoInput, vtxo.Amount, a.Dust, feeAmount, vtxoOutputScript, a.AspPubkey,
connectorPset, vtxoInput, vtxo.Amount, a.Dust, feeAmount, vtxoOutputScript, forfeitPkScript,
)
if err != nil {
return nil, err
Expand Down
18 changes: 16 additions & 2 deletions pkg/client-sdk/covenantless_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,20 @@ func (a *covenantlessArkClient) createAndSignForfeits(
feeRate chainfee.SatPerKVByte,
myPubkey *secp256k1.PublicKey,
) ([]string, error) {
parsedForfeitAddr, err := btcutil.DecodeAddress(a.ForfeitAddress, nil)
if err != nil {
return nil, err
}

forfeitPkScript, err := txscript.PayToAddrScript(parsedForfeitAddr)
if err != nil {
return nil, err
}

parsedScript, err := txscript.ParsePkScript(forfeitPkScript)
if err != nil {
return nil, err
}

signedForfeits := make([]string, 0)
connectorsPsets := make([]*psbt.Packet, 0, len(connectors))
Expand All @@ -1541,7 +1555,7 @@ func (a *covenantlessArkClient) createAndSignForfeits(
return nil, err
}

feeAmount, err := common.ComputeForfeitMinRelayFee(feeRate, vtxoTapTree)
feeAmount, err := common.ComputeForfeitMinRelayFee(feeRate, vtxoTapTree, parsedScript.Class())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1584,7 +1598,7 @@ func (a *covenantlessArkClient) createAndSignForfeits(

for _, connectorPset := range connectorsPsets {
forfeits, err := bitcointree.BuildForfeitTxs(
connectorPset, vtxoInput, vtxo.Amount, a.Dust, feeAmount, vtxoOutputScript, a.AspPubkey,
connectorPset, vtxoInput, vtxo.Amount, a.Dust, feeAmount, vtxoOutputScript, forfeitPkScript,
)
if err != nil {
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions pkg/client-sdk/store/file/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type storeData struct {
Dust string `json:"dust"`
BoardingDescriptorTemplate string `json:"boarding_descriptor_template"`
ExplorerURL string `json:"explorer_url"`
ForfeitAddress string `json:"forfeit_address"`
}

func (d storeData) isEmpty() bool {
Expand Down Expand Up @@ -59,6 +60,7 @@ func (d storeData) decode() store.StoreData {
Dust: uint64(dust),
BoardingDescriptorTemplate: d.BoardingDescriptorTemplate,
ExplorerURL: explorerURL,
ForfeitAddress: d.ForfeitAddress,
}
}

Expand All @@ -75,6 +77,7 @@ func (d storeData) asMap() map[string]string {
"dust": d.Dust,
"boarding_descriptor_template": d.BoardingDescriptorTemplate,
"explorer_url": d.ExplorerURL,
"forfeit_address": d.ForfeitAddress,
}
}

Expand Down Expand Up @@ -122,6 +125,7 @@ func (s *Store) AddData(ctx context.Context, data store.StoreData) error {
Dust: fmt.Sprintf("%d", data.Dust),
BoardingDescriptorTemplate: data.BoardingDescriptorTemplate,
ExplorerURL: data.ExplorerURL,
ForfeitAddress: data.ForfeitAddress,
}

if err := s.write(sd); err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type StoreData struct {
Dust uint64
BoardingDescriptorTemplate string
ExplorerURL string
ForfeitAddress string
}

type ConfigStore interface {
Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestStore(t *testing.T) {
UnilateralExitDelay: 512,
Dust: 1000,
BoardingDescriptorTemplate: "tr(0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,{ and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(USER)), and(older(604672), pk(USER)) })",
ForfeitAddress: "bcrt1qzvqj",
}

tests := []struct {
Expand Down
1 change: 1 addition & 0 deletions pkg/client-sdk/wallet/wallet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestWallet(t *testing.T) {
UnilateralExitDelay: 512,
Dust: 1000,
BoardingDescriptorTemplate: "tr(0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,{ and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(USER)), and(older(604672), pk(USER)) })",
ForfeitAddress: "bcrt1qzvqj",
}
tests := []struct {
name string
Expand Down
Loading

0 comments on commit 2be78b0

Please sign in to comment.