diff --git a/.gitignore b/.gitignore index c6e0414c2..65ab0e32a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,9 @@ .vscode/ *.wasm -wasm_exec.js \ No newline at end of file +wasm_exec.js + +.idea + +build +log \ No newline at end of file diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index 4f73cf88e..590dfeb1b 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -2,6 +2,7 @@ package bitcointree import ( "bytes" + "encoding/binary" "errors" "fmt" "io" @@ -21,9 +22,6 @@ import ( var ( ErrCongestionTreeNotSet = errors.New("congestion tree not set") ErrAggregateKeyNotSet = errors.New("aggregate key not set") - - columnSeparator = byte('|') - rowSeparator = byte('/') ) type Musig2Nonce struct { @@ -37,12 +35,15 @@ func (n *Musig2Nonce) Encode(w io.Writer) error { func (n *Musig2Nonce) Decode(r io.Reader) error { bytes := make([]byte, 66) - _, err := r.Read(bytes) + bytesRead, err := io.ReadFull(r, bytes) if err != nil { return err } + if bytesRead != 66 { + return fmt.Errorf("expected to read 66 bytes, but read %d", bytesRead) + } - n.PubNonce = [66]byte(bytes) + copy(n.PubNonce[:], bytes) return nil } @@ -585,20 +586,23 @@ type readable interface { func encodeMatrix[T writable](matrix [][]T) ([]byte, error) { var buf bytes.Buffer + // Write number of rows + if err := binary.Write(&buf, binary.LittleEndian, uint32(len(matrix))); err != nil { + return nil, err + } + + // For each row, write its length and then its elements for _, row := range matrix { + // Write row length + if err := binary.Write(&buf, binary.LittleEndian, uint32(len(row))); err != nil { + return nil, err + } + // Write row data for _, cell := range row { - if err := buf.WriteByte(columnSeparator); err != nil { - return nil, err - } - if err := cell.Encode(&buf); err != nil { return nil, err } } - - if err := buf.WriteByte(rowSeparator); err != nil { - return nil, err - } } return buf.Bytes(), nil @@ -606,36 +610,37 @@ func encodeMatrix[T writable](matrix [][]T) ([]byte, error) { // decodeMatrix decode a byte stream into a matrix of serializable objects func decodeMatrix[T readable](factory func() T, data io.Reader) ([][]T, error) { - matrix := make([][]T, 0) - row := make([]T, 0) - - for { - separator := make([]byte, 1) + var rowCount uint32 - if _, err := data.Read(separator); err != nil { - if err == io.EOF { - break - } - return nil, err - } + // Read number of rows + if err := binary.Read(data, binary.LittleEndian, &rowCount); err != nil { + return nil, err + } - b := separator[0] + // Initialize matrix + matrix := make([][]T, rowCount) - if b == rowSeparator { - matrix = append(matrix, row) - row = make([]T, 0) - continue + // For each row, read its length and then its elements + for i := uint32(0); i < rowCount; i++ { + var colCount uint32 + // Read row length + if err := binary.Read(data, binary.LittleEndian, &colCount); err != nil { + return nil, err } - cell := factory() + // Initialize row + row := make([]T, colCount) - if err := cell.Decode(data); err != nil { - if err == io.EOF { - break + // Read row data + for j := uint32(0); j < colCount; j++ { + cell := factory() + if err := cell.Decode(data); err != nil { + return nil, err } - return nil, err + row[j] = cell } - row = append(row, cell) + + matrix[i] = row } return matrix, nil diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index b391f4975..1b795b955 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -1,14 +1,14 @@ package bitcointree_test import ( - "bytes" + "encoding/hex" "encoding/json" - "fmt" + "github.com/ark-network/ark/common/tree" "os" "testing" "github.com/ark-network/ark/common/bitcointree" - "github.com/ark-network/ark/common/tree" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -27,22 +27,21 @@ var testTxid, _ = chainhash.NewHashFromStr("49f8664acc899be91902f8ade781b7eeb9cb func TestRoundTripSignTree(t *testing.T) { fixtures := parseFixtures(t) for _, f := range fixtures.Valid { - alice, err := secp256k1.GeneratePrivateKey() - require.NoError(t, err) - - bob, err := secp256k1.GeneratePrivateKey() - require.NoError(t, err) + // Generate 20 cosigners + cosigners := make([]*secp256k1.PrivateKey, 20) + cosignerPubKeys := make([]*btcec.PublicKey, 20) + for i := 0; i < 20; i++ { + privKey, err := secp256k1.GeneratePrivateKey() + require.NoError(t, err) + cosigners[i] = privKey + cosignerPubKeys[i] = privKey.PubKey() + } asp, err := secp256k1.GeneratePrivateKey() require.NoError(t, err) - cosigners := make([]*secp256k1.PublicKey, 0) - cosigners = append(cosigners, alice.PubKey()) - cosigners = append(cosigners, bob.PubKey()) - cosigners = append(cosigners, asp.PubKey()) - _, sharedOutputAmount, err := bitcointree.CraftSharedOutput( - cosigners, + cosignerPubKeys, asp.PubKey(), castReceivers(f.Receivers), minRelayFee, @@ -50,13 +49,12 @@ func TestRoundTripSignTree(t *testing.T) { ) require.NoError(t, err) - // Create a new tree tree, err := bitcointree.CraftCongestionTree( &wire.OutPoint{ Hash: *testTxid, Index: 0, }, - cosigners, + cosignerPubKeys, asp.PubKey(), castReceivers(f.Receivers), minRelayFee, @@ -79,132 +77,48 @@ func TestRoundTripSignTree(t *testing.T) { sharedOutputAmount, tree, root.CloneBytes(), - []*secp256k1.PublicKey{alice.PubKey(), bob.PubKey(), asp.PubKey()}, + cosignerPubKeys, ) require.NoError(t, err) - aliceSession := bitcointree.NewTreeSignerSession(alice, sharedOutputAmount, tree, root.CloneBytes()) - bobSession := bitcointree.NewTreeSignerSession(bob, sharedOutputAmount, tree, root.CloneBytes()) - aspSession := bitcointree.NewTreeSignerSession(asp, sharedOutputAmount, tree, root.CloneBytes()) - - aliceNonces, err := aliceSession.GetNonces() - require.NoError(t, err) - - bobNonces, err := bobSession.GetNonces() - require.NoError(t, err) - - aspNonces, err := aspSession.GetNonces() - require.NoError(t, err) - - s := bytes.NewBuffer(nil) - - err = aspNonces[0][0].Encode(s) - require.NoError(t, err) - - bitcointreeNonce := new(bitcointree.Musig2Nonce) - err = bitcointreeNonce.Decode(s) - require.NoError(t, err) - - require.Equal(t, aspNonces[0][0], bitcointreeNonce) - - var serializedNonces bytes.Buffer - - err = aspNonces.Encode(&serializedNonces) - require.NoError(t, err) - - decodedNonces, err := bitcointree.DecodeNonces(&serializedNonces) - require.NoError(t, err) - - for i, nonces := range aspNonces { - for j, nonce := range nonces { - require.Equal(t, nonce.PubNonce, decodedNonces[i][j].PubNonce, fmt.Sprintf("matrix nonce not equal at index i: %d, j: %d", i, j)) - } + // Create signer sessions for all cosigners + signerSessions := make([]bitcointree.SignerSession, 20) + for i, cosigner := range cosigners { + signerSessions[i] = bitcointree.NewTreeSignerSession(cosigner, sharedOutputAmount, tree, root.CloneBytes()) } - err = aspCoordinator.AddNonce(alice.PubKey(), aliceNonces) - require.NoError(t, err) - - err = aspCoordinator.AddNonce(bob.PubKey(), bobNonces) - require.NoError(t, err) - - err = aspCoordinator.AddNonce(asp.PubKey(), aspNonces) - require.NoError(t, err) + // Get nonces from all signers + for i, session := range signerSessions { + nonces, err := session.GetNonces() + require.NoError(t, err) + err = aspCoordinator.AddNonce(cosignerPubKeys[i], nonces) + require.NoError(t, err) + } aggregatedNonce, err := aspCoordinator.AggregateNonces() require.NoError(t, err) - // coordinator sends the combined nonce to all signers - - err = aliceSession.SetKeys( - cosigners, - ) - require.NoError(t, err) - - err = aliceSession.SetAggregatedNonces( - aggregatedNonce, - ) - require.NoError(t, err) - - err = bobSession.SetKeys( - cosigners, - ) - require.NoError(t, err) - - err = bobSession.SetAggregatedNonces( - aggregatedNonce, - ) - require.NoError(t, err) - - err = aspSession.SetKeys( - cosigners, - ) - require.NoError(t, err) - - err = aspSession.SetAggregatedNonces( - aggregatedNonce, - ) - require.NoError(t, err) - - aliceSig, err := aliceSession.Sign() - require.NoError(t, err) - - bobSig, err := bobSession.Sign() - require.NoError(t, err) - - aspSig, err := aspSession.Sign() - require.NoError(t, err) - - // check that the sigs are serializable - - serializedSigs := bytes.NewBuffer(nil) - - err = aspSig.Encode(serializedSigs) - require.NoError(t, err) - - decodedSigs, err := bitcointree.DecodeSignatures(serializedSigs) - require.NoError(t, err) - - for i, sigs := range aspSig { - for j, sig := range sigs { - require.Equal(t, sig.S, decodedSigs[i][j].S, fmt.Sprintf("matrix sig not equal at index i: %d, j: %d", i, j)) - } + // Set keys and aggregated nonces for all signers + for _, session := range signerSessions { + err = session.SetKeys(cosignerPubKeys) + require.NoError(t, err) + err = session.SetAggregatedNonces(aggregatedNonce) + require.NoError(t, err) } - // coordinator receives the signatures and combines them - err = aspCoordinator.AddSig(alice.PubKey(), aliceSig) - require.NoError(t, err) - - err = aspCoordinator.AddSig(bob.PubKey(), bobSig) - require.NoError(t, err) - - err = aspCoordinator.AddSig(asp.PubKey(), aspSig) - require.NoError(t, err) + // Get signatures from all signers + for i, session := range signerSessions { + sig, err := session.Sign() + require.NoError(t, err) + err = aspCoordinator.AddSig(cosignerPubKeys[i], sig) + require.NoError(t, err) + } signedTree, err := aspCoordinator.SignTree() require.NoError(t, err) // verify the tree - aggregatedKey, err := bitcointree.AggregateKeys(cosigners, root.CloneBytes()) + aggregatedKey, err := bitcointree.AggregateKeys(cosignerPubKeys, root.CloneBytes()) require.NoError(t, err) err = bitcointree.ValidateTreeSigs( @@ -222,6 +136,24 @@ type receiverFixture struct { Pubkey string `json:"pubkey"` } +func (r receiverFixture) toVtxoScript(asp *secp256k1.PublicKey) bitcointree.VtxoScript { + bytesKey, err := hex.DecodeString(r.Pubkey) + if err != nil { + panic(err) + } + + pubkey, err := secp256k1.ParsePubKey(bytesKey) + if err != nil { + panic(err) + } + + return &bitcointree.DefaultVtxoScript{ + Owner: pubkey, + Asp: asp, + ExitDelay: exitDelay, + } +} + func castReceivers(receivers []receiverFixture) []tree.VtxoLeaf { receiversOut := make([]tree.VtxoLeaf, 0, len(receivers)) for _, r := range receivers { diff --git a/common/bitcointree/testdata/musig2.json b/common/bitcointree/testdata/musig2.json index 08efeed6d..3267e124e 100644 --- a/common/bitcointree/testdata/musig2.json +++ b/common/bitcointree/testdata/musig2.json @@ -3,48 +3,83 @@ "valid": [ { "receivers": [ - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - } + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} ] }, { "receivers": [ - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - }, - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 8000 - } + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} ] }, { "receivers": [ - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - }, - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - }, - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - }, - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1000 - }, - { - "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", - "amount": 1100 - } + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} + ] + }, + { + "receivers": [ + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} + ] + }, + { + "receivers": [ + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 6000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} + ] + }, + { + "receivers": [ + {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 6000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 7000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 8000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 9000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 10000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 11000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 12000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 13000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 14000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 15000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 16000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 17000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 18000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 19000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 20000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 21000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 22000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 23000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 24000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 25000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 26000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 27000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 28000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 29000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 30000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 31000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 32000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 33000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 34000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, + {"amount": 35000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} ] } - ] + ] + } } -} \ No newline at end of file diff --git a/common/go.mod b/common/go.mod index 308f4d83e..cee69ee87 100644 --- a/common/go.mod +++ b/common/go.mod @@ -11,6 +11,7 @@ require ( github.com/btcsuite/btcwallet v0.16.10-0.20240718224643-db3a4a2543bd github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/lightningnetwork/lnd v0.18.2-beta + github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 ) diff --git a/docker-compose.clark.regtest.yml b/docker-compose.clark.regtest.yml index 384dd4917..7fe05e945 100644 --- a/docker-compose.clark.regtest.yml +++ b/docker-compose.clark.regtest.yml @@ -6,7 +6,7 @@ services: dockerfile: Dockerfile restart: unless-stopped environment: - - ARK_ROUND_INTERVAL=10 + - ARK_ROUND_INTERVAL=${ARK_ROUND_INTERVAL:-10} - ARK_NETWORK=regtest - ARK_LOG_LEVEL=5 - ARK_ROUND_LIFETIME=20 @@ -26,4 +26,4 @@ services: networks: default: name: nigiri - external: true + external: true \ No newline at end of file diff --git a/docker-compose.regtest.yml b/docker-compose.regtest.yml index 834da4341..5762f644b 100644 --- a/docker-compose.regtest.yml +++ b/docker-compose.regtest.yml @@ -31,15 +31,15 @@ services: - ARK_ROUND_INTERVAL=10 - ARK_NETWORK=liquidregtest - ARK_LOG_LEVEL=5 - - ARK_ESPLORA_URL=http://chopsticks-liquid:3000 - - ARK_ROUND_LIFETIME=20 - - ARK_SCHEDULER_TYPE=block + - ARK_ROUND_LIFETIME=10 - ARK_DB_TYPE=sqlite - ARK_TX_BUILDER_TYPE=covenant - ARK_PORT=6060 - ARK_NO_TLS=true - ARK_NO_MACAROONS=true - ARK_DATADIR=/app/data + - ARK_ESPLORA_URL=http://chopsticks-liquid:3000 + - ARK_SCHEDULER_TYPE=block ports: - "6060:6060" volumes: diff --git a/go.work b/go.work index 4025b5804..134934248 100644 --- a/go.work +++ b/go.work @@ -8,6 +8,7 @@ use ( ./server ./server/pkg/kvdb ./server/pkg/macaroons + ./simulation ) replace github.com/btcsuite/btcd/btcec/v2 => github.com/btcsuite/btcd/btcec/v2 v2.3.3 diff --git a/go.work.sum b/go.work.sum index c0d80e571..84634fb61 100644 --- a/go.work.sum +++ b/go.work.sum @@ -366,7 +366,6 @@ cloud.google.com/go/websecurityscanner v1.6.11/go.mod h1:vhAZjksELSg58EZfUQ1BMEx cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= cloud.google.com/go/workflows v1.12.10 h1:EGJeZmwgE71jxFOI5s9iKST2Bivif3DSzlqVbiXACXQ= cloud.google.com/go/workflows v1.12.10/go.mod h1:RcKqCiOmKs8wFUEf3EwWZPH5eHc7Oq0kamIyOUCk0IE= -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -394,9 +393,7 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/ClickHouse/clickhouse-go v1.4.3 h1:iAFMa2UrQdR5bHJ2/yaSLffZkxpcOYQMCUuKeNXGdqc= github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= -github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= -github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -404,13 +401,10 @@ github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQ github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82 h1:MG93+PZYs9PyEsj/n5/haQu2gK0h4tUtSy9ejtMwWa0= github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4q90ylaVAbnYyx0JYqK4YcGok= github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= @@ -435,14 +429,10 @@ github.com/ark-network/ark/server/pkg/kvdb v0.0.0-20240812230256-910716f72d1a/go github.com/ark-network/ark/server/pkg/macaroons v0.0.0-20240812230256-910716f72d1a/go.mod h1:OtZoQaSumPsVKWq/OkduHZdpAutQYaB2yVf1rlm6vI4= github.com/ark-network/ark/server/pkg/macaroons v0.0.0-20240812233307-18e343b31899/go.mod h1:OtZoQaSumPsVKWq/OkduHZdpAutQYaB2yVf1rlm6vI4= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA= github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 h1:tcFliCWne+zOuUfKNRn8JdFBuWPDuISDH08wD2ULkhk= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8/go.mod h1:JTnlBSot91steJeti4ryyu/tLd4Sk84O5W22L7O2EQU= @@ -466,7 +456,6 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17 h1:HfVVR1vItaG6l github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.17/go.mod h1:YqMdV+gEKCQ59NrB7rzrJdALeBIsYiVi8Inj3+KcqHI= github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11 h1:3/gm/JTX9bX8CpzTgIlrtYpB3EVBDxyg/GY/QdcIEZw= github.com/aws/aws-sdk-go-v2/service/s3 v1.27.11/go.mod h1:fmgDANqTUCxciViKl9hb/zD5LFbvPINFRgWhDbR+vZo= -github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -484,36 +473,24 @@ github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240625142744-cc26860b4026/go.mod h github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.2.2/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= -github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34= github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/btcutil/psbt v1.1.9/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcwallet v0.16.10-0.20240706055350-e391a1c31df2/go.mod h1:SLFUSQbP8ON/wxholYMfVLvGPJyk7boczOW/ob+nww4= github.com/btcsuite/btcwallet/wallet/txauthor v1.2.3/go.mod h1:T2xSiKGpUkSLCh68aF+FMXmKK9mFqNdHl9VaqOr+JjU= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g= github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc= github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4= -github.com/btcsuite/btcwallet/wtxmgr v1.5.3 h1:QrWCio9Leh3DwkWfp+A1SURj8pYn3JuTLv3waP5uEro= github.com/btcsuite/btcwallet/wtxmgr v1.5.3/go.mod h1:M4nQpxGTXiDlSOODKXboXX7NFthmiBNjzAKKNS7Fhjg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= @@ -532,18 +509,13 @@ github.com/cockroachdb/cockroach-go/v2 v2.1.1 h1:3XzfSMuUT0wBe1a3o5C0eOTcArhmmFA github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -553,28 +525,14 @@ github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369 h1:XNT/Zf5l++1Pyg08 github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= -github.com/decred/dcrd/lru v1.1.3 h1:w9EAbvGLyzm6jTjF83UKuqZEiUtJmvRhQDOCEIvSuE0= -github.com/decred/dcrd/lru v1.1.3/go.mod h1:Tw0i0pJyiLEx/oZdHLe1Wdv/Y7EGzAX+sYftnmxBR4o= -github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg= -github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8= @@ -590,47 +548,22 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fergusstrange/embedded-postgres v1.28.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsouza/fake-gcs-server v1.17.0 h1:OeH75kBZcZa3ZE+zz/mFdJ2btt9FgqfjI7gIh9+5fvk= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q= github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= -github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= @@ -645,32 +578,13 @@ github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v23.5.9+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= @@ -678,13 +592,11 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= @@ -708,7 +620,6 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= @@ -716,15 +627,12 @@ github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+ github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -732,11 +640,8 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= @@ -744,18 +649,13 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -763,35 +663,29 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.14.3 h1:h6W9cPuHsRWQFTWUZMAKMgG5jSwQI0Zurzdvlx3Plus= github.com/jackc/pgtype v1.14.3/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= -github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -799,14 +693,10 @@ github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsN github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedib0t/go-pretty/v6 v6.2.7 h1:4823Lult/tJ0VI1PgW3aSKw59pMWQ6Kzv9b3Bj6MwY0= github.com/jedib0t/go-pretty/v6 v6.2.7/go.mod h1:FMkOpgGD3EZ91cW8g/96RfxoV7bdeJyzXPYgz1L1ln0= -github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= github.com/juju/mgotest v1.0.1 h1:XvuZ2whmkHZ5G+Y/wQaSe28p2FyTwcBaqTzStn+QaLc= @@ -826,16 +716,9 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= -github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -850,48 +733,33 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= github.com/lightninglabs/neutrino v0.16.0/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= -github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s= github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= github.com/lightninglabs/neutrino/cache v1.1.0/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY= github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= -github.com/lightningnetwork/lnd v0.18.2-beta h1:Qv4xQ2ka05vqzmdkFdISHCHP6CzHoYNVKfD18XPjHsM= -github.com/lightningnetwork/lnd v0.18.2-beta/go.mod h1:cGQR1cVEZFZQcCx2VBbDY8xwGjCz+SupSopU1HpjP2I= github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI= github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U= github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= github.com/lightningnetwork/lnd/fn v1.0.4/go.mod h1:K9gbvdl5z4XmRcqWUVqvvVcuRKtmq9BNQ+cWYlk+vjw= github.com/lightningnetwork/lnd/fn v1.1.0/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= -github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY= github.com/lightningnetwork/lnd/kvdb v1.4.10/go.mod h1:J2diNABOoII9UrMnxXS5w7vZwP7CA1CStrl8MnIrb3A= github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= -github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= -github.com/lightningnetwork/lnd/sqldb v1.0.3 h1:zLfAwOvM+6+3+hahYO9Q3h8pVV0TghAR7iJ5YMLCd3I= github.com/lightningnetwork/lnd/sqldb v1.0.3/go.mod h1:4cQOkdymlZ1znnjuRNvMoatQGJkRneTj2CoPSPaQhWo= github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= github.com/lightningnetwork/lnd/tlv v1.0.2/go.mod h1:fICAfsqk1IOsC1J7G9IdsWX1EqWRMqEDCNxZJSKr9C4= github.com/lightningnetwork/lnd/tor v1.1.2/go.mod h1:j7T9uJ2NLMaHwE7GiBGnpYLn4f7NRoTM6qj+ul6/ycA= -github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI= github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g= github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 h1:HVArUNQGqGaSSoyYkk9qGht74U0/uNhS0n7jV9rkmno= github.com/ltcsuite/ltcd/btcec/v2 v2.3.2/go.mod h1:T1t5TjbjPnryvlGQ+RpSKGuU8KhjNN7rS5+IznPj1VM= -github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 h1:xuWxvRKxLvOKuS7/Q/7I3tpc3cWAB0+hZpU8YdVqkzg= github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2/go.mod h1:nkLkAFGhursWf2U68gt61hPieK1I+0m78e+2aevNyD8= github.com/ltcsuite/ltcd/ltcutil v1.1.3 h1:8AapjCPLIt/wtYe6Odfk1EC2y9mcbpgjyxyCoNjAkFI= github.com/ltcsuite/ltcd/ltcutil v1.1.3/go.mod h1:z8txd/ohBFrOMBUT70K8iZvHJD/Vc3gzx+6BP6cBxQw= github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/pkger v0.15.1 h1:3MPelV53RnGSW07izx5xGxl4e/sdRD6zqseIk0rMASY= github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -901,7 +769,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -916,15 +783,9 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= @@ -945,34 +806,20 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba h1:fhFP5RliM2HW/8XdcO5QngSfFli9GcRIpMXvypTQt6E= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNGuyA= github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pierrec/lz4/v4 v4.1.16 h1:kQPfno+wyx6C5572ABwV+Uo3pDFzQ7yhyGchSyRda0c= github.com/pierrec/lz4/v4 v4.1.16/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -980,18 +827,14 @@ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFu github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -1006,14 +849,12 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/crypt v0.19.0 h1:WMyLTjHBo64UvNcWqpzY3pbZTYgnemZU8FBZigKc42E= github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78= github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1027,43 +868,24 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/snowflakedb/gosnowflake v1.6.19 h1:KSHXrQ5o7uso25hNIzi/RObXtnSGkFgie91X82KcvMY= github.com/snowflakedb/gosnowflake v1.6.19/go.mod h1:FM1+PWUdwB9udFDsXdfD58NONC0m+MlOSmQRvimobSM= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/timshannon/badgerhold/v4 v4.0.3 h1:W6pd2qckoXw2cl8eH0ZCV/9CXNaXvaM26tzFi5Tj+v8= -github.com/timshannon/badgerhold/v4 v4.0.3/go.mod h1:IkZIr0kcZLMdD7YJfW/G6epb6ZXHD/h0XR2BTk/VZg8= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= @@ -1071,14 +893,8 @@ github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI= -github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8= -github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7 h1:X7DtNv+YWy76kELMZB/xVkIJ7YNp2vpgMFVsDcQA40U= github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7/go.mod h1:Zrvx8XgpWvSPdz1lXnuN083CkoZnzwxBLEB03S8et1I= -github.com/vulpemventures/go-bip39 v1.0.2 h1:+BgKOVo04okKf1wA4Fhv8ccvql+qFyzVUdVJKkb48r0= github.com/vulpemventures/go-bip39 v1.0.2/go.mod h1:mjFmuv9D6BtANI6iscMmbHhmBOwjMCFfny3mxHnuDrk= -github.com/vulpemventures/go-elements v0.5.4 h1:l94xoa9aYPPWiOB7Pmi08rKYvdk/n/sQIbLkQfEAASc= -github.com/vulpemventures/go-elements v0.5.4/go.mod h1:Tvhb+rZWv3lxoI5CdK03J3V+e2QVr/7UAnCYILxFSq4= github.com/xanzy/go-gitlab v0.15.0 h1:rWtwKTgEnXyNUGrOArN7yyc3THRkpYcKXIXia9abywQ= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -1090,23 +906,18 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0 h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ= @@ -1121,11 +932,6 @@ go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= @@ -1151,7 +957,6 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1165,7 +970,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1173,7 +977,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= @@ -1190,8 +993,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -1199,13 +1000,7 @@ golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= @@ -1220,31 +1015,20 @@ golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1258,17 +1042,11 @@ golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= @@ -1281,8 +1059,6 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= @@ -1300,7 +1076,6 @@ google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAm google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= @@ -1328,8 +1103,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= @@ -1339,14 +1112,10 @@ google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJai google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -1355,7 +1124,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCM gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/juju/environschema.v1 v1.0.0 h1:51vT1bzbP9fntQ0I9ECSlku2p19Szj/N2beZFeIH2kM= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= @@ -1364,7 +1132,6 @@ gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= @@ -1380,7 +1147,6 @@ modernc.org/db v1.0.0 h1:2c6NdCfaLnshSvY7OU09cyAY0gYXUZj4lmg5ItHyucg= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= modernc.org/file v1.0.0 h1:9/PdvjVxd5+LcWUQIfapAWRGOkDLK90rloa8s/au06A= modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw= -modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= @@ -1388,19 +1154,15 @@ modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/internal v1.0.0 h1:XMDsFDcBDsibbBnHB2xzljZ+B1yrOVLEFkKL2u15Glw= modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM= -modernc.org/libc v1.59.3 h1:A4QAp1lRSn2/b4aU+wBtq+yeKgq/2BUevrj0p1ZNy2M= modernc.org/libc v1.59.3/go.mod h1:EY/egGEU7Ju66eU6SBqCNYaFUDuc4npICkMWnU5EE3A= modernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= -modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0 h1:bIQ/trWNVjQPlinI6jdOQsi195SIturGo3mp5hsDqVU= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/pkg/client-sdk/covenantless_client.go b/pkg/client-sdk/covenantless_client.go index 447f9c00f..5b1590de3 100644 --- a/pkg/client-sdk/covenantless_client.go +++ b/pkg/client-sdk/covenantless_client.go @@ -1646,10 +1646,13 @@ func (a *covenantlessArkClient) handleRoundSigningNoncesGenerated( return err } + pk := hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed()) + sigTimeStart := time.Now() sigs, err := signerSession.Sign() if err != nil { return err } + log.Infof("for key %v signing took %v", pk, time.Since(sigTimeStart)) if err := a.arkClient.client.SubmitTreeSignatures( ctx, diff --git a/pkg/client-sdk/internal/utils/utils.go b/pkg/client-sdk/internal/utils/utils.go index 256ca867d..e7802e9e3 100644 --- a/pkg/client-sdk/internal/utils/utils.go +++ b/pkg/client-sdk/internal/utils/utils.go @@ -20,7 +20,7 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/vulpemventures/go-elements/address" "github.com/vulpemventures/go-elements/network" - "golang.org/x/crypto/scrypt" + "golang.org/x/crypto/pbkdf2" ) func CoinSelect( @@ -275,12 +275,8 @@ func deriveKey(password, salt []byte) ([]byte, []byte, error) { return nil, nil, err } } - // 2^20 = 1048576 recommended length for key-stretching - // check the doc for other recommended values: - // https://godoc.org/golang.org/x/crypto/scrypt - key, err := scrypt.Key(password, salt, 1048576, 8, 1, 32) - if err != nil { - return nil, nil, err - } + iterations := 10000 + keySize := 32 + key := pbkdf2.Key(password, salt, iterations, keySize, sha256.New) return key, salt, nil } diff --git a/server/cmd/arkd/main.go b/server/cmd/arkd/main.go index f66bf22a1..982ad3048 100755 --- a/server/cmd/arkd/main.go +++ b/server/cmd/arkd/main.go @@ -88,6 +88,8 @@ func mainAction(_ *cli.Context) error { return err } + log.Infof("ASP config: %+v", appConfig) + log.Info("starting service...") if err := svc.Start(); err != nil { return err diff --git a/server/internal/core/application/utils.go b/server/internal/core/application/utils.go index bd026dc76..ccb496e8c 100644 --- a/server/internal/core/application/utils.go +++ b/server/internal/core/application/utils.go @@ -146,14 +146,14 @@ func (m *paymentsMap) pop(num int64) ([]domain.Payment, []ports.BoardingInput, m cosigners = append(cosigners, pubkey) delete(m.ephemeralKeys, p.Payment.Id) } - for _, input := range payments { - for _, vtxo := range input.Inputs { - descriptors[vtxo.VtxoKey] = m.descriptors[vtxo.VtxoKey] - delete(m.descriptors, vtxo.VtxoKey) - } + for _, vtxo := range p.Payment.Inputs { + descriptors[vtxo.VtxoKey] = m.descriptors[vtxo.VtxoKey] + delete(m.descriptors, vtxo.VtxoKey) + } delete(m.payments, p.Id) } + return payments, boardingInputs, descriptors, cosigners } diff --git a/server/test/e2e/covenant/e2e_test.go b/server/test/e2e/covenant/e2e_test.go index 651ef243a..535ecc03a 100644 --- a/server/test/e2e/covenant/e2e_test.go +++ b/server/test/e2e/covenant/e2e_test.go @@ -54,7 +54,7 @@ func TestMain(m *testing.M) { code := m.Run() - _, err = utils.RunCommand("docker", "compose", "-f", composePath, "down") + _, err = utils.RunCommand("docker", "compose", "-f", composePath, "down", "-v") if err != nil { fmt.Printf("error stopping docker-compose: %s", err) os.Exit(1) diff --git a/server/test/e2e/covenantless/e2e_test.go b/server/test/e2e/covenantless/e2e_test.go index 685c3761e..d0f11deb1 100644 --- a/server/test/e2e/covenantless/e2e_test.go +++ b/server/test/e2e/covenantless/e2e_test.go @@ -1,11 +1,9 @@ package e2e_test import ( - "bytes" "context" "encoding/json" "fmt" - "net/http" "os" "testing" "time" @@ -25,6 +23,7 @@ import ( const ( composePath = "../../../../docker-compose.clark.regtest.yml" redeemAddress = "bcrt1q2wrgf2hrkfegt0t97cnv4g5yvfjua9k6vua54d" + aspUrl = "http://localhost:7070" ) func TestMain(m *testing.M) { @@ -41,7 +40,7 @@ func TestMain(m *testing.M) { os.Exit(1) } - if err := setupAspWallet(); err != nil { + if err := utils.SetupServerWalletCovenantless(aspUrl, 0.0); err != nil { fmt.Println(err) os.Exit(1) } @@ -413,113 +412,6 @@ func runClarkCommand(arg ...string) (string, error) { return utils.RunCommand("docker", args...) } -func setupAspWallet() error { - adminHttpClient := &http.Client{ - Timeout: 15 * time.Second, - } - - req, err := http.NewRequest("GET", "http://localhost:7070/v1/admin/wallet/seed", nil) - if err != nil { - return fmt.Errorf("failed to prepare generate seed request: %s", err) - } - req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") - - seedResp, err := adminHttpClient.Do(req) - if err != nil { - return fmt.Errorf("failed to generate seed: %s", err) - } - - var seed struct { - Seed string `json:"seed"` - } - - if err := json.NewDecoder(seedResp.Body).Decode(&seed); err != nil { - return fmt.Errorf("failed to parse response: %s", err) - } - - reqBody := bytes.NewReader([]byte(fmt.Sprintf(`{"seed": "%s", "password": "%s"}`, seed.Seed, utils.Password))) - req, err = http.NewRequest("POST", "http://localhost:7070/v1/admin/wallet/create", reqBody) - if err != nil { - return fmt.Errorf("failed to prepare wallet create request: %s", err) - } - req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") - req.Header.Set("Content-Type", "application/json") - - if _, err := adminHttpClient.Do(req); err != nil { - return fmt.Errorf("failed to create wallet: %s", err) - } - - reqBody = bytes.NewReader([]byte(fmt.Sprintf(`{"password": "%s"}`, utils.Password))) - req, err = http.NewRequest("POST", "http://localhost:7070/v1/admin/wallet/unlock", reqBody) - if err != nil { - return fmt.Errorf("failed to prepare wallet unlock request: %s", err) - } - req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") - req.Header.Set("Content-Type", "application/json") - - if _, err := adminHttpClient.Do(req); err != nil { - return fmt.Errorf("failed to unlock wallet: %s", err) - } - - var status struct { - Initialized bool `json:"initialized"` - Unlocked bool `json:"unlocked"` - Synced bool `json:"synced"` - } - for { - time.Sleep(time.Second) - - req, err := http.NewRequest("GET", "http://localhost:7070/v1/admin/wallet/status", nil) - if err != nil { - return fmt.Errorf("failed to prepare status request: %s", err) - } - resp, err := adminHttpClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get status: %s", err) - } - if err := json.NewDecoder(resp.Body).Decode(&status); err != nil { - return fmt.Errorf("failed to parse status response: %s", err) - } - if status.Initialized && status.Unlocked && status.Synced { - break - } - } - - var addr struct { - Address string `json:"address"` - } - for addr.Address == "" { - time.Sleep(time.Second) - - req, err = http.NewRequest("GET", "http://localhost:7070/v1/admin/wallet/address", nil) - if err != nil { - return fmt.Errorf("failed to prepare new address request: %s", err) - } - req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") - - resp, err := adminHttpClient.Do(req) - if err != nil { - return fmt.Errorf("failed to get new address: %s", err) - } - - if err := json.NewDecoder(resp.Body).Decode(&addr); err != nil { - return fmt.Errorf("failed to parse response: %s", err) - } - } - - const numberOfFaucet = 15 // must cover the liquidity needed for all tests - - for i := 0; i < numberOfFaucet; i++ { - _, err = utils.RunCommand("nigiri", "faucet", addr.Address) - if err != nil { - return fmt.Errorf("failed to fund wallet: %s", err) - } - } - - time.Sleep(5 * time.Second) - return nil -} - func setupArkSDK(t *testing.T) (arksdk.ArkClient, client.ASPClient) { appDataStore, err := store.NewStore(store.Config{ ConfigStoreType: types.FileStore, diff --git a/server/test/e2e/test_utils.go b/server/test/e2e/test_utils.go index c28ba9edc..f43562412 100644 --- a/server/test/e2e/test_utils.go +++ b/server/test/e2e/test_utils.go @@ -1,8 +1,11 @@ package e2e import ( + "bytes" + "encoding/json" "fmt" "io" + "net/http" "os/exec" "strings" "sync" @@ -104,3 +107,121 @@ func newCommand(name string, arg ...string) *exec.Cmd { cmd := exec.Command(name, arg...) return cmd } + +func SetupServerWalletCovenantless(aspUrl string, initFunding float64) error { + adminHttpClient := &http.Client{ + Timeout: 15 * time.Second, + } + req, err := http.NewRequest("GET", fmt.Sprintf("%s/v1/admin/wallet/seed", aspUrl), nil) + if err != nil { + return fmt.Errorf("failed to prepare generate seed request: %s", err) + } + req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") + + seedResp, err := adminHttpClient.Do(req) + if err != nil { + return fmt.Errorf("failed to generate seed: %s", err) + } + + var seed struct { + Seed string `json:"seed"` + } + + if err := json.NewDecoder(seedResp.Body).Decode(&seed); err != nil { + return fmt.Errorf("failed to parse response: %s", err) + } + + reqBody := bytes.NewReader([]byte(fmt.Sprintf(`{"seed": "%s", "password": "%s"}`, seed.Seed, Password))) + req, err = http.NewRequest("POST", "http://localhost:7070/v1/admin/wallet/create", reqBody) + if err != nil { + return fmt.Errorf("failed to prepare wallet create request: %s", err) + } + req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") + req.Header.Set("Content-Type", "application/json") + + if _, err := adminHttpClient.Do(req); err != nil { + return fmt.Errorf("failed to create wallet: %s", err) + } + + reqBody = bytes.NewReader([]byte(fmt.Sprintf(`{"password": "%s"}`, Password))) + req, err = http.NewRequest("POST", "http://localhost:7070/v1/admin/wallet/unlock", reqBody) + if err != nil { + return fmt.Errorf("failed to prepare wallet unlock request: %s", err) + } + req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") + req.Header.Set("Content-Type", "application/json") + + if _, err := adminHttpClient.Do(req); err != nil { + return fmt.Errorf("failed to unlock wallet: %s", err) + } + + var status struct { + Initialized bool `json:"initialized"` + Unlocked bool `json:"unlocked"` + Synced bool `json:"synced"` + } + for { + time.Sleep(time.Second) + + req, err := http.NewRequest("GET", "http://localhost:7070/v1/admin/wallet/status", nil) + if err != nil { + return fmt.Errorf("failed to prepare status request: %s", err) + } + resp, err := adminHttpClient.Do(req) + if err != nil { + return fmt.Errorf("failed to get status: %s", err) + } + if err := json.NewDecoder(resp.Body).Decode(&status); err != nil { + return fmt.Errorf("failed to parse status response: %s", err) + } + if status.Initialized && status.Unlocked && status.Synced { + break + } + } + + var addr struct { + Address string `json:"address"` + } + for addr.Address == "" { + time.Sleep(time.Second) + + req, err = http.NewRequest("GET", "http://localhost:7070/v1/admin/wallet/address", nil) + if err != nil { + return fmt.Errorf("failed to prepare new address request: %s", err) + } + req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW4=") + + resp, err := adminHttpClient.Do(req) + if err != nil { + return fmt.Errorf("failed to get new address: %s", err) + } + + if err := json.NewDecoder(resp.Body).Decode(&addr); err != nil { + return fmt.Errorf("failed to parse response: %s", err) + } + } + + if initFunding == 0.0 { + const numberOfFaucet = 15 // must cover the liquidity needed for all tests + for i := 0; i < numberOfFaucet; i++ { + _, err = RunCommand("nigiri", "faucet", addr.Address) + if err != nil { + return fmt.Errorf("failed to fund wallet: %s", err) + } + } + + } else { + chunkSize := initFunding / 5 + for i := 0; i < 5; i++ { + amount := fmt.Sprintf("%.8f", chunkSize) + _, err = RunCommand("nigiri", "faucet", addr.Address, amount) + if err != nil { + return fmt.Errorf("failed to fund wallet chunk %d: %s", i+1, err) + } + time.Sleep(1 * time.Second) + } + } + + time.Sleep(5 * time.Second) + return nil +} diff --git a/simulation/Makefile b/simulation/Makefile new file mode 100644 index 000000000..d2e04ef56 --- /dev/null +++ b/simulation/Makefile @@ -0,0 +1,48 @@ +.PHONY: run push-to-ecr build-client + +#### Local simulation #### +## run-single: Run bundled simulation where client and server are in the same process +run-single: + @echo "Running singe process simulation..." + go run ./local/single-process/main.go + +## run-multi: Run simulation with separate client and server processes +run-multi: build-local-client + @echo "Running multi-process simulation..." + go run ./local/process-per-client/main.go + +## build-local-client +build-local-client: + @echo "Building local client..." + go build -o ./build/client ./local/process-per-client/client/main.go + +#### Remote simulation #### + +# Default values for optional variables +ECR_REPOSITORY_NAME ?= ark-client-repo +IMAGE_NAME ?= arkclient +DOCKERFILE_PATH ?= ./remote/client +BUILD_CONTEXT ?= ../ + +## push-to-ecr: Build and push client image to ECR +push-to-ecr: + @echo "Building and pushing client image to ECR..." + ./script/build_and_push.sh -a $(AWS_ACCOUNT_ID) -r $(AWS_REGION) -e $(ECR_REPOSITORY_NAME) -i $(IMAGE_NAME) -d $(DOCKERFILE_PATH) -c $(BUILD_CONTEXT) + +## build-client: Build Docker image only without pushing to ECR +build-client: + @echo "Building Docker image without pushing to ECR..." + ./script/build_and_push.sh -a $(AWS_ACCOUNT_ID) -r $(AWS_REGION) -e $(ECR_REPOSITORY_NAME) -i $(IMAGE_NAME) -d $(DOCKERFILE_PATH) -c $(BUILD_CONTEXT) --no-push + +## run-remote: Run simulation on remote server +run-remote: + @echo "Running simulation on remote server..." + @if [ -z "$(SUBNET_IDS)" ]; then \ + echo "Error: SUBNET_IDS is not set. You can find this in CloudFormation outputs."; \ + exit 1; \ + fi + @if [ -z "$(SECURITY_GROUP_IDS)" ]; then \ + echo "Error: SECURITY_GROUP_IDS is not set. You can find this in CloudFormation outputs."; \ + exit 1; \ + fi + go run ./remote/orchestrator/main.go \ No newline at end of file diff --git a/simulation/README.md b/simulation/README.md new file mode 100644 index 000000000..f3685c8b4 --- /dev/null +++ b/simulation/README.md @@ -0,0 +1,102 @@ +# Simulation Framework for Ark Server Testing + +This simulation framework tests the **Ark Server** by simulating multiple clients performing various actions over several rounds. It utilizes YAML configuration files and validates them against a predefined schema. + +## Architecture + +The simulation framework is structured as follows: + +1. **Configuration Files**: + - `schema.yaml`: Defines the structure and rules for configuration files used in simulations. + - `Simulation.yaml`: The main configuration file, following `schema.yaml`, specifies the parameters for each simulation. + +2. **Orchestrator**: + - Acts as the main controller, reading configurations from `schema.yaml` and `Simulation.yaml`. + - Start ASP and Ark Clients and orchestrates the interactions between them based on the defined simulation scenarios. + - Supports both single-process and multi-process simulations for flexible testing. + +3. **Ark Clients**: + - Represent individual Ark Client that interact with the **Ark Server** based on orchestrated instructions. + - Multiple Ark Clients can run in parallel, enabling the simulation of a network of users with varying behaviors. + +4. **External Dependencies**: + - **Nigiri**: Provides a local Bitcoin Regtest environment, necessary for simulating blockchain-related actions. + - **Ark Server**: The server under test, which receives requests from Ark Clients and processes them accordingly. + +

+ Architecture Diagram +

+ +## Usage + +The simulation can be run either locally or on AWS. + +### Local Deployment + +For smaller tests, local deployment allows for a quick setup: + +- **Single process**: The orchestrator and Ark Clients run in the same process. +- **Multi-process**: The orchestrator and clients run as separate processes, mimicking a more realistic client-server interaction. + +#### Prerequisites + +1. **Start Nigiri (Bitcoin Regtest environment)**: + ```bash + nigiri start + ``` + +2. **Configure Testing Scenario**: + - Create a simulation YAML file based on the `schema.yaml` format. + - Check out the example configuration for guidance. + +3. **Run Simulation**: + ```bash + # Single-process mode: + make run-single + + # Multi-process mode: + make run-multi + ``` + +### AWS Deployment +As more users join the round, VTXO tree grows and there will be more transactions to sign by each user. +Considering signing is expensive operation, it quickly becomes a bottleneck in the simulation, as it drains the CPU resources. +To overcome this and to provide a more realistic simulation, this framework supports running the simulation in AWS. + +#### Prerequisites + +1. **Create AWS SSH Keys**: + - Go to AWS EC2 Console > Key Pairs + - Create a new key pair and save the private key file (`.pem`) + +#### Setup Process + +1. **Deploy CloudFormation Stack**: + - Upload the CloudFormation template file to AWS CloudFormation + - Fill in the mandatory parameters: + - Stack name + - SSH key pair (select the one created in prerequisites) + - Ark GitHub URL + - Branch name (defaults to master) + +2. **Get Infrastructure Details**: + - Once CloudFormation stack creation is complete, go to the Outputs tab + - Note down the following values: + - `SUBNET_IDS` + - `SECURITY_GROUP_IDS` + +3. **Verify Installation**: + - SSH into the EC2 instance + - Check installation progress: + ```bash + less /var/log/cloud-init-output.log + ``` + - Verify that the Ark Client Docker image has been successfully pushed to ECR + +4. **Run Remote Simulation**: + ```bash + cd ./ark/simulation/remote/orchestrator + export SUBNET_IDS={SUBNET_IDS} + export SECURITY_GROUP_IDS={SECURITY_GROUP_IDS} + make run-remote + ``` \ No newline at end of file diff --git a/simulation/arch.png b/simulation/arch.png new file mode 100644 index 000000000..d53bb521e Binary files /dev/null and b/simulation/arch.png differ diff --git a/simulation/go.mod b/simulation/go.mod new file mode 100644 index 000000000..ee5dcb295 --- /dev/null +++ b/simulation/go.mod @@ -0,0 +1,122 @@ +module github.com/ark-network/ark/simulation + +go 1.23.1 + +require ( + github.com/ark-network/ark/pkg/client-sdk v0.0.0-20241031170119-04e57f8179a3 + github.com/ark-network/ark/server v0.0.0-20241031170119-04e57f8179a3 + github.com/aws/aws-sdk-go-v2 v1.32.3 + github.com/aws/aws-sdk-go-v2/config v1.28.1 + github.com/aws/aws-sdk-go-v2/service/ecs v1.49.0 + github.com/gorilla/websocket v1.5.3 + github.com/sirupsen/logrus v1.9.3 + github.com/xeipuuv/gojsonschema v1.2.0 + sigs.k8s.io/yaml v1.4.0 +) + +require ( + github.com/aead/siphash v1.0.1 // indirect + github.com/ark-network/ark/api-spec v0.0.0-20241031170119-04e57f8179a3 // indirect + github.com/ark-network/ark/common v0.0.0-20241031170119-04e57f8179a3 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.42 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect + github.com/aws/smithy-go v1.22.0 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/btcutil/psbt v1.1.9 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/btcwallet v0.16.10-0.20240718224643-db3a4a2543bd // indirect + github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 // indirect + github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 // indirect + github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 // indirect + github.com/btcsuite/btcwallet/walletdb v1.4.2 // indirect + github.com/btcsuite/btcwallet/wtxmgr v1.5.3 // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/btcsuite/winsvc v1.0.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/lru v1.1.3 // indirect + github.com/dgraph-io/badger/v4 v4.2.0 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/analysis v0.23.0 // indirect + github.com/go-openapi/errors v0.22.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/loads v0.22.0 // indirect + github.com/go-openapi/runtime v0.28.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/validate v0.24.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.2.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0 // indirect + github.com/jessevdk/go-flags v1.6.1 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/jrick/logrotate v1.0.0 // indirect + github.com/kkdai/bstream v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect + github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd // indirect + github.com/lightninglabs/neutrino/cache v1.1.2 // indirect + github.com/lightningnetwork/lnd v0.18.2-beta // indirect + github.com/lightningnetwork/lnd/clock v1.1.1 // indirect + github.com/lightningnetwork/lnd/fn v1.2.1 // indirect + github.com/lightningnetwork/lnd/queue v1.1.1 // indirect + github.com/lightningnetwork/lnd/ticker v1.1.1 // indirect + github.com/lightningnetwork/lnd/tlv v1.2.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/timshannon/badgerhold/v4 v4.0.3 // indirect + github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 // indirect + github.com/vulpemventures/go-elements v0.5.4 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/otel v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/trace v1.30.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/simulation/go.sum b/simulation/go.sum new file mode 100644 index 000000000..b29bd8f87 --- /dev/null +++ b/simulation/go.sum @@ -0,0 +1,703 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/ark-network/ark/api-spec v0.0.0-20241031170119-04e57f8179a3 h1:FYVDtmrXutcoRpHWlmGqB/WVZOCpGVZPMqVapHVFUjw= +github.com/ark-network/ark/api-spec v0.0.0-20241031170119-04e57f8179a3/go.mod h1:TRbR7D04k6Tx//Eo/DUay+hFTT42NPCo8RmjcyrQ1DY= +github.com/ark-network/ark/common v0.0.0-20241031170119-04e57f8179a3 h1:kbVQK+yYVwsUXNk8JyJOmgKXuHEQaClwcJ8cWim7JWk= +github.com/ark-network/ark/common v0.0.0-20241031170119-04e57f8179a3/go.mod h1:zA5/UUj+G/WXDmihyzIVWViTo9rqKf/lb/Mw5MjzusM= +github.com/ark-network/ark/pkg/client-sdk v0.0.0-20241031170119-04e57f8179a3 h1:fyWUcjbzZo4TvY0/OARzsBAaEVaFh37CT6TzlJD/OLQ= +github.com/ark-network/ark/pkg/client-sdk v0.0.0-20241031170119-04e57f8179a3/go.mod h1:xMsDQ9zuCB9VxUrsZQppmRqjIYPZsT8rXUVxrPSqQWs= +github.com/ark-network/ark/server v0.0.0-20241031170119-04e57f8179a3 h1:Jf+w1Cjy0fiMZGsnkvhKwqhV9UIFZAw9EBAErkcd1Hk= +github.com/ark-network/ark/server v0.0.0-20241031170119-04e57f8179a3/go.mod h1:bbLb1nTdv5d8FimJvw9PMXeWcT3UgsNrKOHurexvdX8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk= +github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2/config v1.28.1 h1:oxIvOUXy8x0U3fR//0eq+RdCKimWI900+SV+10xsCBw= +github.com/aws/aws-sdk-go-v2/config v1.28.1/go.mod h1:bRQcttQJiARbd5JZxw6wG0yIK3eLeSCPdg6uqmmlIiI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 h1:68jFVtt3NulEzojFesM/WVarlFpCaXLKaBxDpzkQ9OQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18/go.mod h1:Fjnn5jQVIo6VyedMc0/EhPpfNlPl7dHV916O6B+49aE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/ecs v1.49.0 h1:xhCV6zY5ZFzfyAUOiBXK6wh0HVQTBkvNwA/eiz89ZWY= +github.com/aws/aws-sdk-go-v2/service/ecs v1.49.0/go.mod h1:RXYd/Ts+sFnjDrVdAZsAfHVkYxQUxhC+l2zrSpSgCGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 h1:UTpsIf0loCIWEbrqdLb+0RxnTXfWh2vhw4nQmFi4nPc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3/go.mod h1:FZ9j3PFHHAR+w0BSEjK955w5YD2UwB/l/H0yAK3MJvI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 h1:2YCmIXv3tmiItw0LlYf6v7gEHebLY45kBEnPezbUKyU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3/go.mod h1:u19stRyNPxGhj6dRm+Cdgu6N75qnbW7+QN0q0dsAk58= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 h1:wVnQ6tigGsRqSWDEEyH6lSAJ9OyFUsSnbaUWChuSGzs= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3/go.mod h1:VZa9yTFyj4o10YGsmDO4gbQJUvvhY72fhumT8W4LqsE= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil/psbt v1.1.9 h1:UmfOIiWMZcVMOLaN+lxbbLSuoINGS1WmK1TZNI0b4yk= +github.com/btcsuite/btcd/btcutil/psbt v1.1.9/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcwallet v0.16.10-0.20240718224643-db3a4a2543bd h1:QDb8foTCRoXrfoZVEzSYgSde16MJh4gCtCin8OCS0kI= +github.com/btcsuite/btcwallet v0.16.10-0.20240718224643-db3a4a2543bd/go.mod h1:X2xDre+j1QphTRo54y2TikUzeSvreL1t1aMXrD8Kc5A= +github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= +github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= +github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= +github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g= +github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo= +github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc= +github.com/btcsuite/btcwallet/walletdb v1.4.2 h1:zwZZ+zaHo4mK+FAN6KeK85S3oOm+92x2avsHvFAhVBE= +github.com/btcsuite/btcwallet/walletdb v1.4.2/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= +github.com/btcsuite/btcwallet/wtxmgr v1.5.3 h1:QrWCio9Leh3DwkWfp+A1SURj8pYn3JuTLv3waP5uEro= +github.com/btcsuite/btcwallet/wtxmgr v1.5.3/go.mod h1:M4nQpxGTXiDlSOODKXboXX7NFthmiBNjzAKKNS7Fhjg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/decred/dcrd/lru v1.1.3 h1:w9EAbvGLyzm6jTjF83UKuqZEiUtJmvRhQDOCEIvSuE0= +github.com/decred/dcrd/lru v1.1.3/go.mod h1:Tw0i0pJyiLEx/oZdHLe1Wdv/Y7EGzAX+sYftnmxBR4o= +github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg= +github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= +github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fergusstrange/embedded-postgres v1.28.0 h1:Atixd24HCuBHBavnG4eiZAjRizOViwUahKGSjJdz1SU= +github.com/fergusstrange/embedded-postgres v1.28.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= +github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= +github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= +github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= +github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= +github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v23.5.9+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= +github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0 h1:CWyXh/jylQWp2dtiV33mY4iSSp6yf4lmn+c7/tN+ObI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0/go.mod h1:nCLIt0w3Ept2NwF8ThLmrppXsfT07oC8k0XNDxd8sVU= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= +github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= +github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= +github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v1.14.3 h1:h6W9cPuHsRWQFTWUZMAKMgG5jSwQI0Zurzdvlx3Plus= +github.com/jackc/pgtype v1.14.3/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= +github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= +github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= +github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= +github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= +github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s= +github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= +github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g= +github.com/lightninglabs/neutrino/cache v1.1.2/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= +github.com/lightningnetwork/lnd v0.18.2-beta h1:Qv4xQ2ka05vqzmdkFdISHCHP6CzHoYNVKfD18XPjHsM= +github.com/lightningnetwork/lnd v0.18.2-beta/go.mod h1:cGQR1cVEZFZQcCx2VBbDY8xwGjCz+SupSopU1HpjP2I= +github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= +github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= +github.com/lightningnetwork/lnd/fn v1.2.1 h1:pPsVGrwi9QBwdLJzaEGK33wmiVKOxs/zc8H7+MamFf0= +github.com/lightningnetwork/lnd/fn v1.2.1/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0= +github.com/lightningnetwork/lnd/healthcheck v1.2.5 h1:aTJy5xeBpcWgRtW/PGBDe+LMQEmNm/HQewlQx2jt7OA= +github.com/lightningnetwork/lnd/healthcheck v1.2.5/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= +github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY= +github.com/lightningnetwork/lnd/kvdb v1.4.10/go.mod h1:J2diNABOoII9UrMnxXS5w7vZwP7CA1CStrl8MnIrb3A= +github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= +github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= +github.com/lightningnetwork/lnd/sqldb v1.0.3 h1:zLfAwOvM+6+3+hahYO9Q3h8pVV0TghAR7iJ5YMLCd3I= +github.com/lightningnetwork/lnd/sqldb v1.0.3/go.mod h1:4cQOkdymlZ1znnjuRNvMoatQGJkRneTj2CoPSPaQhWo= +github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= +github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= +github.com/lightningnetwork/lnd/tlv v1.2.6 h1:icvQG2yDr6k3ZuZzfRdG3EJp6pHurcuh3R6dg0gv/Mw= +github.com/lightningnetwork/lnd/tlv v1.2.6/go.mod h1:/CmY4VbItpOldksocmGT4lxiJqRP9oLxwSZOda2kzNQ= +github.com/lightningnetwork/lnd/tor v1.1.3 h1:hPIxSpT0UUJmt7iCbF4n4nsmkYe++fvQ/zRadeFfprY= +github.com/lightningnetwork/lnd/tor v1.1.3/go.mod h1:/LwOzgL6c+bVW0Aegoj1pGlxx9wSvbulBe876knJetc= +github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI= +github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g= +github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 h1:xuWxvRKxLvOKuS7/Q/7I3tpc3cWAB0+hZpU8YdVqkzg= +github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2/go.mod h1:nkLkAFGhursWf2U68gt61hPieK1I+0m78e+2aevNyD8= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= +github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNGuyA= +github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/timshannon/badgerhold/v4 v4.0.3 h1:W6pd2qckoXw2cl8eH0ZCV/9CXNaXvaM26tzFi5Tj+v8= +github.com/timshannon/badgerhold/v4 v4.0.3/go.mod h1:IkZIr0kcZLMdD7YJfW/G6epb6ZXHD/h0XR2BTk/VZg8= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI= +github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8= +github.com/vulpemventures/go-elements v0.5.4 h1:l94xoa9aYPPWiOB7Pmi08rKYvdk/n/sQIbLkQfEAASc= +github.com/vulpemventures/go-elements v0.5.4/go.mod h1:Tvhb+rZWv3lxoI5CdK03J3V+e2QVr/7UAnCYILxFSq4= +github.com/vulpemventures/go-secp256k1-zkp v1.1.6 h1:BmsrmXRLUibwa75Qkk8yELjpzCzlAjYFGLiLiOdq7Xo= +github.com/vulpemventures/go-secp256k1-zkp v1.1.6/go.mod h1:zo7CpgkuPgoe7fAV+inyxsI9IhGmcoFgyD8nqZaPSOM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.etcd.io/etcd/api/v3 v3.5.15 h1:3KpLJir1ZEBrYuV2v+Twaa/e2MdDCEZ/70H+lzEiwsk= +go.etcd.io/etcd/api/v3 v3.5.15/go.mod h1:N9EhGzXq58WuMllgH9ZvnEr7SI9pS0k0+DHZezGp7jM= +go.etcd.io/etcd/client/pkg/v3 v3.5.15 h1:fo0HpWz/KlHGMCC+YejpiCmyWDEuIpnTDzpJLB5fWlA= +go.etcd.io/etcd/client/pkg/v3 v3.5.15/go.mod h1:mXDI4NAOwEiszrHCb0aqfAYNCrZP4e9hRca3d1YK8EU= +go.etcd.io/etcd/client/v2 v2.305.15 h1:VG2xbf8Vz1KJh65Ar2V5eDmfkp1bpzkSEHlhJM3usp8= +go.etcd.io/etcd/client/v2 v2.305.15/go.mod h1:Ad5dRjPVb/n5yXgAWQ/hXzuXXkBk0Y658ocuXYaUU48= +go.etcd.io/etcd/client/v3 v3.5.15 h1:23M0eY4Fd/inNv1ZfU3AxrbbOdW79r9V9Rl62Nm6ip4= +go.etcd.io/etcd/client/v3 v3.5.15/go.mod h1:CLSJxrYjvLtHsrPKsy7LmZEE+DK2ktfd2bN4RhBMwlU= +go.etcd.io/etcd/pkg/v3 v3.5.15 h1:/Iu6Sr3iYaAjy++8sIDoZW9/EfhcwLZwd4FOZX2mMOU= +go.etcd.io/etcd/pkg/v3 v3.5.15/go.mod h1:e3Acf298sPFmTCGTrnGvkClEw9RYIyPtNzi1XM8rets= +go.etcd.io/etcd/raft/v3 v3.5.15 h1:jOA2HJF7zb3wy8H/pL13e8geWqkEa/kUs0waUggZC0I= +go.etcd.io/etcd/raft/v3 v3.5.15/go.mod h1:k3r7P4seEiUcgxOPLp+mloJWV3Q4QLPGNvy/OgC8OtM= +go.etcd.io/etcd/server/v3 v3.5.15 h1:x35jrWnZgsRwMsFsUJIUdT1bvzIz1B+29HjMfRYVN/E= +go.etcd.io/etcd/server/v3 v3.5.15/go.mod h1:l9jX9oa/iuArjqz0RNX/TDbc70dLXxRZo/nmPucrpFo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM= +google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc= +google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988 h1:+/tmTy5zAieooKIXfzDm9KiA3Bv6JBwriRN9LY+yayk= +google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988/go.mod h1:4+X6GvPs+25wZKbQq9qyAXrwIRExv7w0Ea6MgZLZiDM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a h1:CfbpOLEo2IwNzJdMvE8aiRbPMxoTpgAJeyePh0SmO8M= +modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.59.3 h1:A4QAp1lRSn2/b4aU+wBtq+yeKgq/2BUevrj0p1ZNy2M= +modernc.org/libc v1.59.3/go.mod h1:EY/egGEU7Ju66eU6SBqCNYaFUDuc4npICkMWnU5EE3A= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= +modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/simulation/local/process-per-client/client/main.go b/simulation/local/process-per-client/client/main.go new file mode 100644 index 000000000..69b2b769a --- /dev/null +++ b/simulation/local/process-per-client/client/main.go @@ -0,0 +1,382 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + arksdk "github.com/ark-network/ark/pkg/client-sdk" + "github.com/ark-network/ark/pkg/client-sdk/store" + "github.com/ark-network/ark/pkg/client-sdk/types" + "github.com/gorilla/websocket" + log "github.com/sirupsen/logrus" + "net/http" + "net/url" + "os" + "os/signal" + "syscall" + "time" +) + +func main() { + var clientID string + var aspUrl string + flag.StringVar(&clientID, "id", "", "Client ID") + flag.StringVar(&aspUrl, "asp-url", "", "ASP URL") + flag.Parse() + + if clientID == "" { + log.Fatal("Client ID is required") + } + + if aspUrl == "" { + log.Fatal("ASP URL is required") + } + + client := &Client{ + ID: clientID, + } + + // Initialize context for cancellation + client.ctx, client.cancel = context.WithCancel(context.Background()) + + // Handle OS signals for graceful shutdown + go client.handleSignals() + + // Set up ArkClient + err := client.setupArkClient(aspUrl) + if err != nil { + log.Fatalf("Failed to set up client: %v", err) + } + + // Connect to orchestrator + err = client.connectToOrchestrator() + if err != nil { + log.Fatalf("Failed to connect to orchestrator: %v", err) + } + + // Listen for commands from orchestrator + client.listenForCommands() +} + +// setupArkClient initializes the ArkClient for the client. +func (c *Client) setupArkClient(aspUrl string) error { + appDataStore, err := store.NewStore(store.Config{ + ConfigStoreType: types.InMemoryStore, + }) + if err != nil { + return fmt.Errorf("failed to create store: %s", err) + } + + client, err := arksdk.NewCovenantlessClient(appDataStore) + if err != nil { + return fmt.Errorf("failed to setup ark client: %s", err) + } + + ctx := context.Background() + if err := client.Init(ctx, arksdk.InitArgs{ + WalletType: arksdk.SingleKeyWallet, + ClientType: arksdk.GrpcClient, + AspUrl: aspUrl, + Password: "password", + }); err != nil { + return fmt.Errorf("failed to initialize wallet: %s", err) + } + + if err := client.Unlock(ctx, "password"); err != nil { + return fmt.Errorf("failed to unlock wallet: %s", err) + } + + log.Infof("Client %s initialized ArkClient", c.ID) + c.ArkClient = client + return nil +} + +// connectToOrchestrator establishes a WebSocket connection to the orchestrator. +func (c *Client) connectToOrchestrator() error { + u := url.URL{ + Scheme: "ws", + Host: "localhost:9000", + Path: "/ws", + RawQuery: fmt.Sprintf("id=%s", c.ID), + } + var err error + c.Conn, _, err = websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + return fmt.Errorf("failed to connect to orchestrator: %v", err) + } + log.Infof("Connected to orchestrator") + + // Send the client's address to the orchestrator + err = c.sendAddress() + if err != nil { + return fmt.Errorf("failed to send address: %v", err) + } + + return nil +} + +// sendAddress sends the client's address to the orchestrator. +func (c *Client) sendAddress() error { + ctx := context.Background() + offchainAddress, _, err := c.ArkClient.Receive(ctx) + if err != nil { + return fmt.Errorf("failed to get address: %v", err) + } + c.Address = offchainAddress // Store the address in the client struct + + msg := ClientMessage{ + Type: "Address", + Data: offchainAddress, + } + err = c.Conn.WriteJSON(msg) + if err != nil { + return fmt.Errorf("failed to send address to orchestrator: %v", err) + } + log.Infof("Sent address to orchestrator: %s", offchainAddress) + return nil +} + +// listenForCommands listens for commands from the orchestrator. +func (c *Client) listenForCommands() { + defer c.Conn.Close() + for { + select { + case <-c.ctx.Done(): + log.Infof("Client %s shutting down", c.ID) + return + default: + var command Command + err := c.Conn.ReadJSON(&command) + if err != nil { + log.Infof("Error reading command: %v", err) + return + } + // Handle the command + c.handleCommand(command) + } + } +} + +// handleCommand processes a command received from the orchestrator. +func (c *Client) handleCommand(command Command) { + switch command.Type { + case "Onboard": + amount, ok := command.Data["amount"].(float64) + if !ok { + c.sendError("Invalid amount in Onboard command") + return + } + err := c.onboard(amount) + if err != nil { + c.sendError(fmt.Sprintf("Onboard failed: %v", err)) + } + case "SendAsync": + amount, ok := command.Data["amount"].(float64) + if !ok { + c.sendError("Invalid amount in SendAsync command") + return + } + toClientID, ok := command.Data["to"].(string) + if !ok { + c.sendError("Invalid recipient in SendAsync command") + return + } + err := c.sendAsync(amount, toClientID) + if err != nil { + c.sendError(fmt.Sprintf("SendAsync failed: %v", err)) + } + case "Claim": + err := c.claim() + if err != nil { + c.sendError(fmt.Sprintf("Claim failed: %v", err)) + } + case "Balance": + err := c.balance() + if err != nil { + c.sendError(fmt.Sprintf("Failed to get balance: %v", err)) + } + + case "Shutdown": + c.cancel() + // Add other command types as needed + default: + log.Infof("Unknown command type: %s", command.Type) + } +} + +// sendError sends an error message back to the orchestrator. +func (c *Client) sendError(message string) { + msg := ClientMessage{ + Type: "Error", + Data: message, + } + c.Conn.WriteJSON(msg) +} + +// onboard performs the onboarding process for the client. +func (c *Client) onboard(amount float64) error { + ctx := context.Background() + + _, boardingAddress, err := c.ArkClient.Receive(ctx) + if err != nil { + return err + } + + amountStr := fmt.Sprintf("%.8f", amount) + + // Send command execution request to orchestrator + cmdRequest := map[string]interface{}{ + "command": "nigiri", + "args": []string{"faucet", boardingAddress, amountStr}, + } + err = c.sendCommandRequest(cmdRequest) + if err != nil { + return err + } + + // Wait for the funds to be confirmed (simulate delay) + time.Sleep(5 * time.Second) + + _, err = c.ArkClient.Settle(ctx) + if err != nil { + return fmt.Errorf("client %s failed to onboard: %v", c.ID, err) + } + + log.Infof("Client %s onboarded successfully with %f BTC", c.ID, amount) + c.sendLog(fmt.Sprintf("Onboarded with %f BTC", amount)) + return nil +} + +// sendAsync sends funds asynchronously to another client. +func (c *Client) sendAsync(amount float64, toClientID string) error { + ctx := context.Background() + + // Request recipient address from orchestrator + recipientAddress, err := c.requestRecipientAddress(toClientID) + if err != nil { + return err + } + + receivers := []arksdk.Receiver{ + arksdk.NewBitcoinReceiver(recipientAddress, uint64(amount*1e8)), + } + + _, err = c.ArkClient.SendAsync(ctx, false, receivers) + if err != nil { + return fmt.Errorf("client %s failed to send %f BTC to client %s: %v", + c.ID, amount, toClientID, err) + } + + log.Infof("Client %s sent %f BTC to client %s", c.ID, amount, toClientID) + c.sendLog(fmt.Sprintf("Sent %f BTC to client %s", amount, toClientID)) + return nil +} + +// claim performs the claim action for the client. +func (c *Client) claim() error { + ctx := context.Background() + + txID, err := c.ArkClient.Settle(ctx) + if err != nil { + return fmt.Errorf("client %s failed to claim funds: %v", c.ID, err) + } + + log.Infof("Client %s claimed funds, txID: %v", c.ID, txID) + c.sendLog(fmt.Sprintf("Claimed funds, txID: %v", txID)) + return nil +} + +func (c *Client) balance() error { + ctx := context.Background() + + balance, err := c.ArkClient.Balance(ctx, false) + if err != nil { + return fmt.Errorf("client %s failed to get balance: %v", c.ID, err) + } + + return printJSON(balance) +} + +// sendCommandRequest sends a command execution request to the orchestrator. +func (c *Client) sendCommandRequest(cmdRequest map[string]interface{}) error { + jsonData, _ := json.Marshal(cmdRequest) + resp, err := http.Post("http://localhost:9000/cmd", "application/json", bytes.NewReader(jsonData)) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("command execution failed with status %d", resp.StatusCode) + } + return nil +} + +// sendLog sends a log message to the orchestrator. +func (c *Client) sendLog(message string) { + msg := ClientMessage{ + Type: "Log", + Data: message, + } + c.Conn.WriteJSON(msg) +} + +// requestRecipientAddress requests the recipient's address from the orchestrator. +func (c *Client) requestRecipientAddress(toClientID string) (string, error) { + resp, err := http.Get(fmt.Sprintf("http://localhost:9000/address?client_id=%s", toClientID)) + if err != nil { + return "", err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("failed to get address for client %s", toClientID) + } + var res struct { + Address string `json:"address"` + } + err = json.NewDecoder(resp.Body).Decode(&res) + if err != nil { + return "", err + } + return res.Address, nil +} + +// handleSignals handles OS signals for graceful shutdown. +func (c *Client) handleSignals() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + <-sigs + c.cancel() +} + +// Command represents a command received from the orchestrator. +type Command struct { + Type string `json:"type"` + Data map[string]interface{} `json:"data,omitempty"` +} + +// ClientMessage represents a message sent to the orchestrator. +type ClientMessage struct { + Type string `json:"type"` + Data interface{} `json:"data,omitempty"` +} + +// Client struct represents a client instance. +type Client struct { + ID string + Conn *websocket.Conn + ArkClient arksdk.ArkClient + ctx context.Context + cancel context.CancelFunc + Address string // Added Address field +} + +func printJSON(resp interface{}) error { + jsonBytes, err := json.MarshalIndent(resp, "", "\t") + if err != nil { + return err + } + log.Infoln(string(jsonBytes)) + return nil +} diff --git a/simulation/local/process-per-client/main.go b/simulation/local/process-per-client/main.go new file mode 100644 index 000000000..0452fbcec --- /dev/null +++ b/simulation/local/process-per-client/main.go @@ -0,0 +1,494 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + utils "github.com/ark-network/ark/server/test/e2e" + "github.com/xeipuuv/gojsonschema" + "net/url" + + "net/http" + "os" + "os/exec" + "sync" + "time" + + "github.com/gorilla/websocket" + log "github.com/sirupsen/logrus" + "sigs.k8s.io/yaml" +) + +const ( + composePath = "../docker-compose.clark.regtest.yml" + simulationPath = "simulation.yaml" + clientPath = "./build/client" + defaultAspUrl = "localhost:7070" +) + +var ( + clients = make(map[string]*ClientConnection) + clientsMu sync.Mutex + upgrader = websocket.Upgrader{} +) + +func main() { + // Parse command-line flags + simFile := flag.String("sim", simulationPath, "Path to simulation YAML file") + serverAddress := flag.String("server", "", "Orchestrator server address") + flag.Parse() + + // Load and validate the simulation YAML file + simulation, err := loadAndValidateSimulation(*simFile) + if err != nil { + log.Fatalf("Error loading simulation config: %v", err) + } + + // Determine the ASP URL, start ASP locally if no server address is provided + aspUrl := *serverAddress + if aspUrl == "" { + if err := startAspLocally(*simulation); err != nil { + log.Fatalf("Error starting ASP server: %v", err) + } + aspUrl = defaultAspUrl + } + + aspUrlParsed := &url.URL{ + Scheme: "http", + Host: aspUrl, + } + // Setup the server wallet with the initial funding + if err := utils.SetupServerWalletCovenantless(aspUrlParsed.String(), simulation.Server.InitialFunding); err != nil { + log.Fatal(err) + } + + // Start the orchestrator HTTP server + go startServer() + + // Start clients + err = startClients(aspUrl, simulation.Clients) + if err != nil { + log.Fatalf("Error starting clients: %v", err) + } + + // Wait for clients to connect + time.Sleep(2 * time.Second) + + go func() { + for { + if err := utils.GenerateBlock(); err != nil { + log.Fatal(err) + } + + time.Sleep(1 * time.Second) + } + }() + + // Execute the simulation + executeSimulation(simulation) + + // Stop clients after simulation + stopClients() +} + +// startAspLocally starts ASP server locally. +func startAspLocally(simulation Simulation) error { + log.Infof("Simulation Version: %s\n", simulation.Version) + log.Infof("ASP Network: %s\n", simulation.Server.Network) + log.Infof("Number of Clients: %d\n", len(simulation.Clients)) + log.Infof("Number of Rounds: %d\n", len(simulation.Rounds)) + + roundLifetime := fmt.Sprintf("ARK_ROUND_INTERVAL=%d", simulation.Server.RoundInterval) + tmpfile, err := os.CreateTemp("", "docker-env") + if err != nil { + return err + } + defer os.Remove(tmpfile.Name()) // clean up + + if _, err := tmpfile.Write([]byte(roundLifetime)); err != nil { + return err + } + if err := tmpfile.Close(); err != nil { + return err + } + + log.Infof("Start building ARKD docker container ...") + if _, err := utils.RunCommand("docker", "compose", "-f", composePath, "--env-file", tmpfile.Name(), "up", "-d"); err != nil { + return err + } + + time.Sleep(10 * time.Second) + log.Infoln("ASP running...") + + return nil +} + +// loadAndValidateSimulation reads and validates the simulation YAML file. +func loadAndValidateSimulation(simFile string) (*Simulation, error) { + // Read and convert the schema YAML file to JSON + schemaBytes, err := os.ReadFile("schema.yaml") + if err != nil { + return nil, fmt.Errorf("error reading schema file: %v", err) + } + + schemaJSON, err := yaml.YAMLToJSON(schemaBytes) + if err != nil { + return nil, fmt.Errorf("error converting schema YAML to JSON: %v", err) + } + + // Read and convert the simulation YAML file to JSON + simBytes, err := os.ReadFile(simFile) + if err != nil { + return nil, fmt.Errorf("error reading simulation file: %v", err) + } + + simJSON, err := yaml.YAMLToJSON(simBytes) + if err != nil { + return nil, fmt.Errorf("error converting simulation YAML to JSON: %v", err) + } + + // Create JSON loaders for the schema and the document + schemaLoader := gojsonschema.NewBytesLoader(schemaJSON) + documentLoader := gojsonschema.NewBytesLoader(simJSON) + + // Validate the simulation JSON against the schema JSON + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil { + return nil, fmt.Errorf("error validating simulation: %v", err) + } + + if !result.Valid() { + // Collect error messages + var errorMessages string + for _, desc := range result.Errors() { + errorMessages += fmt.Sprintf("- %s\n", desc) + } + return nil, fmt.Errorf("the simulation is not valid:\n%s", errorMessages) + } + + // Unmarshal the simulation YAML into the Simulation struct + var sim Simulation + err = json.Unmarshal(simJSON, &sim) + if err != nil { + return nil, fmt.Errorf("error parsing simulation YAML: %v", err) + } + + return &sim, nil +} + +// startClients launches each client as a separate process. +func startClients(aspUrl string, clientConfigs []ClientConfig) error { + var wg sync.WaitGroup + + for _, client := range clientConfigs { + wg.Add(1) + go func(client ClientConfig) { + defer wg.Done() + clientID := client.ID + + // Open a log file for the client + logFileName := fmt.Sprintf("./log/client_%s.log", clientID) + logFile, err := os.Create(logFileName) + if err != nil { + log.Errorf("failed to create log file for client %s: %v", clientID, err) + return + } + + cmd := exec.Command(clientPath, "--asp-url", aspUrl, "--id", clientID) + cmd.Stdout = logFile + cmd.Stderr = logFile + err = cmd.Start() + if err != nil { + log.Errorf("failed to start client %s: %v", clientID, err) + return + } + // Store the command process to stop it later if needed + clientsMu.Lock() + clients[clientID] = &ClientConnection{ + ID: clientID, + Conn: nil, // Will be set when the client connects + Cmd: cmd, + ConnMu: sync.Mutex{}, + } + clientsMu.Unlock() + }(client) + } + + wg.Wait() + // Give the client some time to start + time.Sleep(200 * time.Millisecond) + log.Infof("All clients started") + return nil +} + +// stopClients terminates all client processes. +func stopClients() { + // Send shutdown commands to clients + for clientID := range clients { + if err := sendCommand(clientID, Command{ + Type: "Shutdown", + }); err != nil { + log.Errorf("Error sending shutdown command to client %s: %v", clientID, err) + } + } +} + +func executeSimulation(simulation *Simulation) { + for _, round := range simulation.Rounds { + waitRound := false + log.Infof("Executing Round %d at %s", round.Number, time.Now().Format("2006-01-02 15:04:05")) + var wg sync.WaitGroup + for clientID, actions := range round.Actions { + wg.Add(1) + go func(clientID string, actions []ActionMap) { + defer wg.Done() + for _, action := range actions { + actionType, ok := action["type"].(string) + if !ok { + log.Infof("Invalid action type for client %s", clientID) + return + } + + if actionType == "Onboard" || actionType == "Claim" || actionType == "CollaborativeRedeem" { + waitRound = true + } + + // Prepare the command based on actionType + command := Command{ + Type: actionType, + Data: action, + } + // Send the command to the client + err := sendCommand(clientID, command) + if err != nil { + log.Warnf("Error sending %s to client %s: %v", actionType, clientID, err) + return + } + } + }(clientID, actions) + } + wg.Wait() + + sleepTime := 2 * time.Second + if waitRound { + sleepTime = time.Duration(simulation.Server.RoundInterval)*time.Second + 2*time.Second + } + log.Infof("Waiting for %s before starting next round", sleepTime) + time.Sleep(sleepTime) + log.Infof("Round %d completed at %s", round.Number, time.Now().Format("2006-01-02 15:04:05")) + } +} + +// startServer starts the orchestrator's HTTP server. +func startServer() { + http.HandleFunc("/ws", wsHandler) + http.HandleFunc("/cmd", cmdHandler) + http.HandleFunc("/log", logHandler) + http.HandleFunc("/address", addressHandler) // Added address handler + // Start the server + log.Infoln("Orchestrator HTTP server running on port 9000") + if err := http.ListenAndServe(":9000", nil); err != nil { + log.Fatalf("Orchestrator server failed: %v", err) + } +} + +// wsHandler handles WebSocket connections from clients. +func wsHandler(w http.ResponseWriter, r *http.Request) { + // Upgrade HTTP connection to WebSocket + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Infoln("Upgrade error:", err) + return + } + // Read client ID from query parameters + clientID := r.URL.Query().Get("id") + if clientID == "" { + log.Infoln("Client ID not provided") + conn.Close() + return + } + + clientsMu.Lock() + clientConn, exists := clients[clientID] + if !exists { + // New client, add to the clients map + clientConn = &ClientConnection{ + ID: clientID, + } + clients[clientID] = clientConn + } + clientConn.Conn = conn + clientsMu.Unlock() + + // Listen for messages from the client + go func() { + defer conn.Close() + for { + var message ClientMessage + err := conn.ReadJSON(&message) + if err != nil { + log.Infof("Error reading from client %s: %v", clientID, err) + break + } + handleClientMessage(clientID, message) + } + // Client disconnected + log.Infof("Client %s disconnected", clientID) + clientsMu.Lock() + delete(clients, clientID) + clientsMu.Unlock() + }() +} + +// sendCommand sends a command to a client. +func sendCommand(clientID string, command Command) error { + clientsMu.Lock() + clientConn, exists := clients[clientID] + clientsMu.Unlock() + if !exists || clientConn.Conn == nil { + return fmt.Errorf("client %s not connected", clientID) + } + + clientConn.ConnMu.Lock() + defer clientConn.ConnMu.Unlock() + + return clientConn.Conn.WriteJSON(command) +} + +// handleClientMessage processes messages received from clients. +func handleClientMessage(clientID string, message ClientMessage) { + // Process the message based on its type + switch message.Type { + case "Log": + log.Infof("Log from client %s: %s", clientID, message.Data) + case "Address": + address, ok := message.Data.(string) + if !ok { + log.Infof("Invalid address from client %s", clientID) + return + } + clientsMu.Lock() + clientConn, exists := clients[clientID] + if exists { + clientConn.Address = address + } + clientsMu.Unlock() + case "Error": + log.Warnf("Error from client %s: %s", clientID, message.Data) + default: + log.Infof("Unknown message type from client %s: %s", clientID, message.Type) + } +} + +// addressHandler handles requests for client addresses. +func addressHandler(w http.ResponseWriter, r *http.Request) { + clientID := r.URL.Query().Get("client_id") + if clientID == "" { + http.Error(w, "client_id is required", http.StatusBadRequest) + return + } + + clientsMu.Lock() + clientConn, exists := clients[clientID] + clientsMu.Unlock() + if !exists { + http.Error(w, fmt.Sprintf("client %s not found", clientID), http.StatusNotFound) + return + } + if clientConn.Address == "" { + http.Error(w, fmt.Sprintf("address for client %s not available", clientID), http.StatusNotFound) + return + } + + res := struct { + Address string `json:"address"` + }{ + Address: clientConn.Address, + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(res) +} + +// cmdHandler handles command execution requests from clients. +func cmdHandler(w http.ResponseWriter, r *http.Request) { + var cmdRequest struct { + Command string `json:"command"` + Args []string `json:"args"` + } + err := json.NewDecoder(r.Body).Decode(&cmdRequest) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + log.Infof("Executing command: %s %v", cmdRequest.Command, cmdRequest.Args) + // Execute the command + output, err := exec.Command(cmdRequest.Command, cmdRequest.Args...).CombinedOutput() + if err != nil { + log.Infof("Command execution failed: %v", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + log.Infof("Command output: %s", output) + w.WriteHeader(http.StatusOK) +} + +// logHandler handles log messages from clients. +func logHandler(w http.ResponseWriter, r *http.Request) { + var logEntry map[string]interface{} + err := json.NewDecoder(r.Body).Decode(&logEntry) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + log.Infof("Log from client: %v", logEntry) + w.WriteHeader(http.StatusOK) +} + +// Command represents a command sent to a client. +type Command struct { + Type string `json:"type"` + Data map[string]interface{} `json:"data,omitempty"` +} + +// ClientMessage represents a message received from a client. +type ClientMessage struct { + Type string `json:"type"` + Data interface{} `json:"data,omitempty"` +} + +// ClientConfig holds configuration for a client. +type ClientConfig struct { + ID string `json:"id"` + Name string `json:"name"` +} + +// ActionMap represents an action in the simulation rounds. +type ActionMap map[string]interface{} + +// Round represents a simulation round. +type Round struct { + Number int `json:"number"` + Actions map[string][]ActionMap `json:"actions"` +} + +// Simulation represents the entire simulation configuration. +type Simulation struct { + Version string `json:"version"` + Server struct { + Network string `json:"network"` + InitialFunding float64 `json:"initial_funding"` + RoundInterval int `json:"round_interval"` + } `yaml:"server"` + Clients []ClientConfig `json:"clients"` + Rounds []Round `json:"rounds"` +} + +// ClientConnection holds information about a connected client. +type ClientConnection struct { + ID string + Conn *websocket.Conn + Address string + Cmd *exec.Cmd + ConnMu sync.Mutex +} diff --git a/simulation/local/single-process/main.go b/simulation/local/single-process/main.go new file mode 100644 index 000000000..9860cf7e1 --- /dev/null +++ b/simulation/local/single-process/main.go @@ -0,0 +1,355 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "github.com/ark-network/ark/pkg/client-sdk/store" + "github.com/ark-network/ark/pkg/client-sdk/types" + "os" + "sync" + "time" + + arksdk "github.com/ark-network/ark/pkg/client-sdk" + utils "github.com/ark-network/ark/server/test/e2e" + log "github.com/sirupsen/logrus" + + "github.com/xeipuuv/gojsonschema" + "sigs.k8s.io/yaml" +) + +const ( + composePath = "../docker-compose.clark.regtest.yml" + simulationPath = "simulation.yaml" +) + +var ( + aspUrl = "localhost:7070" + clientType = arksdk.GrpcClient + password = "password" + walletType = arksdk.SingleKeyWallet +) + +func main() { + simFile := flag.String("simulation", simulationPath, "Path to the simulation YAML file") + flag.Parse() + + simulation, err := loadAndValidateSimulation(*simFile) + if err != nil { + log.Fatal(err) + } + + log.Infof("Simulation Version: %s\n", simulation.Version) + log.Infof("ASP Network: %s\n", simulation.Server.Network) + log.Infof("Number of Clients: %d\n", len(simulation.Clients)) + log.Infof("Number of Rounds: %d\n", len(simulation.Rounds)) + + roundLifetime := fmt.Sprintf("ARK_ROUND_INTERVAL=%d", simulation.Server.RoundInterval) + tmpfile, err := os.CreateTemp("", "docker-env") + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmpfile.Name()) // clean up + + if _, err := tmpfile.Write([]byte(roundLifetime)); err != nil { + log.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + log.Fatal(err) + } + + log.Infof("Start building ARKD docker container ...") + if _, err := utils.RunCommand("docker", "compose", "-f", composePath, "--env-file", tmpfile.Name(), "up", "-d", "--build"); err != nil { + log.Fatal(err) + } + + time.Sleep(10 * time.Second) + log.Infoln("ASP running...") + + if err := utils.SetupServerWalletCovenantless("http://localhost:7070", simulation.Server.InitialFunding); err != nil { + log.Fatal(err) + } + + time.Sleep(3 * time.Second) + + log.Infoln("ASP wallet initialized") + + go func() { + for { + if err := utils.GenerateBlock(); err != nil { + log.Fatal(err) + } + + time.Sleep(1 * time.Second) + } + }() + + users := make(map[string]User) + usersMtx := sync.Mutex{} + var wg sync.WaitGroup + for _, v := range simulation.Clients { + wg.Add(1) + go func(id string, initialFunding float64) { + defer wg.Done() + cl, err := setupArkClient() + if err != nil { + log.Fatal(err) + } + + usersMtx.Lock() + users[id] = User{ + client: cl, + ID: id, + InitialFunding: initialFunding, + } + usersMtx.Unlock() + }(v.ID, v.InitialFunding) + } + wg.Wait() + log.Infof("Client wallets initialized") + + for _, round := range simulation.Rounds { + log.Infof("Executing Round %d\n", round.Number) + var wg sync.WaitGroup + for clientID, actions := range round.Actions { + user, ok := users[clientID] + if !ok { + log.Fatalf("User %s not found", clientID) + } + wg.Add(1) + go func(u User, actions []interface{}) { + defer wg.Done() + for _, a := range actions { + actionMap := a.(map[string]interface{}) + actionType := actionMap["type"].(string) + amount, _ := actionMap["amount"].(float64) + to, _ := actionMap["to"].(string) + + var err error + switch actionType { + case "Onboard": + err = onboard(u, amount) + case "SendAsync": + err = sendAsync(u, amount, to, users) + case "Claim": + err = claim(u) + default: + log.Printf("Unknown action type: %s for user %s", actionType, u.ID) + return + } + + if err != nil { + log.Printf("%s failed for user %s: %v", actionType, u.ID, err) + } + } + }(user, actions) + } + wg.Wait() + + time.Sleep(2 * time.Second) + } + + //log.Println("Final balances for all clients:") + //for _, user := range users { + // wg.Add(1) + // go func(u User) { + // defer wg.Done() + // ctx := context.Background() + // balance, err := getBalance(u.client, ctx) + // if err != nil { + // log.Errorf("Failed to get balance for user %s: %v", u.ID, err) + // } else { + // if err := printJSON(u.Name, balance); err != nil { + // log.Errorf("Failed to print JSON for user %s: %v", u.ID, err) + // } + // } + // }(user) + //} + //wg.Wait() +} + +func loadAndValidateSimulation(simFile string) (*Simulation, error) { + // Read and convert the schema YAML file to JSON + schemaBytes, err := os.ReadFile("schema.yaml") + if err != nil { + return nil, fmt.Errorf("error reading schema file: %v", err) + } + + schemaJSON, err := yaml.YAMLToJSON(schemaBytes) + if err != nil { + return nil, fmt.Errorf("error converting schema YAML to JSON: %v", err) + } + + // Read and convert the simulation YAML file to JSON + simBytes, err := os.ReadFile(simFile) + if err != nil { + return nil, fmt.Errorf("error reading simulation file: %v", err) + } + + simJSON, err := yaml.YAMLToJSON(simBytes) + if err != nil { + return nil, fmt.Errorf("error converting simulation YAML to JSON: %v", err) + } + + // Create JSON loaders for the schema and the document + schemaLoader := gojsonschema.NewBytesLoader(schemaJSON) + documentLoader := gojsonschema.NewBytesLoader(simJSON) + + // Validate the simulation JSON against the schema JSON + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil { + return nil, fmt.Errorf("error validating simulation: %v", err) + } + + if !result.Valid() { + // Collect error messages + var errorMessages string + for _, desc := range result.Errors() { + errorMessages += fmt.Sprintf("- %s\n", desc) + } + return nil, fmt.Errorf("the simulation is not valid:\n%s", errorMessages) + } + + // Unmarshal the simulation YAML into the Simulation struct + var sim Simulation + err = json.Unmarshal(simJSON, &sim) + if err != nil { + return nil, fmt.Errorf("error parsing simulation YAML: %v", err) + } + + return &sim, nil +} + +func setupArkClient() (arksdk.ArkClient, error) { + appDataStore, err := store.NewStore(store.Config{ + ConfigStoreType: types.InMemoryStore, + }) + + if err != nil { + return nil, fmt.Errorf("failed to create store: %s", err) + } + + client, err := arksdk.NewCovenantlessClient(appDataStore) + if err != nil { + return nil, fmt.Errorf("failed to setup ark client: %s", err) + } + + ctx := context.Background() + if err := client.Init(ctx, arksdk.InitArgs{ + WalletType: walletType, + ClientType: clientType, + AspUrl: aspUrl, + Password: password, + }); err != nil { + return nil, fmt.Errorf("failed to initialize wallet: %s", err) + } + + if err := client.Unlock(ctx, password); err != nil { + return nil, fmt.Errorf("failed to unlock wallet: %s", err) + } + + return client, nil +} + +func onboard(user User, amount float64) error { + ctx := context.Background() + + _, boardingAddress, err := user.client.Receive(ctx) + if err != nil { + return err + } + + amountStr := fmt.Sprintf("%.8f", amount) + + if _, err := utils.RunCommand("nigiri", "faucet", boardingAddress, amountStr); err != nil { + return err + } + + time.Sleep(5 * time.Second) + + if _, err = user.client.Settle(ctx); err != nil { + return fmt.Errorf("user %s failed to onboard: %v", user.ID, err) + } + + log.Infof("%s onboarded successfully with %f BTC", user.ID, amount) + + return nil +} + +func sendAsync(user User, amount float64, to string, users map[string]User) error { + ctx := context.Background() + + toUser, ok := users[to] + if !ok { + return fmt.Errorf("recipient user %s not found", to) + } + + toAddress, _, err := toUser.client.Receive(ctx) + if err != nil { + return err + } + + receivers := []arksdk.Receiver{ + arksdk.NewBitcoinReceiver(toAddress, uint64(amount*1e8)), + } + + if _, err = user.client.SendAsync(ctx, false, receivers); err != nil { + return fmt.Errorf("user %s failed to send %f BTC to user %s: %v", user.ID, amount, toUser.ID, err) + } + + log.Infof("user %s sent %f BTC to user %s", user.ID, amount, toUser.ID) + + return nil +} + +func claim(user User) error { + ctx := context.Background() + + txID, err := user.client.Settle(ctx) + if err != nil { + return fmt.Errorf("user %s failed to claim their funds: %v", user.ID, err) + } + + log.Infof("User %s claimed their funds, txID: %v", user.ID, txID) + + return nil +} + +func getBalance(client arksdk.ArkClient, ctx context.Context) (*arksdk.Balance, error) { + return client.Balance(ctx, false) +} + +type Simulation struct { + Version string `json:"version"` + Server struct { + Network string `json:"network"` + InitialFunding float64 `json:"initial_funding"` + RoundInterval int `json:"round_interval"` + } `json:"server"` + Clients []struct { + ID string `json:"id"` + Name string `json:"name"` + InitialFunding float64 `json:"initial_funding,omitempty"` + } `json:"clients"` + Rounds []struct { + Number int `json:"number"` + Actions map[string][]interface{} `json:"actions"` + } `json:"rounds"` +} +type User struct { + client arksdk.ArkClient + ID string + Name string + InitialFunding float64 +} + +func printJSON(user string, resp interface{}) error { + jsonBytes, err := json.MarshalIndent(resp, "", "\t") + if err != nil { + return err + } + log.Infof("User: %v", user) + log.Infoln(string(jsonBytes)) + return nil +} diff --git a/simulation/remote/client/Dockerfile b/simulation/remote/client/Dockerfile new file mode 100644 index 000000000..d11661aac --- /dev/null +++ b/simulation/remote/client/Dockerfile @@ -0,0 +1,54 @@ +FROM golang:1.23.1 AS builder + +ARG VERSION +ARG TARGETOS +ARG TARGETARCH + +WORKDIR /app + +# Copy the go.mod and go.sum files from ./simulation +COPY simulation/go.mod simulation/go.sum ./ + +# Copy the go.work file from the root +COPY go.work ./ + +# Set GOWORK to use the workspace file +ENV GOWORK=/app/go.work + +# Copy necessary directories +COPY common/ ./common/ +COPY pkg/ ./pkg/ +COPY api-spec ./api-spec/ +COPY client ./client/ +COPY server ./server/ +COPY server/pkg/kvdb ./server/pkg/kvdb/ +COPY server/pkg/macaroons ./server/pkg/macaroons/ +COPY simulation ./simulation/ + +# Copy the main.go file from ./simulation/remote/client +COPY simulation/remote/client/main.go ./ + +RUN go mod download + +# Build the binary with explicit name +RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \ + go build -v -ldflags="-X 'main.Version=${VERSION}'" -o arkclient main.go + +# Stage 2: Create the runtime image +FROM alpine:latest + +# Install file command for debugging +RUN apk add --no-cache file + +# Copy the binary with a specific name +COPY --from=builder /app/arkclient /arkclient + +# Verify the binary +RUN ls -la . && \ + chmod +x /arkclient && \ + file /arkclient + +EXPOSE 9000 + +# Use the binary as entrypoint +ENTRYPOINT ["./arkclient"] \ No newline at end of file diff --git a/simulation/remote/client/main.go b/simulation/remote/client/main.go new file mode 100644 index 000000000..c60a42aec --- /dev/null +++ b/simulation/remote/client/main.go @@ -0,0 +1,372 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + arksdk "github.com/ark-network/ark/pkg/client-sdk" + "github.com/ark-network/ark/pkg/client-sdk/store" + "github.com/ark-network/ark/pkg/client-sdk/types" + log "github.com/sirupsen/logrus" +) + +const ( + clientPort = "9000" +) + +var ( + orchestratorUrl string +) + +func main() { + clientID := os.Getenv("CLIENT_ID") + aspUrl := os.Getenv("ASP_URL") + orchUrl := os.Getenv("ORCHESTRATOR_URL") + explorerUrl := os.Getenv("EXPLORER_URL") + if clientID == "" { + log.Fatal("CLIENT_ID environment variable is required") + } + if aspUrl == "" { + log.Fatal("ASP_URL environment variable is required") + } + if orchUrl == "" { + log.Fatal("ORCHESTRATOR_URL environment variable is required") + } + orchestratorUrl = orchUrl + if explorerUrl == "" { + log.Fatal("EXPLORER_URL environment variable is required") + } + + client := &Client{ + ID: clientID, + } + + // Initialize context for cancellation + client.ctx, client.cancel = context.WithCancel(context.Background()) + + // Set up ArkClient + if err := client.setupArkClient(explorerUrl, aspUrl); err != nil { + log.Fatalf("Failed to set up client: %v", err) + } + + // Start HTTP server + go client.startServer() + + time.Sleep(20 * time.Second) + + // Send address to orchestrator + if err := client.sendAddress(); err != nil { + log.Fatalf("Failed to send address to orchestrator: %v", err) + } + + // Wait for shutdown signal + client.handleSignals() +} + +type Client struct { + ID string + ArkClient arksdk.ArkClient + ctx context.Context + cancel context.CancelFunc + Address string +} + +func (c *Client) setupArkClient(explorerUrl, aspUrl string) error { + appDataStore, err := store.NewStore(store.Config{ + ConfigStoreType: types.InMemoryStore, + }) + if err != nil { + return fmt.Errorf("failed to create store: %s", err) + } + + client, err := arksdk.NewCovenantlessClient(appDataStore) + if err != nil { + return fmt.Errorf("failed to setup ark client: %s", err) + } + + ctx := context.Background() + if err := client.Init(ctx, arksdk.InitArgs{ + WalletType: arksdk.SingleKeyWallet, + ClientType: arksdk.GrpcClient, + AspUrl: aspUrl, + Password: "password", + ExplorerURL: fmt.Sprintf("http://%s", explorerUrl), + }); err != nil { + return fmt.Errorf("failed to initialize wallet: %s", err) + } + + if err := client.Unlock(ctx, "password"); err != nil { + return fmt.Errorf("failed to unlock wallet: %s", err) + } + + log.Infof("Client %s initialized ArkClient", c.ID) + c.ArkClient = client + return nil +} + +func (c *Client) startServer() { + mux := http.NewServeMux() + mux.HandleFunc("/onboard", c.onboardHandler) + mux.HandleFunc("/sendAsync", c.sendAsyncHandler) + mux.HandleFunc("/claim", c.claimHandler) + mux.HandleFunc("/balance", c.balanceHandler) + + server := &http.Server{ + Addr: ":" + clientPort, + Handler: mux, + } + + go func() { + <-c.ctx.Done() + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + server.Shutdown(shutdownCtx) + }() + + log.Infof("Client %s starting HTTP server on port %s", c.ID, clientPort) + if err := server.ListenAndServe(); err != http.ErrServerClosed { + log.Fatalf("Client server failed: %v", err) + } +} + +func (c *Client) sendAddress() error { + ctx := context.Background() + offchainAddress, _, err := c.ArkClient.Receive(ctx) + if err != nil { + return fmt.Errorf("failed to get address: %v", err) + } + c.Address = offchainAddress + + payload := struct { + ClientID string `json:"client_id"` + Address string `json:"address"` + }{ + ClientID: c.ID, + Address: offchainAddress, + } + + jsonData, err := json.Marshal(payload) + if err != nil { + return err + } + + resp, err := http.Post(fmt.Sprintf("http://%s/address", orchestratorUrl), + "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var body map[string]interface{} + _ = json.NewDecoder(resp.Body).Decode(&body) + return fmt.Errorf("failed to register address: status=%d, body=%v", resp.StatusCode, body) + } + + log.Infof("Client %s registered address %s with orchestrator", c.ID, offchainAddress) + return nil +} + +func (c *Client) onboardHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + Amount float64 `json:"amount"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + if err := c.onboard(orchestratorUrl, req.Amount); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (c *Client) sendAsyncHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + Amount float64 `json:"amount"` + ToAddress string `json:"to_address"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + ctx := context.Background() + receivers := []arksdk.Receiver{ + arksdk.NewBitcoinReceiver(req.ToAddress, uint64(req.Amount*1e8)), + } + + _, err := c.ArkClient.SendAsync(ctx, false, receivers) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + logMsg := fmt.Sprintf("Client %s sent async %f BTC to %s", c.ID, req.Amount, req.ToAddress) + log.Infoln(logMsg) + if err := c.sendLogToOrchestrator(logMsg, "Info"); err != nil { + log.Errorf("Failed to send log to orchestrator: %v", err) + } + + w.WriteHeader(http.StatusOK) +} + +func (c *Client) claimHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + if err := c.claim(); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (c *Client) balanceHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + ctx := context.Background() + balance, err := c.ArkClient.Balance(ctx, false) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(balance) +} + +func (c *Client) onboard(orchestratorUrl string, amount float64) error { + ctx := context.Background() + + _, boardingAddress, err := c.ArkClient.Receive(ctx) + if err != nil { + return err + } + + amountStr := fmt.Sprintf("%.8f", amount) + + payload := struct { + Address string `json:"address"` + Amount string `json:"amount"` + }{ + Address: boardingAddress, + Amount: amountStr, + } + + jsonData, err := json.Marshal(payload) + if err != nil { + return err + } + + resp, err := http.Post(fmt.Sprintf("http://%s/faucet", orchestratorUrl), + "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var body map[string]interface{} + _ = json.NewDecoder(resp.Body).Decode(&body) + return fmt.Errorf("failed to faucet address: status=%d, body=%v", resp.StatusCode, body) + } + + // Wait for the funds to be confirmed (simulate delay) + time.Sleep(5 * time.Second) + + _, err = c.ArkClient.Settle(ctx) + if err != nil { + return fmt.Errorf("client %s failed to settle onboard: %v", c.ID, err) + } + + logMsg := fmt.Sprintf("Client %s onboarded successfully with %f BTC", c.ID, amount) + log.Infoln(logMsg) + if err := c.sendLogToOrchestrator(logMsg, "Info"); err != nil { + log.Errorf("Failed to send log to orchestrator: %v", err) + } + + return nil +} + +func (c *Client) claim() error { + ctx := context.Background() + + txID, err := c.ArkClient.Settle(ctx) + if err != nil { + return fmt.Errorf("client %s failed to claim funds: %v", c.ID, err) + } + + logMsg := fmt.Sprintf("Client %s claimed funds, txID: %v", c.ID, txID) + log.Infoln(logMsg) + if err := c.sendLogToOrchestrator(logMsg, "Info"); err != nil { + log.Errorf("Failed to send log to orchestrator: %v", err) + } + return nil +} + +func (c *Client) handleSignals() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + <-sigs + log.Info("Shutting down client...") + c.cancel() +} + +func (c *Client) sendLogToOrchestrator(message, logType string) error { + payload := struct { + ClientID string `json:"client_id"` + Type string `json:"type"` + Message string `json:"message"` + }{ + ClientID: c.ID, + Type: logType, + Message: message, + } + + jsonData, err := json.Marshal(payload) + if err != nil { + return err + } + + resp, err := http.Post(fmt.Sprintf("http://%s/log", orchestratorUrl), + "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + var body map[string]interface{} + _ = json.NewDecoder(resp.Body).Decode(&body) + return fmt.Errorf("failed to send log to orchestrator: status=%d, body=%v", resp.StatusCode, body) + } + + return nil +} diff --git a/simulation/remote/infra/cloudformation.yaml b/simulation/remote/infra/cloudformation.yaml new file mode 100644 index 000000000..74a4b7df0 --- /dev/null +++ b/simulation/remote/infra/cloudformation.yaml @@ -0,0 +1,379 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: AWS CloudFormation Template for Orchestrator and Clients Infrastructure with Simplifications + +Parameters: + VpcCIDR: + Type: String + Default: 10.0.0.0/16 + Description: CIDR block for the VPC + SubnetCIDR: + Type: String + Default: 10.0.1.0/24 + Description: CIDR block for the subnet + AvailabilityZone: + Type: String + Default: eu-central-1a + Description: Availability Zone + KeyPairName: + Type: AWS::EC2::KeyPair::KeyName + Description: Name of an existing EC2 KeyPair to enable SSH access + InstanceType: + Type: String + Default: t2.large + AllowedValues: + - t2.micro + - t2.small + - t2.medium + - t2.large + Description: EC2 Instance Type + AMI: + Type: AWS::EC2::Image::Id + Default: ami-0084a47cc718c111a + Description: Ubuntu Server 24.04 in eu-central-1 + OrchestratorPort: + Type: Number + Default: 9000 + Description: Port on which the orchestrator listens + AspPort: + Type: Number + Default: 7070 + Description: Port on which the ASP listens + GitRepoURL: + Type: String + Description: URL of the Git repository to clone + GitBranch: + Type: String + Default: master + Description: Git branch to checkout (optional) + GoVersion: + Type: String + Default: "1.23.1" + Description: Version of Go to install + +Resources: + + ### VPC and Networking ### + + VPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref VpcCIDR + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: OrchestratorVPC + + Subnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + CidrBlock: !Ref SubnetCIDR + AvailabilityZone: !Ref AvailabilityZone + MapPublicIpOnLaunch: true + Tags: + - Key: Name + Value: OrchestratorSubnet + + InternetGateway: + Type: AWS::EC2::InternetGateway + Properties: + Tags: + - Key: Name + Value: OrchestratorInternetGateway + + AttachGateway: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref VPC + InternetGatewayId: !Ref InternetGateway + + RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref VPC + Tags: + - Key: Name + Value: OrchestratorRouteTable + + PublicRoute: + Type: AWS::EC2::Route + DependsOn: AttachGateway + Properties: + RouteTableId: !Ref RouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + + SubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref Subnet + RouteTableId: !Ref RouteTable + + ### Security Group ### + + SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security Group for Orchestrator EC2 Instance and Clients + VpcId: !Ref VPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: !Ref OrchestratorPort + ToPort: !Ref OrchestratorPort + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: !Ref AspPort + ToPort: !Ref AspPort + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 3000 + ToPort: 3000 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + SecurityGroupEgress: + - IpProtocol: -1 + CidrIp: 0.0.0.0/0 + Tags: + - Key: Name + Value: OrchestratorSecurityGroup + + ### ECR Repository ### + + ECRRepository: + Type: AWS::ECR::Repository + Properties: + RepositoryName: ark-client-repo + + ### IAM Role for Orchestrator EC2 Instance ### + + OrchestratorInstanceRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + Path: "/" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonECS_FullAccess + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + - arn:aws:iam::aws:policy/AmazonS3FullAccess + + OrchestratorInstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Path: "/" + Roles: + - !Ref OrchestratorInstanceRole + + ### EC2 Instance for Orchestrator and ASP ### + + OrchestratorInstance: + Type: AWS::EC2::Instance + Properties: + InstanceType: !Ref InstanceType + IamInstanceProfile: !Ref OrchestratorInstanceProfile + KeyName: !Ref KeyPairName + ImageId: !Ref AMI + BlockDeviceMappings: + - DeviceName: /dev/sda1 + Ebs: + VolumeSize: 100 + VolumeType: gp3 # Optional, can specify desired volume type + DeleteOnTermination: true + NetworkInterfaces: + - DeviceIndex: 0 + SubnetId: !Ref Subnet + AssociatePublicIpAddress: true + GroupSet: + - !Ref SecurityGroup + Tags: + - Key: Name + Value: OrchestratorInstance + UserData: + Fn::Base64: !Sub + - | + #!/bin/bash + # set -e # Commented out for debugging + + echo "Updating package list..." + apt-get update -y + + echo "Installing Docker..." + apt-get install -y docker.io + systemctl start docker + systemctl enable docker + usermod -aG docker ubuntu + + echo "Installing Docker Compose..." + curl -L "https://github.com/docker/compose/releases/download/v2.29.7/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + + echo "Installing Go..." + wget https://dl.google.com/go/go${GoVersion}.linux-amd64.tar.gz + tar -C /usr/local -xzf go${GoVersion}.linux-amd64.tar.gz + ln -s /usr/local/go/bin/go /usr/local/bin/go + echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile + source /etc/profile + + echo "Installing build tools and utilities..." + apt-get install -y build-essential curl jq git unzip + + echo "Installing AWS CLI v2..." + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install + + echo "Installing Nigiri..." + curl https://getnigiri.vulpem.com | sudo bash + + echo "Cloning the repository..." + cd /home/ubuntu + REPO_URL="${GitRepoURL}" + BRANCH="${GitBranch}" + echo "REPO_URL is: $REPO_URL" + echo "BRANCH is: $BRANCH" + if [ -n "$BRANCH" ] && [ "$BRANCH" != "master" ]; then + git clone -b $BRANCH $REPO_URL + else + git clone $REPO_URL + fi + + chown -R ubuntu:ubuntu /home/ubuntu + + echo "Switching to ubuntu user..." + sudo -u ubuntu bash << EOF + + echo "Inside ubuntu user context..." + export AWS_REGION="${AWS::Region}" + AWS_ACCOUNT_ID=\$(aws sts get-caller-identity --query Account --output text) + export AWS_ACCOUNT_ID + export SUBNET_IDS="${Subnet}" + export SECURITY_GROUP_IDS="${SecurityGroup}" + echo "AWS_REGION is: \$AWS_REGION" + echo "AWS_ACCOUNT_ID is: \$AWS_ACCOUNT_ID" + echo "SUBNET_IDS is: \$SUBNET_IDS" + echo "SECURITY_GROUP_IDS is: \$SECURITY_GROUP_IDS" + + cd /home/ubuntu/$(basename $REPO_URL .git)/simulation + + echo "Running nigiri..." + nigiri start + + echo "Running make push-to-ecr..." + cd simulation & make push-to-ecr AWS_ACCOUNT_ID=\$AWS_ACCOUNT_ID AWS_REGION=\$AWS_REGION + + EOF + + echo "Allowing port 9000..." + sudo ufw allow 9000/tcp + - Subnet: !Ref Subnet + SecurityGroup: !Ref SecurityGroup + + ### CloudWatch Logs Group ### + + ClientLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: /ecs/ClientContainer + RetentionInDays: 7 # Adjust as needed + + ### ECS Cluster and Task Definition ### + + ECSCluster: + Type: AWS::ECS::Cluster + Properties: + ClusterName: OrchestratorCluster + + ECSTaskExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - ecs-tasks.amazonaws.com + Action: + - 'sts:AssumeRole' + Path: "/" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy + Policies: + - PolicyName: AllowLogs + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - logs:CreateLogStream + - logs:PutLogEvents + Resource: "arn:aws:logs:*:*:log-group:/ecs/ClientContainer:*" + + ECSTaskDefinition: + Type: AWS::ECS::TaskDefinition + Properties: + Family: ClientTaskDefinition + NetworkMode: awsvpc + RequiresCompatibilities: + - FARGATE + Cpu: '1024' + Memory: '2048' + ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn + TaskRoleArn: !GetAtt ECSTaskExecutionRole.Arn + ContainerDefinitions: + - Name: ClientContainer + Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/ark-client-repo:latest" + Essential: true + Environment: + - Name: ASP_URL + Value: !Sub "${OrchestratorInstance.PrivateIp}:${AspPort}" + - Name: ORCHESTRATOR_URL + Value: !Sub "${OrchestratorInstance.PrivateIp}:${OrchestratorPort}" + - Name: EXPLORER_URL + Value: !Sub "${OrchestratorInstance.PrivateIp}:3000" + LogConfiguration: + LogDriver: awslogs + Options: + awslogs-group: /ecs/ClientContainer + awslogs-region: !Ref AWS::Region + awslogs-stream-prefix: ecs + +Outputs: + OrchestratorInstanceID: + Description: Instance ID of the Orchestrator EC2 instance + Value: !Ref OrchestratorInstance + + OrchestratorPrivateIP: + Description: Private IP of the Orchestrator EC2 instance + Value: !GetAtt OrchestratorInstance.PrivateIp + + OrchestratorPublicIP: + Description: Public IP of the Orchestrator EC2 instance + Value: !GetAtt OrchestratorInstance.PublicIp + + VPCID: + Description: VPC ID + Value: !Ref VPC + + SubnetID: + Description: Subnet ID + Value: !Ref Subnet + + SecurityGroupID: + Description: Security Group ID + Value: !Ref SecurityGroup + + ECRRepositoryURI: + Description: URI of the ECR Repository + Value: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/ark-client-repo" diff --git a/simulation/remote/orchestrator/main.go b/simulation/remote/orchestrator/main.go new file mode 100644 index 000000000..21f0d5434 --- /dev/null +++ b/simulation/remote/orchestrator/main.go @@ -0,0 +1,829 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + "github.com/xeipuuv/gojsonschema" + "io" + "net/http" + "net/url" + "os" + "strings" + "sync" + "time" + + utils "github.com/ark-network/ark/server/test/e2e" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/ecs" + ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" + log "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" + "sigs.k8s.io/yaml" +) + +const ( + composePath = "../../../docker-compose.clark.regtest.yml" + schemaPath = "../../schema.yaml" + simulationPath = "../../simulation.yaml" + defaultAspUrl = "localhost:7070" + clientPort = "9000" // All clients listen on this port +) + +type ClientInfo struct { + ID string + Address string + TaskARN string + IPAddress string +} + +var ( + clients = make(map[string]*ClientInfo) + clientsMu sync.Mutex +) + +func main() { + simFile := flag.String("sim", simulationPath, "Path to simulation YAML file") + serverAddress := flag.String("server", "", "Orchestrator server address") + flag.Parse() + + subnetIDsEnv := os.Getenv("SUBNET_IDS") + securityGroupIDsEnv := os.Getenv("SECURITY_GROUP_IDS") + + if subnetIDsEnv == "" { + log.Fatalf("SUBNET_IDS environment variable is not set") + } + if securityGroupIDsEnv == "" { + log.Fatalf("SECURITY_GROUP_IDS environment variable is not set") + } + + simulation, err := loadAndValidateSimulation(*simFile) + if err != nil { + log.Fatalf("Error loading simulation config: %v", err) + } + + aspUrl := *serverAddress + startedLocally := false + if aspUrl == "" { + if err := startAspLocally(*simulation); err != nil { + log.Fatalf("Error starting ASP server: %v", err) + } + aspUrl = defaultAspUrl + startedLocally = true + } + + if startedLocally { + defer func() { + log.Info("Stopping ASP server...") + if _, err := utils.RunCommand("docker-compose", "-f", composePath, "down", "-v"); err != nil { + log.Errorf("Error stopping ASP server: %v", err) + } + }() + } + + aspUrlParsed := &url.URL{ + Scheme: "http", + Host: aspUrl, + } + + if err := utils.SetupServerWalletCovenantless(aspUrlParsed.String(), simulation.Server.InitialFunding); err != nil { + log.Fatal(err) + } + + // Start the orchestrator HTTP server + go startServer() + + // Start clients + err = startClients(subnetIDsEnv, securityGroupIDsEnv, simulation.Clients) + if err != nil { + log.Fatalf("Error starting clients: %v", err) + } + + // Wait for clients to send their addresses + clientIDs := make([]string, len(simulation.Clients)) + for i, client := range simulation.Clients { + clientIDs[i] = client.ID + } + waitForClientsToSendAddresses(clientIDs) + + go func() { + for { + if err := utils.GenerateBlock(); err != nil { + log.Fatal(err) + } + time.Sleep(1 * time.Second) + } + }() + + // Execute the simulation + executeSimulation(simulation) + + // Stop clients after simulation + stopClients() +} + +func startServer() { + http.HandleFunc("/address", addressHandler) + http.HandleFunc("/faucet", faucetHandler) + http.HandleFunc("/log", logHandler) + log.Infoln("Orchestrator HTTP server running on port 9000") + if err := http.ListenAndServe(":9000", nil); err != nil { + log.Fatalf("Orchestrator server failed: %v", err) + } +} + +func addressHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + ClientID string `json:"client_id"` + Address string `json:"address"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Errorf("Error decoding address request: %v", err) + return + } + + clientsMu.Lock() + if client, exists := clients[req.ClientID]; exists { + client.Address = req.Address + log.Infof("Registered address for client %s: %s", req.ClientID, req.Address) + } else { + log.Warnf("Received address for unknown client: %s", req.ClientID) + } + clientsMu.Unlock() + + w.WriteHeader(http.StatusOK) +} + +func faucetHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + Address string `json:"address"` + Amount string `json:"amount"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Errorf("Error decoding faucet request: %v", err) + return + } + + if _, err := utils.RunCommand("nigiri", "faucet", req.Address, req.Amount); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + log.Errorf("Error running faucet command: %v", err) + return + } + + log.Infof("Faucet sent %s to %s", req.Amount, req.Address) + + w.WriteHeader(http.StatusOK) +} + +func logHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var req struct { + ClientID string `json:"client_id"` + Type string `json:"type"` + Message string `json:"message"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Errorf("Error decoding log request: %v", err) + return + } + + logMsg := fmt.Sprintf("Client %s: %s", req.ClientID, req.Message) + if req.Type == "Error" { + log.Warnln(logMsg) + } + if req.Type == "Info" { + log.Infoln(logMsg) + } + + w.WriteHeader(http.StatusOK) +} + +func executeSimulation(simulation *Simulation) { + for _, round := range simulation.Rounds { + waitRound := false + log.Infof("Executing Round %d at %s", round.Number, time.Now().Format("2006-01-02 15:04:05")) + var wg sync.WaitGroup + for clientID, actions := range round.Actions { + wg.Add(1) + go func(clientID string, actions []ActionMap) { + defer wg.Done() + for _, action := range actions { + actionType, ok := action["type"].(string) + if !ok { + log.Infof("Invalid action type for client %s", clientID) + return + } + + if actionType == "Onboard" || actionType == "Claim" || actionType == "CollaborativeRedeem" { + waitRound = true + } + + if err := executeClientAction(clientID, actionType, action); err != nil { + log.Warnf("Error executing %s for client %s: %v", actionType, clientID, err) + } + } + }(clientID, actions) + } + wg.Wait() + + sleepTime := 2 * time.Second + if waitRound { + sleepTime = time.Duration(simulation.Server.RoundInterval)*time.Second + 2*time.Second + } + log.Infof("Waiting for %s before starting next round", sleepTime) + time.Sleep(sleepTime) + log.Infof("Round %d completed at %s", round.Number, time.Now().Format("2006-01-02 15:04:05")) + } +} + +func executeClientAction(clientID string, actionType string, action ActionMap) error { + clientsMu.Lock() + client, exists := clients[clientID] + clientsMu.Unlock() + + if !exists { + return fmt.Errorf("client %s not found", clientID) + } + + clientURL := fmt.Sprintf("http://%s:%s", client.IPAddress, clientPort) + + switch actionType { + case "Onboard": + amount, _ := action["amount"].(float64) + return executeOnboard(clientURL, amount) + case "SendAsync": + amount, _ := action["amount"].(float64) + toClientID, _ := action["to"].(string) + toAddress, err := getClientAddress(toClientID) + if err != nil { + return err + } + return executeSendAsync(clientURL, amount, toAddress) + case "Claim": + return executeClaim(clientURL) + default: + return fmt.Errorf("unknown action type: %s", actionType) + } +} + +func getClientAddress(clientID string) (string, error) { + clientsMu.Lock() + defer clientsMu.Unlock() + + client, exists := clients[clientID] + if !exists { + return "", fmt.Errorf("client %s not found", clientID) + } + if client.Address == "" { + return "", fmt.Errorf("address for client %s not available", clientID) + } + return client.Address, nil +} + +func executeOnboard(clientURL string, amount float64) error { + payload := map[string]float64{"amount": amount} + return sendRequest(clientURL+"/onboard", payload) +} + +func executeSendAsync(clientURL string, amount float64, toAddress string) error { + payload := map[string]interface{}{ + "amount": amount, + "to_address": toAddress, + } + return sendRequest(clientURL+"/sendAsync", payload) +} + +func executeClaim(clientURL string) error { + return sendRequest(clientURL+"/claim", nil) +} + +func sendRequest(url string, payload interface{}) error { + var jsonData []byte + var err error + if payload != nil { + jsonData, err = json.Marshal(payload) + if err != nil { + return err + } + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + return fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(body)) + } + + return nil +} + +// startClients launches each client as an AWS Fargate task. +func startClients(subnetIDsEnv, securityGroupIDsEnv string, clientConfigs []ClientConfig) error { + awsRegion := "eu-central-1" + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(awsRegion), + ) + if err != nil { + return fmt.Errorf("unable to load AWS SDK config: %v", err) + } + + ecsClient := ecs.NewFromConfig(cfg) + + // Split the IDs into slices + subnetIDs := strings.Split(subnetIDsEnv, ",") + securityGroupIDs := strings.Split(securityGroupIDsEnv, ",") + + clusterName := "OrchestratorCluster" + taskDefinition := "ClientTaskDefinition" + + // Log task definition details + describeTaskDefInput := &ecs.DescribeTaskDefinitionInput{ + TaskDefinition: aws.String(taskDefinition), + } + + taskDefDetails, err := ecsClient.DescribeTaskDefinition(context.TODO(), describeTaskDefInput) + if err != nil { + log.Warnf("Failed to get task definition details: %v", err) + } else { + log.Infof("Task Definition details: %+v", taskDefDetails.TaskDefinition) + } + + // Create context with timeout + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + + // Function to wait for task to be running + waitForTaskRunning := func(taskArn string, clientID string) error { + for { + select { + case <-ctx.Done(): + return fmt.Errorf("timeout waiting for task to start") + default: + describeTasksInput := &ecs.DescribeTasksInput{ + Cluster: aws.String(clusterName), + Tasks: []string{taskArn}, + } + + result, err := ecsClient.DescribeTasks(context.TODO(), describeTasksInput) + if err != nil { + return fmt.Errorf("failed to describe task: %v", err) + } + + if len(result.Tasks) > 0 { + task := result.Tasks[0] + status := aws.ToString(task.LastStatus) + + switch status { + case "RUNNING": + return nil + case "STOPPED": + // Get detailed error information + var errorDetail string + if task.StoppedReason != nil { + errorDetail = *task.StoppedReason + } + + // Check container status for more details + for _, container := range task.Containers { + if container.Reason != nil { + errorDetail += fmt.Sprintf(" Container error: %s", *container.Reason) + } + } + + return fmt.Errorf("task stopped: %s", errorDetail) + case "PENDING", "PROVISIONING": + log.Infof("Client %s task status: %s", clientID, status) + default: + log.Infof("Client %s unexpected status: %s", clientID, status) + } + } + + time.Sleep(5 * time.Second) + } + } + } + + var ( + tasksMu sync.Mutex + tasks []struct { + ClientID string + TaskArn string + } + ) + g := new(errgroup.Group) + for _, client := range clientConfigs { + client := client // Capture range variable + g.Go(func() error { + clientID := client.ID + + // Prepare the overrides for the container + containerOverrides := ecsTypes.ContainerOverride{ + Name: aws.String("ClientContainer"), + Environment: []ecsTypes.KeyValuePair{ + { + Name: aws.String("CLIENT_ID"), + Value: aws.String(clientID), + }, + }, + } + + runTaskInput := &ecs.RunTaskInput{ + Cluster: aws.String(clusterName), + LaunchType: ecsTypes.LaunchTypeFargate, + TaskDefinition: aws.String(taskDefinition), + NetworkConfiguration: &ecsTypes.NetworkConfiguration{ + AwsvpcConfiguration: &ecsTypes.AwsVpcConfiguration{ + Subnets: subnetIDs, + SecurityGroups: securityGroupIDs, + AssignPublicIp: ecsTypes.AssignPublicIpEnabled, + }, + }, + Overrides: &ecsTypes.TaskOverride{ + ContainerOverrides: []ecsTypes.ContainerOverride{containerOverrides}, + }, + } + + var result *ecs.RunTaskOutput + backoff := 2 * time.Second + for i := 0; i < 5; i++ { + result, err = ecsClient.RunTask(context.TODO(), runTaskInput) + if err != nil { + return fmt.Errorf("failed to start client %s: %v", clientID, err) + } + + if len(result.Failures) > 0 { + for _, failure := range result.Failures { + log.Warnf( + "Failed to start client %s: %s, %s", + clientID, + aws.ToString(failure.Reason), + aws.ToString(failure.Detail), + ) + } + time.Sleep(backoff) + backoff *= 2 + continue + } + + if len(result.Tasks) > 0 { + break + } + log.Warnf("No tasks created for client %s, retrying... (%d/5)", clientID, i+1) + time.Sleep(backoff) + backoff *= 2 + } + + if len(result.Tasks) == 0 { + return fmt.Errorf("no tasks created for client %s after 5 attempts", clientID) + } + + taskArn := *result.Tasks[0].TaskArn + log.Infof("Started client %s with task ARN: %s", clientID, taskArn) + + // Store task information + tasksMu.Lock() + tasks = append(tasks, struct { + ClientID string + TaskArn string + }{ + ClientID: clientID, + TaskArn: taskArn, + }) + tasksMu.Unlock() + + // Wait for task to be running + if err := waitForTaskRunning(taskArn, clientID); err != nil { + return fmt.Errorf("client %s failed to start: %v", clientID, err) + } + + ip, err := waitForTaskRunningAndGetIP(ctx, ecsClient, clusterName, taskArn) + if err != nil { + return fmt.Errorf("error waiting for client %s task: %v", clientID, err) + } + + clientsMu.Lock() + clients[clientID] = &ClientInfo{ + ID: clientID, + TaskARN: taskArn, + IPAddress: ip, + } + clientsMu.Unlock() + + log.Infof("Client %s successfully started and running", clientID) + return nil + }) + } + + // Wait for all tasks to be started + if err := g.Wait(); err != nil { + log.Errorf("Error starting clients: %v", err) + // If any error occurred during task startup, stop any started tasks + stopClients() + return err + } + + log.Infof("All clients started successfully") + + // Monitor task health periodically + go func() { + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + tasksMu.Lock() + currentTasks := make([]struct { + ClientID string + TaskArn string + }, len(tasks)) + copy(currentTasks, tasks) + tasksMu.Unlock() + + for _, task := range currentTasks { + describeTasksInput := &ecs.DescribeTasksInput{ + Cluster: aws.String(clusterName), + Tasks: []string{task.TaskArn}, + } + + result, err := ecsClient.DescribeTasks(context.TODO(), describeTasksInput) + if err != nil { + log.Warnf("Failed to describe task for client %s: %v", task.ClientID, err) + continue + } + + if len(result.Tasks) > 0 { + status := aws.ToString(result.Tasks[0].LastStatus) + if status == "STOPPED" { + log.Warnf("Client %s task stopped unexpectedly", task.ClientID) + } + } + } + } + } + }() + + return nil +} + +func waitForTaskRunningAndGetIP(ctx context.Context, ecsClient *ecs.Client, clusterName, taskArn string) (string, error) { + for { + select { + case <-ctx.Done(): + return "", fmt.Errorf("timeout waiting for task to start") + default: + describeTasksInput := &ecs.DescribeTasksInput{ + Cluster: aws.String(clusterName), + Tasks: []string{taskArn}, + } + + result, err := ecsClient.DescribeTasks(ctx, describeTasksInput) + if err != nil { + return "", fmt.Errorf("failed to describe task: %v", err) + } + + if len(result.Tasks) > 0 { + task := result.Tasks[0] + status := aws.ToString(task.LastStatus) + + switch status { + case "RUNNING": + if task.TaskArn != nil && len(task.Attachments) > 0 { + for _, attachment := range task.Attachments { + if aws.ToString(attachment.Type) == "ElasticNetworkInterface" { + for _, detail := range attachment.Details { + if aws.ToString(detail.Name) == "privateIPv4Address" { + return aws.ToString(detail.Value), nil + } + } + } + } + } + return "", fmt.Errorf("could not find IP address for task") + case "STOPPED": + var errorDetail string + if task.StoppedReason != nil { + errorDetail = *task.StoppedReason + } + for _, container := range task.Containers { + if container.Reason != nil { + errorDetail += fmt.Sprintf(" Container error: %s", *container.Reason) + } + } + return "", fmt.Errorf("task stopped: %s", errorDetail) + } + } + + time.Sleep(5 * time.Second) + } + } +} + +func waitForClientsToSendAddresses(clientIDs []string) { + log.Info("Waiting for clients to send addresses...") + timeout := time.After(2 * time.Minute) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + for { + select { + case <-timeout: + log.Fatal("Timeout waiting for client addresses") + case <-ticker.C: + allReceived := true + clientsMu.Lock() + for _, clientID := range clientIDs { + client, exists := clients[clientID] + if !exists || client.Address == "" { + allReceived = false + break + } + } + clientsMu.Unlock() + + if allReceived { + log.Info("All clients have sent their addresses") + return + } + } + } +} + +func stopClients() { + awsRegion := "eu-central-1" + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(awsRegion), + ) + if err != nil { + log.Errorf("Unable to load AWS SDK config: %v", err) + return + } + + ecsClient := ecs.NewFromConfig(cfg) + + clientsMu.Lock() + defer clientsMu.Unlock() + + for _, client := range clients { + if client.TaskARN != "" { + _, err := ecsClient.StopTask(context.TODO(), &ecs.StopTaskInput{ + Cluster: aws.String("OrchestratorCluster"), + Task: aws.String(client.TaskARN), + }) + if err != nil { + log.Errorf("Failed to stop client %s task: %v", client.ID, err) + } else { + log.Infof("Stopped client %s task", client.ID) + } + } + } +} + +// loadAndValidateSimulation reads and validates the simulation YAML file. +func loadAndValidateSimulation(simFile string) (*Simulation, error) { + // Read and convert the schema YAML file to JSON + schemaBytes, err := os.ReadFile(schemaPath) + if err != nil { + return nil, fmt.Errorf("error reading schema file: %v", err) + } + + schemaJSON, err := yaml.YAMLToJSON(schemaBytes) + if err != nil { + return nil, fmt.Errorf("error converting schema YAML to JSON: %v", err) + } + + // Read and convert the simulation YAML file to JSON + simBytes, err := os.ReadFile(simFile) + if err != nil { + return nil, fmt.Errorf("error reading simulation file: %v", err) + } + + simJSON, err := yaml.YAMLToJSON(simBytes) + if err != nil { + return nil, fmt.Errorf("error converting simulation YAML to JSON: %v", err) + } + + // Create JSON loaders for the schema and the document + schemaLoader := gojsonschema.NewBytesLoader(schemaJSON) + documentLoader := gojsonschema.NewBytesLoader(simJSON) + + // Validate the simulation JSON against the schema JSON + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil { + return nil, fmt.Errorf("error validating simulation: %v", err) + } + + if !result.Valid() { + // Collect error messages + var errorMessages string + for _, desc := range result.Errors() { + errorMessages += fmt.Sprintf("- %s\n", desc) + } + return nil, fmt.Errorf("the simulation is not valid:\n%s", errorMessages) + } + + // Unmarshal the simulation YAML into the Simulation struct + var sim Simulation + err = json.Unmarshal(simJSON, &sim) + if err != nil { + return nil, fmt.Errorf("error parsing simulation YAML: %v", err) + } + + return &sim, nil +} + +// startAspLocally starts ASP server locally. +func startAspLocally(simulation Simulation) error { + log.Infof("Simulation Version: %s\n", simulation.Version) + log.Infof("ASP Network: %s\n", simulation.Server.Network) + log.Infof("Number of Clients: %d\n", len(simulation.Clients)) + log.Infof("Number of Rounds: %d\n", len(simulation.Rounds)) + + roundLifetime := fmt.Sprintf("ARK_ROUND_INTERVAL=%d", simulation.Server.RoundInterval) + tmpfile, err := os.CreateTemp("", "docker-env") + if err != nil { + return err + } + defer os.Remove(tmpfile.Name()) // clean up + + if _, err := tmpfile.Write([]byte(roundLifetime)); err != nil { + return err + } + if err := tmpfile.Close(); err != nil { + return err + } + + log.Infof("Start building ARKD docker container ...") + if _, err := utils.RunCommand("docker-compose", "-f", composePath, "--env-file", tmpfile.Name(), "up", "-d"); err != nil { + return err + } + + time.Sleep(10 * time.Second) + log.Infoln("ASP running...") + + return nil +} + +// ClientConfig holds configuration for a client. +type ClientConfig struct { + ID string `json:"id"` + Name string `json:"name"` +} + +// ActionMap represents an action in the simulation rounds. +type ActionMap map[string]interface{} + +// Round represents a simulation round. +type Round struct { + Number int `json:"number"` + Actions map[string][]ActionMap `json:"actions"` +} + +// Simulation represents the entire simulation configuration. +type Simulation struct { + Version string `json:"version"` + Server struct { + Network string `json:"network"` + InitialFunding float64 `json:"initial_funding"` + RoundInterval int `json:"round_interval"` + } `yaml:"server"` + Clients []ClientConfig `json:"clients"` + Rounds []Round `json:"rounds"` +} diff --git a/simulation/schema.yaml b/simulation/schema.yaml new file mode 100644 index 000000000..1ece1e94d --- /dev/null +++ b/simulation/schema.yaml @@ -0,0 +1,73 @@ +$schema: "http://json-schema.org/draft-07/schema#" +type: object +required: + - version + - server + - clients + - rounds +properties: + version: + type: string + server: + type: object + required: + - network + - round_interval + properties: + network: + type: string + enum: ["regtest", "testnet"] + round_interval: + type: integer + minimum: 1 + clients: + type: array + items: + type: object + required: + - id + properties: + id: + type: string + name: + type: string + initial_funding: + type: number + minimum: 0 + rounds: + type: array + items: + type: object + required: + - number + - actions + properties: + number: + type: integer + minimum: 1 + actions: + type: object + patternProperties: + "^client_\\d+$": + type: array + items: + type: object + required: + - type + properties: + type: + type: string + enum: + - "Onboard" + - "SendAsync" + - "SendOffchain" + - "SendOnchain" + - "Claim" + - "CollaborativeRedeem" + - "UnilateralExit" + - "Balance" + amount: + type: number + minimum: 0 + to: + type: string diff --git a/simulation/script/build_and_push.sh b/simulation/script/build_and_push.sh new file mode 100755 index 000000000..733e5237f --- /dev/null +++ b/simulation/script/build_and_push.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +usage() { + echo "Usage: $0 -a -r [-e ] [-i ] [-d ] [-c ] [--no-push]" + echo " -a AWS Account ID" + echo " -r AWS Region" + echo " -e ECR Repository Name (default: ark-client-repo)" + echo " -i Docker Image Name (default: arkclient)" + echo " -d Dockerfile Path (default: current directory)" + echo " -c Build Context Path (default: current directory)" + echo " --no-push Skip pushing the Docker image to ECR" + exit 1 +} + +# Default values +ECR_REPOSITORY_NAME="ark-client-repo" +IMAGE_NAME="arkclient" +DOCKERFILE_PATH="." +BUILD_CONTEXT="." +NO_PUSH=false # Default to pushing image + +# Parse command-line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + -a) AWS_ACCOUNT_ID="$2"; shift ;; + -r) AWS_REGION="$2"; shift ;; + -e) ECR_REPOSITORY_NAME="$2"; shift ;; + -i) IMAGE_NAME="$2"; shift ;; + -d) DOCKERFILE_PATH="$2"; shift ;; + -c) BUILD_CONTEXT="$2"; shift ;; + --no-push) NO_PUSH=true ;; + -h|--help) usage ;; + *) usage ;; + esac + shift +done + +# Check if AWS_ACCOUNT_ID and AWS_REGION are set +if [ "$NO_PUSH" = false ]; then + # Check if AWS_ACCOUNT_ID and AWS_REGION are set + if [ -z "$AWS_ACCOUNT_ID" ] || [ -z "$AWS_REGION" ]; then + echo "Error: AWS Account ID and AWS Region are required." + usage + fi +fi + +# Build the Docker image +echo "Building Docker image..." +docker build -t ${IMAGE_NAME} -f ${DOCKERFILE_PATH}/Dockerfile ${BUILD_CONTEXT} + +# Skip pushing if --no-push is set +if [ "$NO_PUSH" = true ]; then + echo "Skipping ECR push as per --no-push flag." + exit 0 +fi + +# Authenticate Docker to ECR +echo "Authenticating Docker to ECR..." +aws ecr get-login-password --region ${AWS_REGION} | \ +docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com + +# Create ECR repository if it doesn't exist +echo "Checking if ECR repository exists..." +aws ecr describe-repositories --repository-names "${ECR_REPOSITORY_NAME}" --region ${AWS_REGION} > /dev/null 2>&1 || \ +{ + echo "ECR repository doesn't exist. Creating..." + aws ecr create-repository --repository-name "${ECR_REPOSITORY_NAME}" --region ${AWS_REGION} +} + +# Tag the Docker image +echo "Tagging Docker image..." +docker tag ${IMAGE_NAME}:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:latest + +# Push the Docker image to ECR +echo "Pushing Docker image to ECR..." +docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:latest + +echo "Docker image pushed to ECR successfully." diff --git a/simulation/simulation.yaml b/simulation/simulation.yaml new file mode 100644 index 000000000..80dfde6fa --- /dev/null +++ b/simulation/simulation.yaml @@ -0,0 +1,718 @@ +version: "1.0" + +server: + network: "regtest" + initial_funding: 1.0 + round_interval: 25 + +clients: + - id: "client_0" + name: "Client0" + - id: "client_1" + name: "Client1" + - id: "client_2" + name: "Client2" + - id: "client_3" + name: "Client3" + - id: "client_4" + name: "Client4" + - id: "client_5" + name: "Client5" + - id: "client_6" + name: "Client6" + - id: "client_7" + name: "Client7" + - id: "client_8" + name: "Client8" + - id: "client_9" + name: "Client9" + - id: "client_10" + name: "Client10" + - id: "client_11" + name: "Client11" + - id: "client_12" + name: "Client12" + - id: "client_13" + name: "Client13" + - id: "client_14" + name: "Client14" + - id: "client_15" + name: "Client15" + - id: "client_16" + name: "Client16" + - id: "client_17" + name: "Client17" + - id: "client_18" + name: "Client18" + - id: "client_19" + name: "Client19" + - id: "client_20" + name: "Client20" + - id: "client_21" + name: "Client21" + - id: "client_22" + name: "Client22" + - id: "client_23" + name: "Client23" + - id: "client_24" + name: "Client24" + - id: "client_25" + name: "Client25" + - id: "client_26" + name: "Client26" + - id: "client_27" + name: "Client27" + - id: "client_28" + name: "Client28" + - id: "client_29" + name: "Client29" + - id: "client_30" + name: "Client30" + - id: "client_31" + name: "Client31" + - id: "client_32" + name: "Client32" + - id: "client_33" + name: "Client33" + - id: "client_34" + name: "Client34" + - id: "client_35" + name: "Client35" + - id: "client_36" + name: "Client36" + - id: "client_37" + name: "Client37" + - id: "client_38" + name: "Client38" + - id: "client_39" + name: "Client39" + - id: "client_40" + name: "Client40" + - id: "client_41" + name: "Client41" + - id: "client_42" + name: "Client42" + - id: "client_43" + name: "Client43" + - id: "client_44" + name: "Client44" + - id: "client_45" + name: "Client45" + - id: "client_46" + name: "Client46" + - id: "client_47" + name: "Client47" + - id: "client_48" + name: "Client48" + - id: "client_49" + name: "Client49" + - id: "client_50" + name: "Client50" + - id: "client_51" + name: "Client51" + - id: "client_52" + name: "Client52" + - id: "client_53" + name: "Client53" + - id: "client_54" + name: "Client54" + - id: "client_55" + name: "Client55" + - id: "client_56" + name: "Client56" + - id: "client_57" + name: "Client57" + - id: "client_58" + name: "Client58" + - id: "client_59" + name: "Client59" + - id: "client_60" + name: "Client60" + - id: "client_61" + name: "Client61" + - id: "client_62" + name: "Client62" + - id: "client_63" + name: "Client63" + - id: "client_64" + name: "Client64" + - id: "client_65" + name: "Client65" + - id: "client_66" + name: "Client66" + - id: "client_67" + name: "Client67" + - id: "client_68" + name: "Client68" + - id: "client_69" + name: "Client69" + - id: "client_70" + name: "Client70" + - id: "client_71" + name: "Client71" + - id: "client_72" + name: "Client72" + - id: "client_73" + name: "Client73" + - id: "client_74" + name: "Client74" + - id: "client_75" + name: "Client75" + - id: "client_76" + name: "Client76" + - id: "client_77" + name: "Client77" + - id: "client_78" + name: "Client78" + - id: "client_79" + name: "Client79" + - id: "client_80" + name: "Client80" + - id: "client_81" + name: "Client81" + - id: "client_82" + name: "Client82" + - id: "client_83" + name: "Client83" + - id: "client_84" + name: "Client84" + - id: "client_85" + name: "Client85" + - id: "client_86" + name: "Client86" + - id: "client_87" + name: "Client87" + - id: "client_88" + name: "Client88" + - id: "client_89" + name: "Client89" + - id: "client_90" + name: "Client90" + - id: "client_91" + name: "Client91" + - id: "client_92" + name: "Client92" + - id: "client_93" + name: "Client93" + - id: "client_94" + name: "Client94" + - id: "client_95" + name: "Client95" + - id: "client_96" + name: "Client96" + - id: "client_97" + name: "Client97" + - id: "client_98" + name: "Client98" + - id: "client_99" + name: "Client99" + +rounds: + - number: 1 + actions: + client_0: + - type: "Onboard" + amount: 0.3 + + - number: 2 + actions: + client_0: + - type: "SendAsync" + amount: 0.002 + to: "client_1" + - type: "SendAsync" + amount: 0.002 + to: "client_2" + - type: "SendAsync" + amount: 0.002 + to: "client_3" + - type: "SendAsync" + amount: 0.002 + to: "client_4" + - type: "SendAsync" + amount: 0.002 + to: "client_5" + - type: "SendAsync" + amount: 0.002 + to: "client_6" + - type: "SendAsync" + amount: 0.002 + to: "client_7" + - type: "SendAsync" + amount: 0.002 + to: "client_8" + - type: "SendAsync" + amount: 0.002 + to: "client_9" + - type: "SendAsync" + amount: 0.002 + to: "client_10" + - type: "SendAsync" + amount: 0.002 + to: "client_11" + - type: "SendAsync" + amount: 0.002 + to: "client_12" + - type: "SendAsync" + amount: 0.002 + to: "client_13" + - type: "SendAsync" + amount: 0.002 + to: "client_14" + - type: "SendAsync" + amount: 0.002 + to: "client_15" + - type: "SendAsync" + amount: 0.002 + to: "client_16" + - type: "SendAsync" + amount: 0.002 + to: "client_17" + - type: "SendAsync" + amount: 0.002 + to: "client_18" + - type: "SendAsync" + amount: 0.002 + to: "client_19" + - type: "SendAsync" + amount: 0.002 + to: "client_20" + - type: "SendAsync" + amount: 0.002 + to: "client_21" + - type: "SendAsync" + amount: 0.002 + to: "client_22" + - type: "SendAsync" + amount: 0.002 + to: "client_23" + - type: "SendAsync" + amount: 0.002 + to: "client_24" + - type: "SendAsync" + amount: 0.002 + to: "client_25" + - type: "SendAsync" + amount: 0.002 + to: "client_26" + - type: "SendAsync" + amount: 0.002 + to: "client_27" + - type: "SendAsync" + amount: 0.002 + to: "client_28" + - type: "SendAsync" + amount: 0.002 + to: "client_29" + - type: "SendAsync" + amount: 0.002 + to: "client_30" + - type: "SendAsync" + amount: 0.002 + to: "client_31" + - type: "SendAsync" + amount: 0.002 + to: "client_32" + - type: "SendAsync" + amount: 0.002 + to: "client_33" + - type: "SendAsync" + amount: 0.002 + to: "client_34" + - type: "SendAsync" + amount: 0.002 + to: "client_35" + - type: "SendAsync" + amount: 0.002 + to: "client_36" + - type: "SendAsync" + amount: 0.002 + to: "client_37" + - type: "SendAsync" + amount: 0.002 + to: "client_38" + - type: "SendAsync" + amount: 0.002 + to: "client_39" + - type: "SendAsync" + amount: 0.002 + to: "client_40" + - type: "SendAsync" + amount: 0.002 + to: "client_41" + - type: "SendAsync" + amount: 0.002 + to: "client_42" + - type: "SendAsync" + amount: 0.002 + to: "client_43" + - type: "SendAsync" + amount: 0.002 + to: "client_44" + - type: "SendAsync" + amount: 0.002 + to: "client_45" + - type: "SendAsync" + amount: 0.002 + to: "client_46" + - type: "SendAsync" + amount: 0.002 + to: "client_47" + - type: "SendAsync" + amount: 0.002 + to: "client_48" + - type: "SendAsync" + amount: 0.002 + to: "client_49" + - type: "SendAsync" + amount: 0.002 + to: "client_50" + - type: "SendAsync" + amount: 0.002 + to: "client_51" + - type: "SendAsync" + amount: 0.002 + to: "client_52" + - type: "SendAsync" + amount: 0.002 + to: "client_53" + - type: "SendAsync" + amount: 0.002 + to: "client_54" + - type: "SendAsync" + amount: 0.002 + to: "client_55" + - type: "SendAsync" + amount: 0.002 + to: "client_56" + - type: "SendAsync" + amount: 0.002 + to: "client_57" + - type: "SendAsync" + amount: 0.002 + to: "client_58" + - type: "SendAsync" + amount: 0.002 + to: "client_59" + - type: "SendAsync" + amount: 0.002 + to: "client_60" + - type: "SendAsync" + amount: 0.002 + to: "client_61" + - type: "SendAsync" + amount: 0.002 + to: "client_62" + - type: "SendAsync" + amount: 0.002 + to: "client_63" + - type: "SendAsync" + amount: 0.002 + to: "client_64" + - type: "SendAsync" + amount: 0.002 + to: "client_65" + - type: "SendAsync" + amount: 0.002 + to: "client_66" + - type: "SendAsync" + amount: 0.002 + to: "client_67" + - type: "SendAsync" + amount: 0.002 + to: "client_68" + - type: "SendAsync" + amount: 0.002 + to: "client_69" + - type: "SendAsync" + amount: 0.002 + to: "client_70" + - type: "SendAsync" + amount: 0.002 + to: "client_71" + - type: "SendAsync" + amount: 0.002 + to: "client_72" + - type: "SendAsync" + amount: 0.002 + to: "client_73" + - type: "SendAsync" + amount: 0.002 + to: "client_74" + - type: "SendAsync" + amount: 0.002 + to: "client_75" + - type: "SendAsync" + amount: 0.002 + to: "client_76" + - type: "SendAsync" + amount: 0.002 + to: "client_77" + - type: "SendAsync" + amount: 0.002 + to: "client_78" + - type: "SendAsync" + amount: 0.002 + to: "client_79" + - type: "SendAsync" + amount: 0.002 + to: "client_80" + - type: "SendAsync" + amount: 0.002 + to: "client_81" + - type: "SendAsync" + amount: 0.002 + to: "client_82" + - type: "SendAsync" + amount: 0.002 + to: "client_83" + - type: "SendAsync" + amount: 0.002 + to: "client_84" + - type: "SendAsync" + amount: 0.002 + to: "client_85" + - type: "SendAsync" + amount: 0.002 + to: "client_86" + - type: "SendAsync" + amount: 0.002 + to: "client_87" + - type: "SendAsync" + amount: 0.002 + to: "client_88" + - type: "SendAsync" + amount: 0.002 + to: "client_89" + - type: "SendAsync" + amount: 0.002 + to: "client_90" + - type: "SendAsync" + amount: 0.002 + to: "client_91" + - type: "SendAsync" + amount: 0.002 + to: "client_92" + - type: "SendAsync" + amount: 0.002 + to: "client_93" + - type: "SendAsync" + amount: 0.002 + to: "client_94" + - type: "SendAsync" + amount: 0.002 + to: "client_95" + - type: "SendAsync" + amount: 0.002 + to: "client_96" + - type: "SendAsync" + amount: 0.002 + to: "client_97" + - type: "SendAsync" + amount: 0.002 + to: "client_98" + - type: "SendAsync" + amount: 0.002 + to: "client_99" + + - number: 3 + actions: + client_1: + - type: "Claim" + client_2: + - type: "Claim" + client_3: + - type: "Claim" + client_4: + - type: "Claim" + client_5: + - type: "Claim" + client_6: + - type: "Claim" + client_7: + - type: "Claim" + client_8: + - type: "Claim" + client_9: + - type: "Claim" + client_10: + - type: "Claim" + client_11: + - type: "Claim" + client_12: + - type: "Claim" + client_13: + - type: "Claim" + client_14: + - type: "Claim" + client_15: + - type: "Claim" + client_16: + - type: "Claim" + client_17: + - type: "Claim" + client_18: + - type: "Claim" + client_19: + - type: "Claim" + client_20: + - type: "Claim" + client_21: + - type: "Claim" + client_22: + - type: "Claim" + client_23: + - type: "Claim" + client_24: + - type: "Claim" + client_25: + - type: "Claim" + client_26: + - type: "Claim" + client_27: + - type: "Claim" + client_28: + - type: "Claim" + client_29: + - type: "Claim" + client_30: + - type: "Claim" + client_31: + - type: "Claim" + client_32: + - type: "Claim" + client_33: + - type: "Claim" + client_34: + - type: "Claim" + client_35: + - type: "Claim" + client_36: + - type: "Claim" + client_37: + - type: "Claim" + client_38: + - type: "Claim" + client_39: + - type: "Claim" + client_40: + - type: "Claim" + client_41: + - type: "Claim" + client_42: + - type: "Claim" + client_43: + - type: "Claim" + client_44: + - type: "Claim" + client_45: + - type: "Claim" + client_46: + - type: "Claim" + client_47: + - type: "Claim" + client_48: + - type: "Claim" + client_49: + - type: "Claim" + client_50: + - type: "Claim" + client_51: + - type: "Claim" + client_52: + - type: "Claim" + client_53: + - type: "Claim" + client_54: + - type: "Claim" + client_55: + - type: "Claim" + client_56: + - type: "Claim" + client_57: + - type: "Claim" + client_58: + - type: "Claim" + client_59: + - type: "Claim" + client_60: + - type: "Claim" + client_61: + - type: "Claim" + client_62: + - type: "Claim" + client_63: + - type: "Claim" + client_64: + - type: "Claim" + client_65: + - type: "Claim" + client_66: + - type: "Claim" + client_67: + - type: "Claim" + client_68: + - type: "Claim" + client_69: + - type: "Claim" + client_70: + - type: "Claim" + client_71: + - type: "Claim" + client_72: + - type: "Claim" + client_73: + - type: "Claim" + client_74: + - type: "Claim" + client_75: + - type: "Claim" + client_76: + - type: "Claim" + client_77: + - type: "Claim" + client_78: + - type: "Claim" + client_79: + - type: "Claim" + client_80: + - type: "Claim" + client_81: + - type: "Claim" + client_82: + - type: "Claim" + client_83: + - type: "Claim" + client_84: + - type: "Claim" + client_85: + - type: "Claim" + client_86: + - type: "Claim" + client_87: + - type: "Claim" + client_88: + - type: "Claim" + client_89: + - type: "Claim" + client_90: + - type: "Claim" + client_91: + - type: "Claim" + client_92: + - type: "Claim" + client_93: + - type: "Claim" + client_94: + - type: "Claim" + client_95: + - type: "Claim" + client_96: + - type: "Claim" + client_97: + - type: "Claim" + client_98: + - type: "Claim" + client_99: + - type: "Claim" +