mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 04:34:19 +01:00
* [proto] add APIs to send and receive musig2 signing data * [common] add serialization functions for nonces and signatures * [application] implements tree signing * fix: remove old debug logs * [proto] cleaning * [common] fix musig2.go * [application] fixes and logs * [interface] fix: stop forwarding 2 times the events * [client] add musig2 support + sign the tree when joining a round * [interface] add new APIs into permissions.go * [application][proto] rework PingResponse (return all events type) * [common] split SetKeys into 2 distinct methods * [client] fixes according to musig2.go changes * [sdk] support tree signing + new PingResponse * [sdk] fixes * [application] revert event channel type * [application] use domain.RoundEvent as lastEvent type * [application] remove IsCovenantLess * comments * [application] revert roundAborted changes * [interface] remove bitcointree dependencie
206 lines
4.0 KiB
Go
206 lines
4.0 KiB
Go
package covenantless
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
|
|
arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1"
|
|
"github.com/ark-network/ark/client/utils"
|
|
"github.com/ark-network/ark/common/bitcointree"
|
|
"github.com/btcsuite/btcd/btcutil"
|
|
"github.com/btcsuite/btcd/btcutil/psbt"
|
|
"github.com/btcsuite/btcd/txscript"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
func (c *clArkBitcoinCLI) Onboard(ctx *cli.Context) error {
|
|
amount := ctx.Uint64("amount")
|
|
|
|
if amount <= 0 {
|
|
return fmt.Errorf("missing amount flag (--amount)")
|
|
}
|
|
|
|
net, err := utils.GetNetwork(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
userPubKey, err := utils.GetWalletPublicKey(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
client, cancel, err := getClientFromState(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer cancel()
|
|
|
|
aspPubkey, err := utils.GetAspPublicKey(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
roundLifetime, err := utils.GetRoundLifetime(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
unilateralExitDelay, err := utils.GetUnilateralExitDelay(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
minRelayFee, err := utils.GetMinRelayFee(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
congestionTreeLeaf := bitcointree.Receiver{
|
|
Pubkey: hex.EncodeToString(userPubKey.SerializeCompressed()),
|
|
Amount: uint64(amount), // Convert amount to uint64
|
|
}
|
|
|
|
leaves := []bitcointree.Receiver{congestionTreeLeaf}
|
|
|
|
ephemeralKey, err := secp256k1.GeneratePrivateKey()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cosigners := []*secp256k1.PublicKey{ephemeralKey.PubKey()} // TODO asp as cosigner
|
|
|
|
sharedOutputScript, sharedOutputAmount, err := bitcointree.CraftSharedOutput(
|
|
cosigners,
|
|
aspPubkey,
|
|
leaves,
|
|
uint64(minRelayFee),
|
|
roundLifetime,
|
|
unilateralExitDelay,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
netParams := toChainParams(net)
|
|
|
|
address, err := btcutil.NewAddressTaproot(sharedOutputScript[2:], &netParams)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
onchainReceiver := receiver{
|
|
To: address.EncodeAddress(),
|
|
Amount: uint64(sharedOutputAmount),
|
|
}
|
|
|
|
partialTx, err := sendOnchain(ctx, []receiver{onchainReceiver})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ptx, err := psbt.NewFromRawBytes(strings.NewReader(partialTx), true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
txid := ptx.UnsignedTx.TxHash().String()
|
|
|
|
congestionTree, err := bitcointree.CraftCongestionTree(
|
|
&wire.OutPoint{
|
|
Hash: ptx.UnsignedTx.TxHash(),
|
|
Index: 0,
|
|
},
|
|
cosigners,
|
|
aspPubkey,
|
|
leaves,
|
|
uint64(minRelayFee),
|
|
roundLifetime,
|
|
unilateralExitDelay,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sweepClosure := bitcointree.CSVSigClosure{
|
|
Pubkey: aspPubkey,
|
|
Seconds: uint(roundLifetime),
|
|
}
|
|
|
|
sweepTapLeaf, err := sweepClosure.Leaf()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sweepTapTree := txscript.AssembleTaprootScriptTree(*sweepTapLeaf)
|
|
root := sweepTapTree.RootNode.TapHash()
|
|
|
|
signer := bitcointree.NewTreeSignerSession(
|
|
ephemeralKey,
|
|
congestionTree,
|
|
minRelayFee,
|
|
root.CloneBytes(),
|
|
)
|
|
|
|
nonces, err := signer.GetNonces() // TODO send nonces to ASP
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
coordinator, err := bitcointree.NewTreeCoordinatorSession(
|
|
congestionTree,
|
|
minRelayFee,
|
|
root.CloneBytes(),
|
|
cosigners,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := coordinator.AddNonce(ephemeralKey.PubKey(), nonces); err != nil {
|
|
return err
|
|
}
|
|
|
|
aggregatedNonces, err := coordinator.AggregateNonces()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := signer.SetKeys(cosigners); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := signer.SetAggregatedNonces(aggregatedNonces); err != nil {
|
|
return err
|
|
}
|
|
|
|
sigs, err := signer.Sign()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := coordinator.AddSig(ephemeralKey.PubKey(), sigs); err != nil {
|
|
return err
|
|
}
|
|
|
|
signedTree, err := coordinator.SignTree()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = client.Onboard(ctx.Context, &arkv1.OnboardRequest{
|
|
BoardingTx: partialTx,
|
|
CongestionTree: castCongestionTree(signedTree),
|
|
UserPubkey: hex.EncodeToString(userPubKey.SerializeCompressed()),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("onboard_txid:", txid)
|
|
|
|
return nil
|
|
}
|