mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 20:54:20 +01:00
Make the round participants sign the vtxo tree (#271)
* [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
This commit is contained in:
@@ -3,6 +3,7 @@ package covenantless
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"github.com/ark-network/ark/common/tree"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcutil/psbt"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"github.com/urfave/cli/v2"
|
||||
"google.golang.org/grpc"
|
||||
@@ -220,12 +222,15 @@ func castCongestionTree(congestionTree tree.CongestionTree) *arkv1.Tree {
|
||||
func handleRoundStream(
|
||||
ctx *cli.Context, client arkv1.ArkServiceClient, paymentID string,
|
||||
vtxosToSign []vtxo, secKey *secp256k1.PrivateKey, receivers []*arkv1.Output,
|
||||
ephemeralKey *secp256k1.PrivateKey,
|
||||
) (poolTxID string, err error) {
|
||||
stream, err := client.GetEventStream(ctx.Context, &arkv1.GetEventStreamRequest{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
myEphemeralPublicKey := hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed())
|
||||
|
||||
var pingStop func()
|
||||
pingReq := &arkv1.PingRequest{
|
||||
PaymentId: paymentID,
|
||||
@@ -236,6 +241,8 @@ func handleRoundStream(
|
||||
|
||||
defer pingStop()
|
||||
|
||||
var treeSignerSession bitcointree.SignerSession
|
||||
|
||||
for {
|
||||
event, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
@@ -250,6 +257,143 @@ func handleRoundStream(
|
||||
return "", fmt.Errorf("round failed: %s", e.GetReason())
|
||||
}
|
||||
|
||||
if e := event.GetRoundSigning(); e != nil {
|
||||
pingStop()
|
||||
fmt.Println("tree created, generating nonces...")
|
||||
|
||||
cosignersPubKeysHex := e.GetCosignersPubkeys()
|
||||
|
||||
cosigners := make([]*secp256k1.PublicKey, 0, len(cosignersPubKeysHex))
|
||||
|
||||
for _, pubkeyHex := range cosignersPubKeysHex {
|
||||
pubkeyBytes, err := hex.DecodeString(pubkeyHex)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pubkey, err := secp256k1.ParsePubKey(pubkeyBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cosigners = append(cosigners, pubkey)
|
||||
}
|
||||
|
||||
congestionTree, err := toCongestionTree(e.GetUnsignedTree())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
minRelayFee, err := utils.GetMinRelayFee(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
aspPubkey, err := utils.GetAspPublicKey(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lifetime, err := utils.GetRoundLifetime(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sweepClosure := bitcointree.CSVSigClosure{
|
||||
Pubkey: aspPubkey,
|
||||
Seconds: uint(lifetime),
|
||||
}
|
||||
|
||||
sweepTapLeaf, err := sweepClosure.Leaf()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sweepTapTree := txscript.AssembleTaprootScriptTree(*sweepTapLeaf)
|
||||
root := sweepTapTree.RootNode.TapHash()
|
||||
|
||||
treeSignerSession = bitcointree.NewTreeSignerSession(
|
||||
ephemeralKey, congestionTree, int64(minRelayFee), root.CloneBytes(),
|
||||
)
|
||||
|
||||
nonces, err := treeSignerSession.GetNonces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := treeSignerSession.SetKeys(cosigners); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var nonceBuffer bytes.Buffer
|
||||
|
||||
if err := nonces.Encode(&nonceBuffer); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
serializedNonces := hex.EncodeToString(nonceBuffer.Bytes())
|
||||
|
||||
if _, err := client.SendTreeNonces(ctx.Context, &arkv1.SendTreeNoncesRequest{
|
||||
RoundId: e.GetId(),
|
||||
PublicKey: myEphemeralPublicKey,
|
||||
TreeNonces: serializedNonces,
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fmt.Println("nonces sent")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if e := event.GetRoundSigningNoncesGenerated(); e != nil {
|
||||
pingStop()
|
||||
fmt.Println("nonces generated, signing the tree...")
|
||||
|
||||
if treeSignerSession == nil {
|
||||
return "", fmt.Errorf("tree signer session not set")
|
||||
}
|
||||
|
||||
combinedNoncesBytes, err := hex.DecodeString(e.GetTreeNonces())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
combinedNonces, err := bitcointree.DecodeNonces(bytes.NewReader(combinedNoncesBytes))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := treeSignerSession.SetAggregatedNonces(combinedNonces); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sigs, err := treeSignerSession.Sign()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var sigBuffer bytes.Buffer
|
||||
|
||||
if err := sigs.Encode(&sigBuffer); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
serializedSigs := hex.EncodeToString(sigBuffer.Bytes())
|
||||
|
||||
if _, err := client.SendTreeSignatures(ctx.Context, &arkv1.SendTreeSignaturesRequest{
|
||||
RoundId: e.GetId(),
|
||||
TreeSignatures: serializedSigs,
|
||||
PublicKey: myEphemeralPublicKey,
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fmt.Println("tree signed")
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if e := event.GetRoundFinalization(); e != nil {
|
||||
// stop pinging as soon as we receive some forfeit txs
|
||||
pingStop()
|
||||
|
||||
Reference in New Issue
Block a user