From 8c6540441480d680346087c47be536e2d1d22db9 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:50 +0100 Subject: [PATCH 01/19] multi: allow proof courier to short cut with local archive With this commit we allow the universe RPC courier to short cut the iterative proof retrieval process if we arrive at a proof in the chain that we already have in the local archive. And since the local archive only stores full chains of proofs, once we get one from it, the full retrieval process is complete. --- proof/courier.go | 97 +++++++++++++++++++++++++++-------- proof/courier_test.go | 115 ++++++++++++++++++++++++++++++++++++++++++ tapcfg/server.go | 1 + tapdb/multiverse.go | 4 +- 4 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 proof/courier_test.go diff --git a/proof/courier.go b/proof/courier.go index b31517c7d..42ff090a5 100644 --- a/proof/courier.go +++ b/proof/courier.go @@ -85,6 +85,10 @@ type CourierCfg struct { // TransferLog is a log for recording proof delivery and retrieval // attempts. TransferLog TransferLog + + // LocalArchive is an archive that can be used to fetch proofs from the + // local archive. + LocalArchive Archiver } // CourierDispatch is an interface that abstracts away the different proof @@ -123,10 +127,6 @@ func (u *URLDispatch) NewCourier(addr *url.URL, cfg.BackoffCfg, u.cfg.TransferLog, ) - hashMailCfg := HashMailCourierCfg{ - ReceiverAckTimeout: cfg.ReceiverAckTimeout, - } - hashMailBox, err := NewHashMailBox(addr) if err != nil { return nil, fmt.Errorf("unable to make mailbox: %v", @@ -134,7 +134,7 @@ func (u *URLDispatch) NewCourier(addr *url.URL, } return &HashMailCourier{ - cfg: &hashMailCfg, + cfg: u.cfg, backoffHandle: backoffHandler, recipient: recipient, mailbox: hashMailBox, @@ -165,7 +165,7 @@ func (u *URLDispatch) NewCourier(addr *url.URL, recipient: recipient, client: client, backoffHandle: backoffHandler, - transfer: u.cfg.TransferLog, + cfg: u.cfg, subscribers: subscribers, rawConn: conn, }, nil @@ -593,9 +593,9 @@ func (b *BackoffHandler) initialDelay(ctx context.Context, // Exec attempts to execute the given proof transfer function using a repeating // backoff time delayed strategy. The backoff strategy is used to ensure that we // don't spam the courier service with proof transfer attempts. -func (b *BackoffHandler) Exec(ctx context.Context, - proofLocator Locator, transferType TransferType, - transferFunc func() error, subscriberEvent func(fn.Event)) error { +func (b *BackoffHandler) Exec(ctx context.Context, proofLocator Locator, + transferType TransferType, transferFunc func() error, + subscriberEvent func(fn.Event)) error { if b.cfg == nil { return fmt.Errorf("backoff config not specified") @@ -721,8 +721,8 @@ type HashMailCourierCfg struct { // HashMailCourier is a hashmail proof courier service handle. It implements the // Courier interface. type HashMailCourier struct { - // cfg contains the courier's configuration parameters. - cfg *HashMailCourierCfg + // cfg is the general courier configuration. + cfg *CourierCfg // backoffHandle is a handle to the backoff procedure used in proof // delivery. @@ -786,10 +786,10 @@ func (h *HashMailCourier) DeliverProof(ctx context.Context, // Wait to receive the ACK from the remote party over // their stream. log.Infof("Waiting (%v) for receiver ACK via sid=%x", - h.cfg.ReceiverAckTimeout, receiverStreamID) + h.cfg.HashMailCfg.ReceiverAckTimeout, receiverStreamID) ctxTimeout, cancel := context.WithTimeout( - ctx, h.cfg.ReceiverAckTimeout, + ctx, h.cfg.HashMailCfg.ReceiverAckTimeout, ) defer cancel() err = h.mailbox.RecvAck(ctxTimeout, receiverStreamID) @@ -1008,6 +1008,9 @@ type UniverseRpcCourier struct { // the universe RPC server. client unirpc.UniverseClient + // cfg is the general courier configuration. + cfg *CourierCfg + // rawConn is the raw connection that the courier will use to interact // with the remote gRPC service. rawConn *grpc.ClientConn @@ -1016,10 +1019,6 @@ type UniverseRpcCourier struct { // delivery. backoffHandle *BackoffHandler - // transfer is the log that the courier will use to record the - // attempted delivery of proofs to the receiver. - transfer TransferLog - // subscribers is a map of components that want to be notified on new // events, keyed by their subscription ID. subscribers map[uint64]*fn.EventReceiver[fn.Event] @@ -1188,7 +1187,9 @@ func (c *UniverseRpcCourier) ReceiveProof(ctx context.Context, return proofBlob, nil } - proofFile, err := FetchProofProvenance(ctx, originLocator, fetchProof) + proofFile, err := FetchProofProvenance( + ctx, c.cfg.LocalArchive, originLocator, fetchProof, + ) if err != nil { return nil, fmt.Errorf("error fetching proof provenance: %w", err) @@ -1270,14 +1271,19 @@ type TransferLog interface { // FetchProofProvenance iterates backwards through the main chain of proofs // until it reaches the genesis point (the asset is the genesis asset) and then // returns the full proof file with the full provenance for the asset. -func FetchProofProvenance(ctx context.Context, originLocator Locator, +func FetchProofProvenance(ctx context.Context, localArchive Archiver, + originLocator Locator, fetchSingleProof func(context.Context, Locator) (Blob, error)) (*File, error) { // In order to reconstruct the proof file we must collect all the // transition proofs that make up the main chain of proofs. That is // accomplished by iterating backwards through the main chain of proofs - // until we reach the genesis point (minting proof). + // until we reach the genesis point (minting proof). The local archive + // can be a proof file based archive or a single proof based archive. If + // we do get a full proof file from the local archive, we do have a + // shortcut to the full remaining provenance, and we can stop the + // iterative lookup. // We will update the locator at each iteration. currentLocator := originLocator @@ -1287,6 +1293,57 @@ func FetchProofProvenance(ctx context.Context, originLocator Locator, // is a reversal of that found in the proof file. var reversedProofs []Blob for { + // Before we attempt to fetch the proof from the potentially + // remote universe, we'll check our local archive to see if we + // already have it. This doesn't make sense in all cases, so we + // allow the local archive to be nil, in which case we just skip + // this step. The local universe might give us a single proof or + // a full file, depending on its type. If we get a full file, we + // are already done. + var ( + fullProof Blob + err error + ) + if localArchive != nil { + fullProof, err = localArchive.FetchProof( + ctx, currentLocator, + ) + } + + // If we don't have a local archive, then the IsFile() check + // returns false, and we skip this block. + if err == nil && fullProof.IsFile() { + // The file in the local archive contains the full + // provenance from the current proof back to the + // genesis. + proofFile, err := fullProof.AsFile() + if err != nil { + return nil, fmt.Errorf("unable to decode "+ + "proof file: %w", err) + } + + // So if this is the first proof we've fetched, we're + // already done. + if len(reversedProofs) == 0 { + return proofFile, nil + } + + // If we have already fetched some proofs, we'll need to + // append them to the proof file we just fetched. + for i := len(reversedProofs) - 1; i >= 0; i-- { + err := proofFile.AppendProofRaw( + reversedProofs[i], + ) + if err != nil { + return nil, fmt.Errorf("error "+ + "appending proof to proof "+ + "file: %w", err) + } + } + + return proofFile, nil + } + // Setup proof receive/query routine and start backoff // procedure. proofBlob, err := fetchSingleProof(ctx, currentLocator) diff --git a/proof/courier_test.go b/proof/courier_test.go new file mode 100644 index 000000000..f9bc61adb --- /dev/null +++ b/proof/courier_test.go @@ -0,0 +1,115 @@ +package proof + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/fn" + "github.com/lightninglabs/taproot-assets/internal/test" + "github.com/stretchr/testify/require" +) + +type mockProofArchive struct { + proofs map[Locator]Blob +} + +func newMockProofArchive() *mockProofArchive { + return &mockProofArchive{ + proofs: make(map[Locator]Blob), + } +} + +func (m *mockProofArchive) FetchProof(ctx context.Context, + id Locator) (Blob, error) { + + proof, ok := m.proofs[id] + if !ok { + return nil, ErrProofNotFound + } + + return proof, nil +} + +func (m *mockProofArchive) HasProof(ctx context.Context, + id Locator) (bool, error) { + + _, ok := m.proofs[id] + + return ok, nil +} + +func (m *mockProofArchive) FetchProofs(ctx context.Context, + id asset.ID) ([]*AnnotatedProof, error) { + + return nil, fmt.Errorf("not implemented") +} + +func (m *mockProofArchive) ImportProofs(ctx context.Context, + headerVerifier HeaderVerifier, groupVerifier GroupVerifier, + replace bool, proofs ...*AnnotatedProof) error { + + return fmt.Errorf("not implemented") +} + +// TestUniverseRpcCourierLocalArchiveShortCut tests that the local archive is +// used as a shortcut to fetch a proof if it's available. +func TestUniverseRpcCourierLocalArchiveShortCut(t *testing.T) { + localArchive := newMockProofArchive() + + testBlocks := readTestData(t) + oddTxBlock := testBlocks[0] + + genesis := asset.RandGenesis(t, asset.Collectible) + scriptKey := test.RandPubKey(t) + proof := randomProof(t, genesis, scriptKey, oddTxBlock, 0, 1) + + file, err := NewFile(V0, proof, proof) + require.NoError(t, err) + proof.AdditionalInputs = []File{*file, *file} + + var fileBuf bytes.Buffer + require.NoError(t, file.Encode(&fileBuf)) + proofBlob := Blob(fileBuf.Bytes()) + + locator := Locator{ + AssetID: fn.Ptr(genesis.ID()), + ScriptKey: *proof.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(proof.OutPoint()), + } + localArchive.proofs[locator] = proofBlob + + courier := &UniverseRpcCourier{ + recipient: Recipient{}, + client: nil, + cfg: &CourierCfg{ + LocalArchive: localArchive, + }, + rawConn: nil, + backoffHandle: nil, + subscribers: nil, + } + + ctx := context.Background() + ctxt, cancel := context.WithTimeout(ctx, testTimeout) + defer cancel() + + // If we attempt to receive a proof that the local archive has, we + // expect to get it back. + annotatedProof, err := courier.ReceiveProof(ctxt, locator) + require.NoError(t, err) + + require.Equal(t, proofBlob, annotatedProof.Blob) + + // If we query for a proof that the local archive doesn't have, we + // should end up in the code path that attempts to fetch the proof from + // the universe. Since we don't want to set up a full universe server + // in the test, we just make sure we get an error from that code path. + _, err = courier.ReceiveProof(ctxt, Locator{ + AssetID: fn.Ptr(genesis.ID()), + ScriptKey: *proof.Asset.ScriptKey.PubKey, + }) + require.ErrorContains(t, err, "is missing outpoint") +} diff --git a/tapcfg/server.go b/tapcfg/server.go index 862de4653..727405119 100644 --- a/tapcfg/server.go +++ b/tapcfg/server.go @@ -325,6 +325,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger, HashMailCfg: cfg.HashMailCourier, UniverseRpcCfg: cfg.UniverseRpcCourier, TransferLog: assetStore, + LocalArchive: proofArchive, }) multiNotifier := proof.NewMultiArchiveNotifier(assetStore, multiverse) diff --git a/tapdb/multiverse.go b/tapdb/multiverse.go index 39af6b364..a961201f7 100644 --- a/tapdb/multiverse.go +++ b/tapdb/multiverse.go @@ -960,7 +960,9 @@ func (b *MultiverseStore) FetchProof(ctx context.Context, return proofs[0].Leaf.RawProof, nil } - file, err := proof.FetchProofProvenance(ctx, originLocator, fetchProof) + file, err := proof.FetchProofProvenance( + ctx, nil, originLocator, fetchProof, + ) if err != nil { return nil, fmt.Errorf("error fetching proof from archive: %w", err) From 5d8102e2f06bcdecade679b1750cc266a333462d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:51 +0100 Subject: [PATCH 02/19] itest: fix duplicate naming, add hashmail courier to test name --- itest/test_list_on_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/itest/test_list_on_test.go b/itest/test_list_on_test.go index 7ff7ca92f..d25f84dec 100644 --- a/itest/test_list_on_test.go +++ b/itest/test_list_on_test.go @@ -41,7 +41,7 @@ var testCases = []*testCase{ test: testReOrgMintAndSend, }, { - name: "basic send unidirectional", + name: "basic send unidirectional hashmail courier", test: testBasicSendUnidirectional, proofCourierType: proof.HashmailCourierType, }, @@ -54,7 +54,8 @@ var testCases = []*testCase{ test: testRestartReceiverCheckBalance, }, { - name: "resume pending package send", + name: "resume pending package send hashmail " + + "courier", test: testResumePendingPackageSend, proofCourierType: proof.HashmailCourierType, }, @@ -72,7 +73,8 @@ var testCases = []*testCase{ test: testReattemptFailedReceiveUniCourier, }, { - name: "offline receiver eventually receives", + name: "offline receiver eventually receives " + + "hashmail courier", test: testOfflineReceiverEventuallyReceives, proofCourierType: proof.HashmailCourierType, }, @@ -81,7 +83,7 @@ var testCases = []*testCase{ test: testSendNoCourierUniverseImport, }, { - name: "basic send passive asset", + name: "basic send passive asset hashmail courier", test: testBasicSendPassiveAsset, proofCourierType: proof.HashmailCourierType, }, @@ -123,7 +125,7 @@ var testCases = []*testCase{ test: testMintMultiAssetGroups, }, { - name: "sending multi asset groups", + name: "sending multi asset groups hashmail courier", test: testMultiAssetGroupSend, proofCourierType: proof.HashmailCourierType, }, From 62074b321690ac13c36a1827eba0d04a46435ed8 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:53 +0100 Subject: [PATCH 03/19] tapdb: make sure proofs don't collide With this commit we make sure that proofs in the database don't collide if they use the same script key but different anchor transactions. This situation can occur if a TAP address receives multiple transfers. We also make sure we can query for the correct proof if we also specify the outpoint in the query. --- tapdb/addrs.go | 14 ++++++-- tapdb/assets_store.go | 55 ++++++++++++++++++++++++-------- tapdb/assets_store_test.go | 53 ++++++++++++++++++++++++++++-- tapdb/sqlc/assets.sql.go | 38 ++++++++++++++++------ tapdb/sqlc/querier.go | 2 +- tapdb/sqlc/queries/assets.sql | 19 +++++++---- tapdb/sqlc/queries/transfers.sql | 5 ++- tapdb/sqlc/transfers.sql.go | 7 +++- 8 files changed, 154 insertions(+), 39 deletions(-) diff --git a/tapdb/addrs.go b/tapdb/addrs.go index 195a0f116..1abd8cd2c 100644 --- a/tapdb/addrs.go +++ b/tapdb/addrs.go @@ -131,7 +131,7 @@ type AddrBook interface { // FetchAssetProof fetches the asset proof for a given asset identified // by its script key. - FetchAssetProof(ctx context.Context, scriptKey []byte) (AssetProofI, + FetchAssetProof(ctx context.Context, arg FetchAssetProof) (AssetProofI, error) // FetchGenesisByAssetID attempts to fetch asset genesis information @@ -895,11 +895,19 @@ func (t *TapAddressBook) CompleteEvent(ctx context.Context, event *address.Event, status address.Status, anchorPoint wire.OutPoint) error { - scriptKeyBytes := event.Addr.ScriptKey.SerializeCompressed() + outpoint, err := encodeOutpoint(anchorPoint) + if err != nil { + return fmt.Errorf("unable to encode outpoint: %w", err) + } + + args := FetchAssetProof{ + TweakedScriptKey: event.Addr.ScriptKey.SerializeCompressed(), + Outpoint: outpoint, + } var writeTxOpts AddrBookTxOptions return t.db.ExecTx(ctx, &writeTxOpts, func(db AddrBook) error { - proofData, err := db.FetchAssetProof(ctx, scriptKeyBytes) + proofData, err := db.FetchAssetProof(ctx, args) if err != nil { return fmt.Errorf("error fetching asset proof: %w", err) } diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index 1698b0655..60de6d2f3 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -45,6 +45,9 @@ type ( // where the proofs for a specific asset are fetched. AssetProofI = sqlc.FetchAssetProofRow + // FetchAssetProof are the query parameters for fetching an asset proof. + FetchAssetProof = sqlc.FetchAssetProofParams + // AssetProofByIDRow is the asset proof for a given asset, identified by // its asset ID. AssetProofByIDRow = sqlc.FetchAssetProofsByAssetIDRow @@ -173,7 +176,7 @@ type ActiveAssetsStore interface { // FetchAssetProof fetches the asset proof for a given asset identified // by its script key. FetchAssetProof(ctx context.Context, - scriptKey []byte) (AssetProofI, error) + arg FetchAssetProof) (AssetProofI, error) // HasAssetProof returns true if we have proof for a given asset // identified by its script key. @@ -1187,7 +1190,9 @@ func (a *AssetStore) FetchAssetProofs(ctx context.Context, serializedKey := asset.ToSerialized(scriptKey) assetProof, err := q.FetchAssetProof( - ctx, serializedKey[:], + ctx, FetchAssetProof{ + TweakedScriptKey: serializedKey[:], + }, ) if err != nil { return fmt.Errorf("unable to fetch asset "+ @@ -1212,20 +1217,32 @@ func (a *AssetStore) FetchAssetProofs(ctx context.Context, func (a *AssetStore) FetchProof(ctx context.Context, locator proof.Locator) (proof.Blob, error) { - // We don't need anything else but the script key since we have an - // on-disk index for all proofs we store. - scriptKey := locator.ScriptKey + // We have an on-disk index for all proofs we store, so we can use the + // script key as the primary identifier. + args := FetchAssetProof{ + TweakedScriptKey: locator.ScriptKey.SerializeCompressed(), + } + + // But script keys aren't unique, so if the locator explicitly specifies + // an outpoint, we'll use that as well. + if locator.OutPoint != nil { + outpoint, err := encodeOutpoint(*locator.OutPoint) + if err != nil { + return nil, fmt.Errorf("unable to encode outpoint: %w", + err) + } + + args.Outpoint = outpoint + } var diskProof proof.Blob readOpts := NewAssetStoreReadTx() dbErr := a.db.ExecTx(ctx, &readOpts, func(q ActiveAssetsStore) error { - assetProof, err := q.FetchAssetProof( - ctx, scriptKey.SerializeCompressed(), - ) + assetProof, err := q.FetchAssetProof(ctx, args) if err != nil { - return fmt.Errorf("unable to fetch asset "+ - "proof: %w", err) + return fmt.Errorf("unable to fetch asset proof: %w", + err) } diskProof = assetProof.ProofFile @@ -1500,6 +1517,7 @@ func (a *AssetStore) importAssetFromProof(ctx context.Context, scriptKeyBytes := newAsset.ScriptKey.PubKey.SerializeCompressed() return db.UpsertAssetProof(ctx, ProofUpdate{ TweakedScriptKey: scriptKeyBytes, + Outpoint: anchorPoint, ProofFile: proof.Blob, }) } @@ -1532,11 +1550,20 @@ func (a *AssetStore) upsertAssetProof(ctx context.Context, return fmt.Errorf("unable to insert chain tx: %w", err) } + outpointBytes, err := encodeOutpoint(wire.OutPoint{ + Hash: anchorTXID, + Index: proof.OutputIndex, + }) + if err != nil { + return err + } + // As a final step, we'll insert the proof file we used to generate all // the above information. scriptKeyBytes := proof.Asset.ScriptKey.PubKey.SerializeCompressed() return db.UpsertAssetProof(ctx, ProofUpdate{ TweakedScriptKey: scriptKeyBytes, + Outpoint: outpointBytes, ProofFile: proof.Blob, }) } @@ -1546,9 +1573,9 @@ func (a *AssetStore) upsertAssetProof(ctx context.Context, // The final resting place of the asset will be used as the script key itself. // // NOTE: This implements the proof.ArchiveBackend interface. -func (a *AssetStore) ImportProofs(ctx context.Context, - headerVerifier proof.HeaderVerifier, groupVerifier proof.GroupVerifier, - replace bool, proofs ...*proof.AnnotatedProof) error { +func (a *AssetStore) ImportProofs(ctx context.Context, _ proof.HeaderVerifier, + _ proof.GroupVerifier, replace bool, + proofs ...*proof.AnnotatedProof) error { var writeTxOpts AssetStoreTxOptions err := a.db.ExecTx(ctx, &writeTxOpts, func(q ActiveAssetsStore) error { @@ -2604,6 +2631,7 @@ func (a *AssetStore) ConfirmParcelDelivery(ctx context.Context, // this given delta. err = q.UpsertAssetProof(ctx, ProofUpdate{ TweakedScriptKey: out.ScriptKeyBytes, + Outpoint: out.AnchorOutpoint, ProofFile: receiverProof.Blob, }) if err != nil { @@ -2730,6 +2758,7 @@ func (a *AssetStore) reAnchorPassiveAssets(ctx context.Context, // Update the asset proof. err = q.UpsertAssetProof(ctx, ProofUpdate{ AssetID: sqlInt64(passiveAsset.AssetID), + Outpoint: passiveAsset.Outpoint, ProofFile: proofFile, }) if err != nil { diff --git a/tapdb/assets_store_test.go b/tapdb/assets_store_test.go index 036374a74..4fd0b7f50 100644 --- a/tapdb/assets_store_test.go +++ b/tapdb/assets_store_test.go @@ -331,6 +331,14 @@ func TestImportAssetProof(t *testing.T) { require.NoError(t, err) require.Equal(t, updatedBlob, []byte(currentBlob)) + // Make sure we get the same result if we also query by proof outpoint. + currentBlob, err = assetStore.FetchProof(ctxb, proof.Locator{ + ScriptKey: *testAsset.ScriptKey.PubKey, + OutPoint: &testProof.AssetSnapshot.OutPoint, + }) + require.NoError(t, err) + require.Equal(t, updatedBlob, []byte(currentBlob)) + // Make sure the chain TX was updated as well. assets, err = assetStore.FetchAllAssets(ctxb, false, false, nil) require.NoError(t, err) @@ -348,6 +356,45 @@ func TestImportAssetProof(t *testing.T) { t, testProof.AssetSnapshot.OutPoint, dbAsset.AnchorOutpoint, ) require.Equal(t, testProof.AnchorTx.TxHash(), dbAsset.AnchorTx.TxHash()) + + // We now add a second proof for the same script key but a different + // outpoint and expect that to be stored and retrieved correctly. + oldOutpoint := testProof.AssetSnapshot.OutPoint + newChainTx := wire.NewMsgTx(2) + newChainTx.TxIn = []*wire.TxIn{{ + PreviousOutPoint: test.RandOp(t), + }} + newChainTx.TxOut = []*wire.TxOut{{ + PkScript: bytes.Repeat([]byte{0x01}, 34), + }} + newOutpoint := wire.OutPoint{ + Hash: newChainTx.TxHash(), + Index: 0, + } + testProof.AssetSnapshot.AnchorTx = newChainTx + testProof.AssetSnapshot.OutPoint = newOutpoint + testProof.Blob = []byte("new proof") + + require.NoError(t, assetStore.ImportProofs( + ctxb, proof.MockHeaderVerifier, proof.MockGroupVerifier, false, + testProof, + )) + + // We should still be able to fetch the old proof. + dbBlob, err := assetStore.FetchProof(ctxb, proof.Locator{ + ScriptKey: *testAsset.ScriptKey.PubKey, + OutPoint: &oldOutpoint, + }) + require.NoError(t, err) + require.Equal(t, updatedBlob, []byte(dbBlob)) + + // But also the new one. + dbBlob, err = assetStore.FetchProof(ctxb, proof.Locator{ + ScriptKey: *testAsset.ScriptKey.PubKey, + OutPoint: &newOutpoint, + }) + require.NoError(t, err) + require.EqualValues(t, testProof.Blob, []byte(dbBlob)) } // TestInternalKeyUpsert tests that if we insert an internal key that's a @@ -1408,9 +1455,9 @@ func TestAssetExportLog(t *testing.T) { // As a final check for the asset, we'll fetch its blob to ensure it's // been updated on disk. - diskSenderBlob, err := db.FetchAssetProof( - ctx, newScriptKey.PubKey.SerializeCompressed(), - ) + diskSenderBlob, err := db.FetchAssetProof(ctx, FetchAssetProof{ + TweakedScriptKey: newScriptKey.PubKey.SerializeCompressed(), + }) require.NoError(t, err) require.Equal(t, receiverBlob, diskSenderBlob.ProofFile) diff --git a/tapdb/sqlc/assets.sql.go b/tapdb/sqlc/assets.sql.go index 6c15a89fd..1e83afc80 100644 --- a/tapdb/sqlc/assets.sql.go +++ b/tapdb/sqlc/assets.sql.go @@ -508,34 +508,45 @@ func (q *Queries) FetchAssetMetaForAsset(ctx context.Context, assetID []byte) (F const fetchAssetProof = `-- name: FetchAssetProof :one WITH asset_info AS ( - SELECT assets.asset_id, script_keys.tweaked_script_key + SELECT assets.asset_id, script_keys.tweaked_script_key, utxos.outpoint FROM assets JOIN script_keys ON assets.script_key_id = script_keys.script_key_id - WHERE script_keys.tweaked_script_key = $1 + JOIN managed_utxos utxos + ON assets.anchor_utxo_id = utxos.utxo_id + WHERE script_keys.tweaked_script_key = $1 + AND (utxos.outpoint = $2 OR $2 IS NULL) ) SELECT asset_info.tweaked_script_key AS script_key, asset_proofs.proof_file, - asset_info.asset_id as asset_id, asset_proofs.proof_id as proof_id + asset_info.asset_id as asset_id, asset_proofs.proof_id as proof_id, + asset_info.outpoint as outpoint FROM asset_proofs JOIN asset_info - ON asset_info.asset_id = asset_proofs.asset_id + ON asset_info.asset_id = asset_proofs.asset_id ` +type FetchAssetProofParams struct { + TweakedScriptKey []byte + Outpoint []byte +} + type FetchAssetProofRow struct { ScriptKey []byte ProofFile []byte AssetID int64 ProofID int64 + Outpoint []byte } -func (q *Queries) FetchAssetProof(ctx context.Context, tweakedScriptKey []byte) (FetchAssetProofRow, error) { - row := q.db.QueryRowContext(ctx, fetchAssetProof, tweakedScriptKey) +func (q *Queries) FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) (FetchAssetProofRow, error) { + row := q.db.QueryRowContext(ctx, fetchAssetProof, arg.TweakedScriptKey, arg.Outpoint) var i FetchAssetProofRow err := row.Scan( &i.ScriptKey, &i.ProofFile, &i.AssetID, &i.ProofID, + &i.Outpoint, ) return i, err } @@ -2318,14 +2329,15 @@ WITH target_asset(asset_id) AS ( FROM assets JOIN script_keys ON assets.script_key_id = script_keys.script_key_id + JOIN managed_utxos utxos + ON assets.anchor_utxo_id = utxos.utxo_id WHERE (script_keys.tweaked_script_key = $2 OR $2 IS NULL) AND (assets.asset_id = $3 OR $3 IS NULL) - -- TODO(guggero): Fix this by disallowing multiple assets with the same - -- script key! - LIMIT 1 + AND (utxos.outpoint = $4 + OR $4 IS NULL) ) INSERT INTO asset_proofs ( asset_id, proof_file @@ -2340,10 +2352,16 @@ type UpsertAssetProofParams struct { ProofFile []byte TweakedScriptKey []byte AssetID sql.NullInt64 + Outpoint []byte } func (q *Queries) UpsertAssetProof(ctx context.Context, arg UpsertAssetProofParams) error { - _, err := q.db.ExecContext(ctx, upsertAssetProof, arg.ProofFile, arg.TweakedScriptKey, arg.AssetID) + _, err := q.db.ExecContext(ctx, upsertAssetProof, + arg.ProofFile, + arg.TweakedScriptKey, + arg.AssetID, + arg.Outpoint, + ) return err } diff --git a/tapdb/sqlc/querier.go b/tapdb/sqlc/querier.go index 15c7b14ac..5d072f672 100644 --- a/tapdb/sqlc/querier.go +++ b/tapdb/sqlc/querier.go @@ -42,7 +42,7 @@ type Querier interface { FetchAssetMeta(ctx context.Context, metaID int64) (FetchAssetMetaRow, error) FetchAssetMetaByHash(ctx context.Context, metaDataHash []byte) (FetchAssetMetaByHashRow, error) FetchAssetMetaForAsset(ctx context.Context, assetID []byte) (FetchAssetMetaForAssetRow, error) - FetchAssetProof(ctx context.Context, tweakedScriptKey []byte) (FetchAssetProofRow, error) + FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) (FetchAssetProofRow, error) FetchAssetProofs(ctx context.Context) ([]FetchAssetProofsRow, error) FetchAssetProofsByAssetID(ctx context.Context, assetID []byte) ([]FetchAssetProofsByAssetIDRow, error) FetchAssetWitnesses(ctx context.Context, assetID sql.NullInt64) ([]FetchAssetWitnessesRow, error) diff --git a/tapdb/sqlc/queries/assets.sql b/tapdb/sqlc/queries/assets.sql index 516369fdf..eb7c0e0cd 100644 --- a/tapdb/sqlc/queries/assets.sql +++ b/tapdb/sqlc/queries/assets.sql @@ -632,14 +632,15 @@ WITH target_asset(asset_id) AS ( FROM assets JOIN script_keys ON assets.script_key_id = script_keys.script_key_id + JOIN managed_utxos utxos + ON assets.anchor_utxo_id = utxos.utxo_id WHERE (script_keys.tweaked_script_key = sqlc.narg('tweaked_script_key') OR sqlc.narg('tweaked_script_key') IS NULL) AND (assets.asset_id = sqlc.narg('asset_id') OR sqlc.narg('asset_id') IS NULL) - -- TODO(guggero): Fix this by disallowing multiple assets with the same - -- script key! - LIMIT 1 + AND (utxos.outpoint = sqlc.narg('outpoint') + OR sqlc.narg('outpoint') IS NULL) ) INSERT INTO asset_proofs ( asset_id, proof_file @@ -678,17 +679,21 @@ JOIN asset_info -- name: FetchAssetProof :one WITH asset_info AS ( - SELECT assets.asset_id, script_keys.tweaked_script_key + SELECT assets.asset_id, script_keys.tweaked_script_key, utxos.outpoint FROM assets JOIN script_keys ON assets.script_key_id = script_keys.script_key_id - WHERE script_keys.tweaked_script_key = $1 + JOIN managed_utxos utxos + ON assets.anchor_utxo_id = utxos.utxo_id + WHERE script_keys.tweaked_script_key = $1 + AND (utxos.outpoint = sqlc.narg('outpoint') OR sqlc.narg('outpoint') IS NULL) ) SELECT asset_info.tweaked_script_key AS script_key, asset_proofs.proof_file, - asset_info.asset_id as asset_id, asset_proofs.proof_id as proof_id + asset_info.asset_id as asset_id, asset_proofs.proof_id as proof_id, + asset_info.outpoint as outpoint FROM asset_proofs JOIN asset_info - ON asset_info.asset_id = asset_proofs.asset_id; + ON asset_info.asset_id = asset_proofs.asset_id; -- name: HasAssetProof :one WITH asset_info AS ( diff --git a/tapdb/sqlc/queries/transfers.sql b/tapdb/sqlc/queries/transfers.sql index 234397f9f..3575924d9 100644 --- a/tapdb/sqlc/queries/transfers.sql +++ b/tapdb/sqlc/queries/transfers.sql @@ -155,10 +155,13 @@ INSERT INTO passive_assets ( -- name: QueryPassiveAssets :many SELECT passive.asset_id, passive.new_anchor_utxo, passive.script_key, passive.new_witness_stack, passive.new_proof, - genesis_assets.asset_id AS genesis_id, passive.asset_version + genesis_assets.asset_id AS genesis_id, passive.asset_version, + utxos.outpoint FROM passive_assets as passive JOIN assets ON passive.asset_id = assets.asset_id JOIN genesis_assets ON assets.genesis_id = genesis_assets.gen_asset_id + JOIN managed_utxos utxos + ON passive.new_anchor_utxo = utxos.utxo_id WHERE passive.transfer_id = @transfer_id; diff --git a/tapdb/sqlc/transfers.sql.go b/tapdb/sqlc/transfers.sql.go index 38f9d8327..079ac54c8 100644 --- a/tapdb/sqlc/transfers.sql.go +++ b/tapdb/sqlc/transfers.sql.go @@ -455,12 +455,15 @@ func (q *Queries) QueryAssetTransfers(ctx context.Context, arg QueryAssetTransfe const queryPassiveAssets = `-- name: QueryPassiveAssets :many SELECT passive.asset_id, passive.new_anchor_utxo, passive.script_key, passive.new_witness_stack, passive.new_proof, - genesis_assets.asset_id AS genesis_id, passive.asset_version + genesis_assets.asset_id AS genesis_id, passive.asset_version, + utxos.outpoint FROM passive_assets as passive JOIN assets ON passive.asset_id = assets.asset_id JOIN genesis_assets ON assets.genesis_id = genesis_assets.gen_asset_id + JOIN managed_utxos utxos + ON passive.new_anchor_utxo = utxos.utxo_id WHERE passive.transfer_id = $1 ` @@ -472,6 +475,7 @@ type QueryPassiveAssetsRow struct { NewProof []byte GenesisID []byte AssetVersion int32 + Outpoint []byte } func (q *Queries) QueryPassiveAssets(ctx context.Context, transferID int64) ([]QueryPassiveAssetsRow, error) { @@ -491,6 +495,7 @@ func (q *Queries) QueryPassiveAssets(ctx context.Context, transferID int64) ([]Q &i.NewProof, &i.GenesisID, &i.AssetVersion, + &i.Outpoint, ); err != nil { return nil, err } From 1e9d8bb40c6f9328b55d400e50558245ba895860 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:54 +0100 Subject: [PATCH 04/19] tapdb: fix proof update by ID Since we now have a JOIN with the managed_utxos in the UpsertAssetProof we cannot use that to update proofs that haven't been re-anchored yet. But because we re-anchor passive assets only _after_ updating the proofs, this would previously result in no rows being updated. We could change the order of operations instead, but having WHERE clause for a specific database ID mixed in with optional value based queries wasn't super beautiful in the first place. So we opt for having a more explicit upsert for database ID based proof identification. --- tapdb/asset_minting.go | 4 ++++ tapdb/assets_store.go | 12 +++++++----- tapdb/sqlc/assets.sql.go | 36 +++++++++++++++++++++++------------ tapdb/sqlc/querier.go | 1 + tapdb/sqlc/queries/assets.sql | 15 +++++++++++---- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/tapdb/asset_minting.go b/tapdb/asset_minting.go index de20ea173..967999acf 100644 --- a/tapdb/asset_minting.go +++ b/tapdb/asset_minting.go @@ -109,6 +109,10 @@ type ( // ProofUpdate is used to update a proof file on disk. ProofUpdate = sqlc.UpsertAssetProofParams + // ProofUpdateByID is used to update a proof file on disk by asset + // database ID. + ProofUpdateByID = sqlc.UpsertAssetProofByIDParams + // NewScriptKey wraps the params needed to insert a new script key on // disk. NewScriptKey = sqlc.UpsertScriptKeyParams diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index 60de6d2f3..bb0bd26bf 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -201,8 +201,11 @@ type ActiveAssetsStore interface { // UpsertAssetProof inserts a new or updates an existing asset proof on // disk. - UpsertAssetProof(ctx context.Context, - arg sqlc.UpsertAssetProofParams) error + UpsertAssetProof(ctx context.Context, arg ProofUpdate) error + + // UpsertAssetProofByID inserts a new or updates an existing asset + // proof on disk. + UpsertAssetProofByID(ctx context.Context, arg ProofUpdateByID) error // InsertAssetWitness inserts a new prev input for an asset into the // database. @@ -2756,9 +2759,8 @@ func (a *AssetStore) reAnchorPassiveAssets(ctx context.Context, } // Update the asset proof. - err = q.UpsertAssetProof(ctx, ProofUpdate{ - AssetID: sqlInt64(passiveAsset.AssetID), - Outpoint: passiveAsset.Outpoint, + err = q.UpsertAssetProofByID(ctx, ProofUpdateByID{ + AssetID: passiveAsset.AssetID, ProofFile: proofFile, }) if err != nil { diff --git a/tapdb/sqlc/assets.sql.go b/tapdb/sqlc/assets.sql.go index 1e83afc80..f84138bb7 100644 --- a/tapdb/sqlc/assets.sql.go +++ b/tapdb/sqlc/assets.sql.go @@ -2333,11 +2333,9 @@ WITH target_asset(asset_id) AS ( ON assets.anchor_utxo_id = utxos.utxo_id WHERE (script_keys.tweaked_script_key = $2 - OR $2 IS NULL) - AND (assets.asset_id = $3 - OR $3 IS NULL) - AND (utxos.outpoint = $4 - OR $4 IS NULL) + OR $2 IS NULL) + AND (utxos.outpoint = $3 + OR $3 IS NULL) ) INSERT INTO asset_proofs ( asset_id, proof_file @@ -2351,17 +2349,31 @@ INSERT INTO asset_proofs ( type UpsertAssetProofParams struct { ProofFile []byte TweakedScriptKey []byte - AssetID sql.NullInt64 Outpoint []byte } func (q *Queries) UpsertAssetProof(ctx context.Context, arg UpsertAssetProofParams) error { - _, err := q.db.ExecContext(ctx, upsertAssetProof, - arg.ProofFile, - arg.TweakedScriptKey, - arg.AssetID, - arg.Outpoint, - ) + _, err := q.db.ExecContext(ctx, upsertAssetProof, arg.ProofFile, arg.TweakedScriptKey, arg.Outpoint) + return err +} + +const upsertAssetProofByID = `-- name: UpsertAssetProofByID :exec +INSERT INTO asset_proofs ( + asset_id, proof_file +) VALUES ( + $1, $2 +) ON CONFLICT (asset_id) + -- This is not a NOP, we always overwrite the proof with the new one. + DO UPDATE SET proof_file = EXCLUDED.proof_file +` + +type UpsertAssetProofByIDParams struct { + AssetID int64 + ProofFile []byte +} + +func (q *Queries) UpsertAssetProofByID(ctx context.Context, arg UpsertAssetProofByIDParams) error { + _, err := q.db.ExecContext(ctx, upsertAssetProofByID, arg.AssetID, arg.ProofFile) return err } diff --git a/tapdb/sqlc/querier.go b/tapdb/sqlc/querier.go index 5d072f672..56f83238f 100644 --- a/tapdb/sqlc/querier.go +++ b/tapdb/sqlc/querier.go @@ -152,6 +152,7 @@ type Querier interface { UpsertAssetGroupWitness(ctx context.Context, arg UpsertAssetGroupWitnessParams) (int64, error) UpsertAssetMeta(ctx context.Context, arg UpsertAssetMetaParams) (int64, error) UpsertAssetProof(ctx context.Context, arg UpsertAssetProofParams) error + UpsertAssetProofByID(ctx context.Context, arg UpsertAssetProofByIDParams) error UpsertChainTx(ctx context.Context, arg UpsertChainTxParams) (int64, error) UpsertFederationGlobalSyncConfig(ctx context.Context, arg UpsertFederationGlobalSyncConfigParams) error UpsertFederationProofSyncLog(ctx context.Context, arg UpsertFederationProofSyncLogParams) (int64, error) diff --git a/tapdb/sqlc/queries/assets.sql b/tapdb/sqlc/queries/assets.sql index eb7c0e0cd..b995c729a 100644 --- a/tapdb/sqlc/queries/assets.sql +++ b/tapdb/sqlc/queries/assets.sql @@ -636,11 +636,9 @@ WITH target_asset(asset_id) AS ( ON assets.anchor_utxo_id = utxos.utxo_id WHERE (script_keys.tweaked_script_key = sqlc.narg('tweaked_script_key') - OR sqlc.narg('tweaked_script_key') IS NULL) - AND (assets.asset_id = sqlc.narg('asset_id') - OR sqlc.narg('asset_id') IS NULL) + OR sqlc.narg('tweaked_script_key') IS NULL) AND (utxos.outpoint = sqlc.narg('outpoint') - OR sqlc.narg('outpoint') IS NULL) + OR sqlc.narg('outpoint') IS NULL) ) INSERT INTO asset_proofs ( asset_id, proof_file @@ -650,6 +648,15 @@ INSERT INTO asset_proofs ( -- This is not a NOP, we always overwrite the proof with the new one. DO UPDATE SET proof_file = EXCLUDED.proof_file; +-- name: UpsertAssetProofByID :exec +INSERT INTO asset_proofs ( + asset_id, proof_file +) VALUES ( + @asset_id, @proof_file +) ON CONFLICT (asset_id) + -- This is not a NOP, we always overwrite the proof with the new one. + DO UPDATE SET proof_file = EXCLUDED.proof_file; + -- name: FetchAssetProofs :many WITH asset_info AS ( SELECT assets.asset_id, script_keys.tweaked_script_key From c026b15a417ca8a7dec378a8f1145d62d081f615 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:55 +0100 Subject: [PATCH 05/19] multi: use wire.NewOutPointFromString, remove duplicate func This is a simple code move commit that removes a parsing function from the integration test and uses a commonly available one instead. --- cmd/tapcli/universe.go | 3 ++- itest/round_trip_send_test.go | 2 +- itest/universe_test.go | 5 +++-- itest/utils.go | 29 +---------------------------- rpcserver.go | 32 +------------------------------- 5 files changed, 8 insertions(+), 63 deletions(-) diff --git a/cmd/tapcli/universe.go b/cmd/tapcli/universe.go index b35d800ba..22801f9e3 100644 --- a/cmd/tapcli/universe.go +++ b/cmd/tapcli/universe.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" + "github.com/btcsuite/btcd/wire" tap "github.com/lightninglabs/taproot-assets" "github.com/lightninglabs/taproot-assets/fn" "github.com/lightninglabs/taproot-assets/proof" @@ -456,7 +457,7 @@ func parseAssetKey(ctx *cli.Context) (*unirpc.AssetKey, error) { return nil, fmt.Errorf("outpoint and script key must be set") } - outpoint, err := tap.UnmarshalOutpoint(ctx.String(outpointName)) + outpoint, err := wire.NewOutPointFromString(ctx.String(outpointName)) if err != nil { return nil, err } diff --git a/itest/round_trip_send_test.go b/itest/round_trip_send_test.go index d312eed21..cc199d663 100644 --- a/itest/round_trip_send_test.go +++ b/itest/round_trip_send_test.go @@ -127,7 +127,7 @@ func testRoundTripSend(t *harnessTest) { // recipient's output is the second one. bobToAliceOutput := transferResp.Transfers[0].Outputs[1] bobToAliceAnchor := bobToAliceOutput.Anchor - outpoint, err := ParseOutPoint(bobToAliceAnchor.Outpoint) + outpoint, err := wire.NewOutPointFromString(bobToAliceAnchor.Outpoint) require.NoError(t.t, err) internalKey, err := btcec.ParsePubKey(bobToAliceAnchor.InternalKey) diff --git a/itest/universe_test.go b/itest/universe_test.go index 4fbae3a34..8129b54c7 100644 --- a/itest/universe_test.go +++ b/itest/universe_test.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/wire" tap "github.com/lightninglabs/taproot-assets" "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/fn" @@ -150,7 +151,7 @@ func testUniverseSync(t *harnessTest) { // query for that asset with the compressed script key. firstAssetID := rpcSimpleAssets[0].AssetGenesis.AssetId firstScriptKey := hex.EncodeToString(rpcSimpleAssets[0].ScriptKey) - firstOutpoint, err := tap.UnmarshalOutpoint( + firstOutpoint, err := wire.NewOutPointFromString( rpcSimpleAssets[0].ChainAnchor.AnchorOutpoint, ) require.NoError(t.t, err) @@ -326,7 +327,7 @@ func testUniverseManualSync(t *harnessTest) { // We should also be able to fetch an asset from Bob's Universe, and // query for that asset with the compressed script key. - firstOutpoint, err := tap.UnmarshalOutpoint( + firstOutpoint, err := wire.NewOutPointFromString( firstAsset.ChainAnchor.AnchorOutpoint, ) require.NoError(t.t, err) diff --git a/itest/utils.go b/itest/utils.go index f842c2a34..8cf11cbed 100644 --- a/itest/utils.go +++ b/itest/utils.go @@ -2,9 +2,6 @@ package itest import ( "context" - "fmt" - "strconv" - "strings" "testing" "time" @@ -48,34 +45,10 @@ func CopyRequests( return copied } -// ParseOutPoint -func ParseOutPoint(s string) (*wire.OutPoint, error) { - split := strings.Split(s, ":") - if len(split) != 2 { - return nil, fmt.Errorf("expecting outpoint to be in format " + - "of: txid:index") - } - - index, err := strconv.ParseInt(split[1], 10, 32) - if err != nil { - return nil, fmt.Errorf("unable to decode output index: %v", err) - } - - txid, err := chainhash.NewHashFromStr(split[0]) - if err != nil { - return nil, fmt.Errorf("unable to parse hex string: %v", err) - } - - return &wire.OutPoint{ - Hash: *txid, - Index: uint32(index), - }, nil -} - // ParseGenInfo converts a taprpc.GenesisInfo into its asset.Genesis // counterpart. func ParseGenInfo(t *testing.T, genInfo *taprpc.GenesisInfo) *asset.Genesis { - genPoint, err := ParseOutPoint(genInfo.GenesisPoint) + genPoint, err := wire.NewOutPointFromString(genInfo.GenesisPoint) require.NoError(t, err) parsedGenesis := asset.Genesis{ diff --git a/rpcserver.go b/rpcserver.go index 416eb96fa..f2008d8dd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -9,7 +9,6 @@ import ( "fmt" "math" "net/http" - "strconv" "strings" "sync" "sync/atomic" @@ -3693,34 +3692,6 @@ func (r *rpcServer) AssetLeaves(ctx context.Context, return resp, nil } -// UnmarshalOutpoint un-marshals an outpoint from a string received via RPC. -func UnmarshalOutpoint(outpoint string) (*wire.OutPoint, error) { - parts := strings.Split(outpoint, ":") - if len(parts) != 2 { - return nil, errors.New("outpoint should be of form txid:index") - } - - txidStr := parts[0] - if hex.DecodedLen(len(txidStr)) != chainhash.HashSize { - return nil, fmt.Errorf("invalid hex-encoded txid %v", txidStr) - } - - txid, err := chainhash.NewHashFromStr(txidStr) - if err != nil { - return nil, err - } - - outputIndex, err := strconv.Atoi(parts[1]) - if err != nil { - return nil, fmt.Errorf("invalid output index: %v", err) - } - - return &wire.OutPoint{ - Hash: *txid, - Index: uint32(outputIndex), - }, nil -} - // unmarshalLeafKey un-marshals a leaf key from the RPC form. func unmarshalLeafKey(key *unirpc.AssetKey) (universe.LeafKey, error) { var leafKey universe.LeafKey @@ -3760,8 +3731,7 @@ func unmarshalLeafKey(key *unirpc.AssetKey) (universe.LeafKey, error) { case key.GetOpStr() != "": // Parse a bitcoin outpoint in the form txid:index into a // wire.OutPoint struct. - outpointStr := key.GetOpStr() - outpoint, err := UnmarshalOutpoint(outpointStr) + outpoint, err := wire.NewOutPointFromString(key.GetOpStr()) if err != nil { return leafKey, err } From 22e80d903701b24023f579e58c302176196ad5d1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:56 +0100 Subject: [PATCH 06/19] proof: use outpoint in proof file name To make sure we don't accidentally overwrite a proof file if we receive to a TAP address multiple times, we also use the first couple of bytes of the outpoint TXID and index in the file name. We don't use the full outpoint as in some operating systems the full path for a file is not allowed to exceed 256 characters (the path and file name combined). And since we already use 130 characters for the hex encoded asset ID and script key, we need to shorten the outpoint somewhat. We will add a migration that renames existing files on disk in the next commit. --- proof/archive.go | 171 +++++++++++++++++++++++++++++++++++++----- proof/archive_test.go | 151 ++++++++++++++++++++++++++++--------- 2 files changed, 269 insertions(+), 53 deletions(-) diff --git a/proof/archive.go b/proof/archive.go index 9530a616f..ccfdf89c7 100644 --- a/proof/archive.go +++ b/proof/archive.go @@ -28,9 +28,18 @@ const ( // ProofDirName is the name of the directory we'll use to store our // proofs. ProofDirName = "proofs" + + // outpointTruncateLength is the number of hex characters we use to + // represent the outpoint hash in the file name. This is to avoid + // problems with long file names on some operating systems. + outpointTruncateLength = 32 ) var ( + // emptyKey is an empty public key that we use to check if a script key + // is valid. + emptyKey btcec.PublicKey + // ErrProofNotFound is returned when a user attempts to look up a proof // based on a Locator, but we can't find it on disk. ErrProofNotFound = fmt.Errorf("unable to find proof") @@ -42,6 +51,17 @@ var ( // ErrInvalidLocatorKey is returned when a specified locator script key // is invalid. ErrInvalidLocatorKey = fmt.Errorf("invalid script key locator") + + // ErrOutPointMissing is returned when a specified locator does not + // contain an outpoint. The outpoint is required when storing a proof. + ErrOutPointMissing = fmt.Errorf("outpoint missing in key locator") + + // ErrMultipleProofs is returned if looking up a proof with only the + // asset ID and script key results in multiple proofs being found. + ErrMultipleProofs = fmt.Errorf( + "multiple proofs found with asset ID and script key, specify " + + "outpoint to disambiguate", + ) ) // Locator is able to uniquely identify a proof in the extended Taproot Asset @@ -231,10 +251,10 @@ var _ NotifyArchiver = (*MultiArchiveNotifier)(nil) // archiver takes a single root directory then creates the following overlap // mapping: // -// proofs/ -// ├─ asset_id1/ -// │ ├─ script_key1 -// │ ├─ script_key2 +// proofs/ +// ├─ asset_id1/ +// │ ├─ scriptKey1-outpointTxid[:32]-outpointIndex.assetproof +// │ ├─ scriptKey2-outpointTxid[:32]-outpointIndex.assetproof type FileArchiver struct { // proofPath is the directory name that we'll use as the roof for all // our files. @@ -266,37 +286,127 @@ func NewFileArchiver(dirName string) (*FileArchiver, error) { }, nil } -// genProofFilePath generates the full proof file path based on a rootPath and -// a valid locator. The final path is: root/assetID/scriptKey.assetproof -func genProofFilePath(rootPath string, loc Locator) (string, error) { - var emptyKey btcec.PublicKey - +// genProofFileStoragePath generates the full proof file path for storing a +// proof based on a rootPath and a valid locator. +// The final path is: +// +// root/assetID/scriptKey-outpointTxid[:32]-outpointIndex.assetproof +// +// NOTE: Because some operating systems have issues with paths longer than 256 +// characters, we don't use the full outpoint in the file name, but only the +// first 16 bytes (32 hex characters) of the hash. That should be enough to +// avoid collisions but saves us a full 32 characters (we already use 130 for +// the hex encoded asset ID and script key). +func genProofFileStoragePath(rootPath string, loc Locator) (string, error) { switch { case loc.AssetID == nil: return "", ErrInvalidLocatorID case loc.ScriptKey.IsEqual(&emptyKey): return "", ErrInvalidLocatorKey + + case loc.OutPoint == nil: + return "", ErrOutPointMissing } + assetID := hex.EncodeToString(loc.AssetID[:]) + + truncatedHash := loc.OutPoint.Hash.String()[:outpointTruncateLength] + fileName := fmt.Sprintf("%x-%s-%d%s", loc.ScriptKey.SerializeCompressed(), + truncatedHash, loc.OutPoint.Index, TaprootAssetsFileSuffix) + + return filepath.Join(rootPath, assetID, fileName), nil +} + +// lookupProofFilePath returns the full path for reading a proof file, based on +// the given locator. If the locator does not contain an outpoint, we'll check +// if there is just a single proof available on disk. If there is, we return +// that. If there are multiple, then the user needs to also specify the outpoint +// and we return ErrMultipleProofs. +func lookupProofFilePath(rootPath string, loc Locator) (string, error) { + // If an outpoint is specified, we want to look up a very specific file + // on disk. + if loc.OutPoint != nil { + fullName, err := genProofFileStoragePath(rootPath, loc) + if err != nil { + return "", err + } + + // If the file doesn't exist under the full name, we know there + // just isn't a proof file for that asset yet. + if !lnrpc.FileExists(fullName) { + return "", fmt.Errorf("proof file %s does not "+ + "exist: %w", fullName, ErrProofNotFound) + } + + return fullName, nil + } + + // If the user didn't specify an outpoint, we look up all proof files + // that start with the script key given. If there is exactly one, we + // return it. + switch { + case loc.AssetID == nil: + return "", ErrInvalidLocatorID + + case loc.ScriptKey.IsEqual(&emptyKey): + return "", ErrInvalidLocatorKey + } assetID := hex.EncodeToString(loc.AssetID[:]) scriptKey := hex.EncodeToString(loc.ScriptKey.SerializeCompressed()) - return filepath.Join(rootPath, assetID, scriptKey+TaprootAssetsFileSuffix), nil + searchPattern := filepath.Join(rootPath, assetID, scriptKey+"*") + matches, err := filepath.Glob(searchPattern) + if err != nil { + return "", fmt.Errorf("error listing proof files: %w", err) + } + + switch { + // We have no proof for this script key. + case len(matches) == 0: + return "", ErrProofNotFound + + // Exactly one proof for this script key, we'll return it. + case len(matches) == 1: + return matches[0], nil + + // User needs to specify the outpoint as well, since we have multiple + // proofs for this script key. + default: + return "", ErrMultipleProofs + } } -// FetchProof fetches a proof for an asset uniquely identified by the -// passed ProofIdentifier. +// extractLastProof extracts the last proof from a proof file. +func extractLastProof(fileContent Blob) (*Proof, error) { + parsedFile := &File{} + err := parsedFile.Decode(bytes.NewReader(fileContent)) + if err != nil { + return nil, fmt.Errorf("error parsing proof file: %w", err) + } + + // To find out the new file name, we need to parse the proof + // file and extract the last proof in it. + lastProof, err := parsedFile.LastProof() + if err != nil { + return nil, fmt.Errorf("error extracting last proof from "+ + "proof file: %w", err) + } + + return lastProof, nil +} + +// FetchProof fetches a proof for an asset uniquely identified by the passed +// ProofIdentifier. // -// If a proof cannot be found, then ErrProofNotFound should be -// returned. +// If a proof cannot be found, then ErrProofNotFound should be returned. // // NOTE: This implements the Archiver interface. func (f *FileArchiver) FetchProof(_ context.Context, id Locator) (Blob, error) { // All our on-disk storage is based on asset IDs, so to look up a path, // we just need to compute the full file path and see if it exists on // disk. - proofPath, err := genProofFilePath(f.proofPath, id) + proofPath, err := lookupProofFilePath(f.proofPath, id) if err != nil { return nil, fmt.Errorf("unable to make proof file path: %w", err) @@ -320,7 +430,7 @@ func (f *FileArchiver) HasProof(_ context.Context, id Locator) (bool, error) { // All our on-disk storage is based on asset IDs, so to look up a path, // we just need to compute the full file path and see if it exists on // disk. - proofPath, err := genProofFilePath(f.proofPath, id) + proofPath, err := lookupProofFilePath(f.proofPath, id) if err != nil { return false, fmt.Errorf("unable to make proof file path: %w", err) @@ -352,9 +462,16 @@ func (f *FileArchiver) FetchProofs(_ context.Context, continue } - scriptKeyBytes, err := hex.DecodeString(strings.ReplaceAll( + parts := strings.Split(strings.ReplaceAll( fileName, TaprootAssetsFileSuffix, "", - )) + ), "-") + if len(parts) != 3 { + return nil, fmt.Errorf("malformed proof file name "+ + "'%s', expected two parts, got %d", fileName, + len(parts)) + } + + scriptKeyBytes, err := hex.DecodeString(parts[0]) if err != nil { return nil, fmt.Errorf("malformed proof file name, "+ "unable to decode script key: %w", err) @@ -372,10 +489,21 @@ func (f *FileArchiver) FetchProofs(_ context.Context, return nil, fmt.Errorf("unable to read proof: %w", err) } + // We only have part of the outpoint in the file name, so we + // need to read the file and parse the last proof to extract the + // outpoint. + lastProof, err := extractLastProof(proofFile) + if err != nil { + return nil, fmt.Errorf("unable to extract last proof "+ + "from proof file: %w", err) + } + + outPoint := lastProof.OutPoint() proofs[idx] = &AnnotatedProof{ Locator: Locator{ AssetID: &id, ScriptKey: *scriptKey, + OutPoint: &outPoint, }, Blob: proofFile, } @@ -396,7 +524,9 @@ func (f *FileArchiver) ImportProofs(_ context.Context, proofs ...*AnnotatedProof) error { for _, proof := range proofs { - proofPath, err := genProofFilePath(f.proofPath, proof.Locator) + proofPath, err := genProofFileStoragePath( + f.proofPath, proof.Locator, + ) if err != nil { return err } @@ -411,6 +541,9 @@ func (f *FileArchiver) ImportProofs(_ context.Context, "%s does not exist", proofPath) } + log.Tracef("Importing proof file %s (replace=%v)", proofPath, + replace) + err = os.WriteFile(proofPath, proof.Blob, 0666) if err != nil { return fmt.Errorf("unable to store proof: %v", err) diff --git a/proof/archive_test.go b/proof/archive_test.go index f1789abbe..27c3366d0 100644 --- a/proof/archive_test.go +++ b/proof/archive_test.go @@ -3,11 +3,10 @@ package proof import ( "bytes" "context" - "math/rand" - "os" "testing" "time" + "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/internal/test" "github.com/stretchr/testify/require" @@ -17,14 +16,74 @@ var ( testTimeout = 5 * time.Second ) -func randAssetID(t *testing.T) *asset.ID { +func randAssetID() *asset.ID { var a asset.ID - _, err := rand.Read(a[:]) - require.NoError(t, err) + copy(a[:], test.RandBytes(32)) return &a } +// TestFileArchiverProofCollision tests that we can store two different proofs +// with the same script key but different outpoints. +func TestFileArchiverProofCollision(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + // First, we'll make a temp directory we'll use as the root of our file + // system. + tempDir := t.TempDir() + + fileArchive, err := NewFileArchiver(tempDir) + require.NoError(t, err) + + // We store two different proofs with the same script key but different + // outpoints. This should result in two different files on disk. + var ( + scriptKey = *test.RandPubKey(t) + assetID = randAssetID() + testOp1 = test.RandOp(t) + testOp2 = test.RandOp(t) + locator1 = Locator{ + AssetID: assetID, + ScriptKey: scriptKey, + OutPoint: &testOp1, + } + locator2 = Locator{ + AssetID: assetID, + ScriptKey: scriptKey, + OutPoint: &testOp2, + } + blob1 = []byte("this is the first blob") + blob2 = []byte("this is the second blob") + ) + err = fileArchive.ImportProofs( + ctx, MockHeaderVerifier, MockGroupVerifier, false, + &AnnotatedProof{ + Locator: locator1, + Blob: blob1, + }, + ) + require.NoError(t, err) + err = fileArchive.ImportProofs( + ctx, MockHeaderVerifier, MockGroupVerifier, false, + &AnnotatedProof{ + Locator: locator2, + Blob: blob2, + }, + ) + require.NoError(t, err) + + // When retrieving the proofs, we should get the same blobs back. + proof1, err := fileArchive.FetchProof(ctx, locator1) + require.NoError(t, err) + require.EqualValues(t, blob1, proof1) + + proof2, err := fileArchive.FetchProof(ctx, locator2) + require.NoError(t, err) + require.EqualValues(t, blob2, proof2) +} + // TestFileArchiver tests that the file archiver functions as advertised when // it comes to writing and also reading proof file on disk. func TestFileArchiver(t *testing.T) { @@ -32,12 +91,9 @@ func TestFileArchiver(t *testing.T) { // First, we'll make a temp directory we'll use as the root of our file // system. - dir, err := os.MkdirTemp("", "tap-proofs-") - require.NoError(t, err) - - defer os.RemoveAll(dir) + tempDir := t.TempDir() - fileArchive, err := NewFileArchiver(dir) + fileArchive, err := NewFileArchiver(tempDir) require.NoError(t, err) // We'll use a fake verifier that just returns that the proof is valid. @@ -47,7 +103,7 @@ func TestFileArchiver(t *testing.T) { ctx := context.Background() - var tests = []struct { + var testCases = []struct { name string locator Locator @@ -56,27 +112,28 @@ func TestFileArchiver(t *testing.T) { fetchFunc func(*FileArchiver) error - expectedErorr error + expectedFetchError error + expectedStoreError error }{ // Attempting to fetch a proof that doesn't exist on disk should // return an error. { name: "proof not found", locator: Locator{ - AssetID: randAssetID(t), + AssetID: randAssetID(), ScriptKey: *test.RandPubKey(t), }, - expectedErorr: ErrProofNotFound, + expectedFetchError: ErrProofNotFound, }, - // Attempting to fetch a file on disk that doesn't have an asset ID - // specified should return an error. + // Attempting to fetch a file on disk that doesn't have an asset + // ID specified should return an error. { name: "invalid asset ID", locator: Locator{ ScriptKey: *test.RandPubKey(t), }, - expectedErorr: ErrInvalidLocatorID, + expectedFetchError: ErrInvalidLocatorID, }, // Fetching w/ the assetID, but not script key should return an @@ -84,9 +141,23 @@ func TestFileArchiver(t *testing.T) { { name: "invalid script key", locator: Locator{ - AssetID: randAssetID(t), + AssetID: randAssetID(), }, - expectedErorr: ErrInvalidLocatorKey, + expectedFetchError: ErrInvalidLocatorKey, + }, + + // Storing a proof with assetID and script key, but no outpoint + // should return an error as well. + { + name: "invalid outpoint", + locator: Locator{ + AssetID: randAssetID(), + ScriptKey: *test.RandPubKey(t), + }, + proofBlob: func() Blob { + return bytes.Repeat([]byte{0x01}, 100) + }, + expectedStoreError: ErrOutPointMissing, }, // We should be able to insert a proof, then get it right back @@ -94,36 +165,48 @@ func TestFileArchiver(t *testing.T) { { name: "proof happy path", locator: Locator{ - AssetID: randAssetID(t), + AssetID: randAssetID(), ScriptKey: *test.RandPubKey(t), + OutPoint: &wire.OutPoint{}, }, proofBlob: func() Blob { return bytes.Repeat([]byte{0x01}, 100) }, }, } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { var proofBlob Blob - if test.proofBlob != nil { - proofBlob = test.proofBlob() + if testCase.proofBlob != nil { + proofBlob = testCase.proofBlob() proof := &AnnotatedProof{ Blob: proofBlob, - Locator: test.locator, + Locator: testCase.locator, } - require.NoError( - t, archive.ImportProofs( - ctx, MockHeaderVerifier, - MockGroupVerifier, false, - proof, - ), + + err = archive.ImportProofs( + ctx, MockHeaderVerifier, + MockGroupVerifier, false, proof, ) + + if testCase.expectedStoreError != nil { + require.ErrorIs( + t, err, + testCase.expectedStoreError, + ) + + return + } + + require.NoError(t, err) } - diskProof, err := archive.FetchProof(ctx, test.locator) - require.ErrorIs(t, err, test.expectedErorr) + diskProof, err := archive.FetchProof( + ctx, testCase.locator, + ) + require.ErrorIs(t, err, testCase.expectedFetchError) - if test.proofBlob != nil { + if testCase.proofBlob != nil { require.Equal(t, proofBlob, diskProof) } }) From ce6f5fe63ccea15ce44e15dc913dbbb74a046523 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:57 +0100 Subject: [PATCH 07/19] proof: add migration for proof files under old name With this commit we make sure that whenever we start the file archive we migrate any proof files that use the old name to the new naming scheme. --- proof/archive.go | 108 +++++++++++++++++++++++++++++++++++-- proof/archive_test.go | 122 ++++++++++++++++++++++++++++++++++++++++++ proof/proof_test.go | 55 ++++++++++++------- 3 files changed, 261 insertions(+), 24 deletions(-) diff --git a/proof/archive.go b/proof/archive.go index ccfdf89c7..7506cbc84 100644 --- a/proof/archive.go +++ b/proof/archive.go @@ -9,6 +9,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" "time" @@ -21,9 +22,13 @@ import ( ) const ( + // TaprootAssetsFileEnding is the main file suffix for the Taproot Asset + // proof files stored on disk, without the dot. + TaprootAssetsFileEnding = "assetproof" + // TaprootAssetsFileSuffix is the main file suffix for the Taproot Asset - // proof files stored on disk. - TaprootAssetsFileSuffix = ".assetproof" + // proof files stored on disk, including the dot. + TaprootAssetsFileSuffix = "." + TaprootAssetsFileEnding // ProofDirName is the name of the directory we'll use to store our // proofs. @@ -62,6 +67,17 @@ var ( "multiple proofs found with asset ID and script key, specify " + "outpoint to disambiguate", ) + + // OutPointFileNamePattern is the regular expression we use to find out + // if a proof file on disk already has the new naming scheme. The first + // number (66) is the number of hex characters in the compressed script + // key, the second number (32) is the number of hex characters in the + // truncated outpoint txid (16 bytes of the txid). The last part is the + // variable length outpoint index (at least one digit). + OutPointFileNamePattern = regexp.MustCompile( + `^[0-9a-f]{66}-[0-9a-f]{32}-[0-9]+\.` + + TaprootAssetsFileEnding + "$", + ) ) // Locator is able to uniquely identify a proof in the extended Taproot Asset @@ -280,6 +296,16 @@ func NewFileArchiver(dirName string) (*FileArchiver, error) { return nil, fmt.Errorf("unable to create proof dir: %w", err) } + // We need to make sure that all our proof files have the new naming + // scheme. If they don't, we'll rename them now. This might take quite a + // while since we need to read each proof file and parse it to extract + // the outpoint and then rename it. + err := migrateOldFileNames(proofPath) + if err != nil { + return nil, fmt.Errorf("error migrating old proof file "+ + "names: %w", err) + } + return &FileArchiver{ proofPath: proofPath, eventDistributor: fn.NewEventDistributor[Blob](), @@ -312,8 +338,9 @@ func genProofFileStoragePath(rootPath string, loc Locator) (string, error) { assetID := hex.EncodeToString(loc.AssetID[:]) truncatedHash := loc.OutPoint.Hash.String()[:outpointTruncateLength] - fileName := fmt.Sprintf("%x-%s-%d%s", loc.ScriptKey.SerializeCompressed(), - truncatedHash, loc.OutPoint.Index, TaprootAssetsFileSuffix) + fileName := fmt.Sprintf("%x-%s-%d.%s", + loc.ScriptKey.SerializeCompressed(), truncatedHash, + loc.OutPoint.Index, TaprootAssetsFileEnding) return filepath.Join(rootPath, assetID, fileName), nil } @@ -396,6 +423,79 @@ func extractLastProof(fileContent Blob) (*Proof, error) { return lastProof, nil } +// migrateOldFileNames looks for proof files in the root path that don't conform +// to the new naming scheme and renames them to the new scheme. +func migrateOldFileNames(rootPath string) error { + // List all files matching rootPath/*/*.assetproof. + searchPattern := filepath.Join( + rootPath, "*", "*"+TaprootAssetsFileSuffix, + ) + oldProofs, err := filepath.Glob(searchPattern) + if err != nil { + return fmt.Errorf("error listing old proof files: %w", err) + } + + // Skip files that already have the new naming pattern. + oldProofs = fn.Filter(oldProofs, func(path string) bool { + return !OutPointFileNamePattern.MatchString(filepath.Base(path)) + }) + + // Nothing to migrate, let's not even log a message to avoid startup + // log spam. + if len(oldProofs) == 0 { + return nil + } + + log.Infof("Found %d proof files in %s with old naming scheme, "+ + "renaming now (will take a while)", len(oldProofs), rootPath) + + var ( + startTime = time.Now() + numFilesRenamed int + ) + for _, oldPath := range oldProofs { + proofFile, err := os.ReadFile(oldPath) + if err != nil { + return fmt.Errorf("unable to read proof: %w", err) + } + + // To find out the new file name, we need to parse the proof + // file and extract the last proof in it. + lastProof, err := extractLastProof(proofFile) + if err != nil { + return fmt.Errorf("unable to extract last proof from "+ + "proof file: %w", err) + } + + newFileName, err := genProofFileStoragePath(rootPath, Locator{ + AssetID: fn.Ptr(lastProof.Asset.ID()), + ScriptKey: *lastProof.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(lastProof.OutPoint()), + }) + if err != nil { + return fmt.Errorf("error generating new file name: "+ + "%w", err) + } + + err = os.Rename(oldPath, newFileName) + if err != nil { + return fmt.Errorf("error renaming file %s to %s: %w", + oldPath, newFileName, err) + } + + numFilesRenamed++ + if numFilesRenamed%1000 == 0 { + log.Infof("Renamed %d of %d old files", numFilesRenamed, + len(oldProofs)) + } + } + + log.Infof("Done renaming %d proof files, took %v", len(oldProofs), + time.Since(startTime)) + + return nil +} + // FetchProof fetches a proof for an asset uniquely identified by the passed // ProofIdentifier. // diff --git a/proof/archive_test.go b/proof/archive_test.go index 27c3366d0..894b0b1d8 100644 --- a/proof/archive_test.go +++ b/proof/archive_test.go @@ -3,11 +3,15 @@ package proof import ( "bytes" "context" + "encoding/hex" + "os" + "path/filepath" "testing" "time" "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/fn" "github.com/lightninglabs/taproot-assets/internal/test" "github.com/stretchr/testify/require" ) @@ -212,3 +216,121 @@ func TestFileArchiver(t *testing.T) { }) } } + +// TestMigrateOldFileNames tests that we can migrate old file names to the new +// format. +func TestMigrateOldFileNames(t *testing.T) { + // First, we'll make a temp directory we'll use as the root of our file + // system. + tempDir := t.TempDir() + proofDir := filepath.Join(tempDir, ProofDirName) + + toFileBlob := func(proof Proof) []byte { + file, err := NewFile(V0, proof, proof) + require.NoError(t, err) + + var buf bytes.Buffer + err = file.Encode(&buf) + require.NoError(t, err) + + return buf.Bytes() + } + + // storeProofOldName is a helper that stores a proof file under the old + // naming scheme. + storeProofOldName := func(proof Proof) { + assetID := hex.EncodeToString(fn.ByteSlice(proof.Asset.ID())) + scriptKey := proof.Asset.ScriptKey.PubKey + fileName := filepath.Join( + proofDir, assetID, hex.EncodeToString( + scriptKey.SerializeCompressed(), + )+TaprootAssetsFileSuffix, + ) + + err := os.MkdirAll(filepath.Dir(fileName), 0755) + require.NoError(t, err) + err = os.WriteFile(fileName, toFileBlob(proof), 0644) + require.NoError(t, err) + } + + // storeProofNewName is a helper that stores a proof file under the new + // naming scheme. + storeProofNewName := func(proof Proof) { + fileName, err := genProofFileStoragePath(proofDir, Locator{ + AssetID: fn.Ptr(proof.Asset.ID()), + ScriptKey: *proof.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(proof.OutPoint()), + }) + require.NoError(t, err) + + err = os.MkdirAll(filepath.Dir(fileName), 0755) + require.NoError(t, err) + err = os.WriteFile(fileName, toFileBlob(proof), 0644) + require.NoError(t, err) + } + + // assertProofAtNewName is a helper that asserts that a proof file is + // stored under the new naming scheme. + assertProofAtNewName := func(proof Proof) { + fileName, err := genProofFileStoragePath(proofDir, Locator{ + AssetID: fn.Ptr(proof.Asset.ID()), + ScriptKey: *proof.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(proof.OutPoint()), + }) + require.NoError(t, err) + + _, err = os.Stat(fileName) + require.NoError(t, err) + } + + testBlocks := readTestData(t) + oddTxBlock := testBlocks[0] + + genesis1 := asset.RandGenesis(t, asset.Collectible) + genesis2 := asset.RandGenesis(t, asset.Collectible) + scriptKey1 := test.RandPubKey(t) + scriptKey2 := test.RandPubKey(t) + + // We create 4 different proofs with the old naming scheme. + proof1 := randomProof(t, genesis1, scriptKey1, oddTxBlock, 0, 1) + storeProofOldName(proof1) + proof2 := randomProof(t, genesis1, scriptKey2, oddTxBlock, 0, 1) + storeProofOldName(proof2) + proof3 := randomProof(t, genesis2, scriptKey1, oddTxBlock, 1, 1) + storeProofOldName(proof3) + proof4 := randomProof(t, genesis2, scriptKey2, oddTxBlock, 1, 1) + storeProofOldName(proof4) + + // We also create a proof with the new naming scheme. + proof5 := randomProof(t, genesis1, scriptKey1, oddTxBlock, 1, 1) + storeProofNewName(proof5) + + // We now create the file archive and expect the 4 proofs to be renamed. + fileArchive, err := NewFileArchiver(tempDir) + require.NoError(t, err) + + // After creating the archiver, we should now have all 4 proofs with the + // old name be moved/renamed to the new name. + assertProofAtNewName(proof1) + assertProofAtNewName(proof2) + assertProofAtNewName(proof3) + assertProofAtNewName(proof4) + + // The proof that was already there with the new name should still be + // there. + assertProofAtNewName(proof5) + + // We should be able to import a new proof, and it should be stored + // under the new naming scheme. + proof6 := randomProof(t, genesis2, scriptKey2, oddTxBlock, 2, 1) + err = fileArchive.ImportProofs(nil, nil, nil, false, &AnnotatedProof{ + Locator: Locator{ + AssetID: fn.Ptr(proof6.Asset.ID()), + ScriptKey: *proof6.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(proof6.OutPoint()), + }, + Blob: toFileBlob(proof6), + }) + require.NoError(t, err) + assertProofAtNewName(proof6) +} diff --git a/proof/proof_test.go b/proof/proof_test.go index 24b9bf66e..a273b852c 100644 --- a/proof/proof_test.go +++ b/proof/proof_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/hex" + "encoding/json" "fmt" "os" "path/filepath" @@ -137,17 +138,13 @@ func assertEqualProof(t *testing.T, expected, actual *Proof) { require.Equal(t, expected.ChallengeWitness, actual.ChallengeWitness) } -func TestProofEncoding(t *testing.T) { - t.Parallel() - - testBlocks := readTestData(t) - oddTxBlock := testBlocks[0] +func randomProof(t *testing.T, genesis asset.Genesis, + scriptKey *btcec.PublicKey, block wire.MsgBlock, txIndex int, + outputIndex uint32) Proof { - txMerkleProof, err := NewTxMerkleProof(oddTxBlock.Transactions, 0) + txMerkleProof, err := NewTxMerkleProof(block.Transactions, txIndex) require.NoError(t, err) - genesis := asset.RandGenesis(t, asset.Collectible) - scriptKey := test.RandPubKey(t) tweakedScriptKey := asset.NewScriptKey(scriptKey) protoAsset := asset.NewAssetNoErr( t, genesis, 1, 0, 0, tweakedScriptKey, nil, @@ -168,26 +165,26 @@ func TestProofEncoding(t *testing.T) { }, ) require.NoError(t, err) - asset := assets[0] - asset.GroupKey.RawKey = keychain.KeyDescriptor{} + proofAsset := assets[0] + proofAsset.GroupKey.RawKey = keychain.KeyDescriptor{} // Empty the group witness, since it will eventually be stored as the // asset's witness within the proof. // TODO(guggero): Actually store the witness in the proof. - asset.GroupKey.Witness = nil + proofAsset.GroupKey.Witness = nil // Empty the raw script key, since we only serialize the tweaked // pubkey. We'll also force the main script key to be an x-only key as // well. - asset.ScriptKey.PubKey, err = schnorr.ParsePubKey( - schnorr.SerializePubKey(asset.ScriptKey.PubKey), + proofAsset.ScriptKey.PubKey, err = schnorr.ParsePubKey( + schnorr.SerializePubKey(proofAsset.ScriptKey.PubKey), ) require.NoError(t, err) - asset.ScriptKey.TweakedScriptKey = nil + proofAsset.ScriptKey.TweakedScriptKey = nil _, commitmentProof, err := mintCommitment.Proof( - asset.TapCommitmentKey(), asset.AssetCommitmentKey(), + proofAsset.TapCommitmentKey(), proofAsset.AssetCommitmentKey(), ) require.NoError(t, err) @@ -198,15 +195,15 @@ func TestProofEncoding(t *testing.T) { testBranchPreimage := commitment.NewPreimageFromBranch( txscript.NewTapBranch(leaf1, leaf2), ) - proof := Proof{ + return Proof{ PrevOut: genesis.FirstPrevOut, - BlockHeader: oddTxBlock.Header, + BlockHeader: block.Header, BlockHeight: 42, - AnchorTx: *oddTxBlock.Transactions[0], + AnchorTx: *block.Transactions[txIndex], TxMerkleProof: *txMerkleProof, - Asset: *asset, + Asset: *proofAsset, InclusionProof: TaprootProof{ - OutputIndex: 1, + OutputIndex: outputIndex, InternalKey: test.RandPubKey(t), CommitmentProof: &CommitmentProof{ Proof: *commitmentProof, @@ -260,6 +257,18 @@ func TestProofEncoding(t *testing.T) { GenesisReveal: &genesis, GroupKeyReveal: &groupReveal, } +} + +func TestProofEncoding(t *testing.T) { + t.Parallel() + + testBlocks := readTestData(t) + oddTxBlock := testBlocks[0] + + genesis := asset.RandGenesis(t, asset.Collectible) + scriptKey := test.RandPubKey(t) + proof := randomProof(t, genesis, scriptKey, oddTxBlock, 0, 1) + file, err := NewFile(V0, proof, proof) require.NoError(t, err) proof.AdditionalInputs = []File{*file, *file} @@ -841,6 +850,12 @@ func TestProofVerification(t *testing.T) { require.NoError(t, p.Asset.Encode(&buf)) t.Logf("Proof asset encoded: %x", buf.Bytes()) + ta := asset.NewTestFromAsset(t, &p.Asset) + assetJSON, err := json.Marshal(ta) + require.NoError(t, err) + + t.Logf("Proof asset JSON: %s", assetJSON) + // Ensure that verification of a proof of unknown version fails. p.Version = TransitionVersion(212) From be57c942b7f51d643de1372f394407646e5604a9 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:58 +0100 Subject: [PATCH 08/19] multi: move ChainAsset from tapdb to asset pkg --- asset/asset.go | 52 +++++++++++++++++++++++ rpcserver.go | 5 +-- tapcfg/server.go | 2 +- tapdb/asset_minting_test.go | 8 ++-- tapdb/assets_store.go | 73 ++++++-------------------------- tapgarden/re-org_watcher_test.go | 2 +- 6 files changed, 73 insertions(+), 69 deletions(-) diff --git a/asset/asset.go b/asset/asset.go index f5482f434..dab13565e 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -10,6 +10,7 @@ import ( "io" "reflect" "strings" + "time" "unicode" "unicode/utf8" @@ -17,6 +18,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/lndclient" @@ -1621,3 +1623,53 @@ func ValidateAssetName(name string) error { return nil } + +// ChainAsset is a wrapper around the base asset struct that includes +// information detailing where in the chain the asset is currently anchored. +type ChainAsset struct { + *Asset + + // IsSpent indicates whether the above asset was previously spent. + IsSpent bool + + // AnchorTx is the transaction that anchors this chain asset. + AnchorTx *wire.MsgTx + + // AnchorBlockHash is the blockhash that mined the anchor tx. + AnchorBlockHash chainhash.Hash + + // AnchorBlockHeight is the height of the block that mined the anchor + // tx. + AnchorBlockHeight uint32 + + // AnchorOutpoint is the outpoint that commits to the asset. + AnchorOutpoint wire.OutPoint + + // AnchorInternalKey is the raw internal key that was used to create the + // anchor Taproot output key. + AnchorInternalKey *btcec.PublicKey + + // AnchorMerkleRoot is the Taproot merkle root hash of the anchor output + // the asset was committed to. If there is no Tapscript sibling, this is + // equal to the Taproot Asset root commitment hash. + AnchorMerkleRoot []byte + + // AnchorTapscriptSibling is the serialized preimage of a Tapscript + // sibling, if there was one. If this is empty, then the + // AnchorTapscriptSibling hash is equal to the Taproot root hash of the + // anchor output. + AnchorTapscriptSibling []byte + + // AnchorLeaseOwner is the identity of the application that currently + // has a lease on this UTXO. If empty/nil, then the UTXO is not + // currently leased. A lease means that the UTXO is being + // reserved/locked to be spent in an upcoming transaction and that it + // should not be available for coin selection through any of the wallet + // RPCs. + AnchorLeaseOwner [32]byte + + // AnchorLeaseExpiry is the expiry of the lease. If the expiry is nil or + // the time is in the past, then the lease is not valid and the UTXO is + // available for coin selection. + AnchorLeaseExpiry *time.Time +} diff --git a/rpcserver.go b/rpcserver.go index f2008d8dd..9a3064ac6 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -29,7 +29,6 @@ import ( "github.com/lightninglabs/taproot-assets/mssmt" "github.com/lightninglabs/taproot-assets/proof" "github.com/lightninglabs/taproot-assets/rpcperms" - "github.com/lightninglabs/taproot-assets/tapdb" "github.com/lightninglabs/taproot-assets/tapfreighter" "github.com/lightninglabs/taproot-assets/tapgarden" "github.com/lightninglabs/taproot-assets/tappsbt" @@ -720,7 +719,7 @@ func (r *rpcServer) fetchRpcAssets(ctx context.Context, withWitness, return rpcAssets, nil } -func (r *rpcServer) marshalChainAsset(ctx context.Context, a *tapdb.ChainAsset, +func (r *rpcServer) marshalChainAsset(ctx context.Context, a *asset.ChainAsset, withWitness bool) (*taprpc.Asset, error) { rpcAsset, err := taprpc.MarshalAsset( @@ -1397,7 +1396,7 @@ func (r *rpcServer) marshalProof(ctx context.Context, p *proof.Proof, } } - rpcAsset, err := r.marshalChainAsset(ctx, &tapdb.ChainAsset{ + rpcAsset, err := r.marshalChainAsset(ctx, &asset.ChainAsset{ Asset: &p.Asset, AnchorTx: &p.AnchorTx, AnchorBlockHash: p.BlockHeader.BlockHash(), diff --git a/tapcfg/server.go b/tapcfg/server.go index 727405119..704f3cc5b 100644 --- a/tapcfg/server.go +++ b/tapcfg/server.go @@ -250,7 +250,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger, } return fn.Map( - assets, func(a *tapdb.ChainAsset) *asset.Asset { + assets, func(a *asset.ChainAsset) *asset.Asset { return a.Asset }, ), nil diff --git a/tapdb/asset_minting_test.go b/tapdb/asset_minting_test.go index d89a110ab..f984136c0 100644 --- a/tapdb/asset_minting_test.go +++ b/tapdb/asset_minting_test.go @@ -765,17 +765,17 @@ func TestCommitBatchChainActions(t *testing.T) { // Count the number of assets with a group key. Each grouped asset // should have a grouped genesis witness. - groupCount := fn.Count(assets, func(a *ChainAsset) bool { + groupCount := fn.Count(assets, func(a *asset.ChainAsset) bool { return a.GroupKey != nil }) - groupWitnessCount := fn.Count(assets, func(a *ChainAsset) bool { + groupWitnessCount := fn.Count(assets, func(a *asset.ChainAsset) bool { return a.HasGenesisWitnessForGroup() }) require.Equal(t, groupCount, groupWitnessCount) // All the assets returned should have the genesis prev ID set up. ungroupedCount := len(assets) - groupCount - genesisWitnessCount := fn.Count(assets, func(a *ChainAsset) bool { + genesisWitnessCount := fn.Count(assets, func(a *asset.ChainAsset) bool { return a.HasGenesisWitness() }) require.Equal(t, ungroupedCount, genesisWitnessCount) @@ -783,7 +783,7 @@ func TestCommitBatchChainActions(t *testing.T) { // All the assets should also have a matching asset version as the // seedlings we created. mintingBatch := randAssetCtx.mintingBatch - require.True(t, fn.All(assets, func(dbAsset *ChainAsset) bool { + require.True(t, fn.All(assets, func(dbAsset *asset.ChainAsset) bool { seedling, ok := mintingBatch.Seedlings[dbAsset.Genesis.Tag] if !ok { t.Logf("seedling for %v not found", diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index bb0bd26bf..edf10e44d 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -361,56 +361,6 @@ func NewAssetStore(db BatchedAssetStore, clock clock.Clock) *AssetStore { } } -// ChainAsset is a wrapper around the base asset struct that includes -// information detailing where in the chain the asset is currently anchored. -type ChainAsset struct { - *asset.Asset - - // IsSpent indicates whether the above asset was previously spent. - IsSpent bool - - // AnchorTx is the transaction that anchors this chain asset. - AnchorTx *wire.MsgTx - - // AnchorBlockHash is the blockhash that mined the anchor tx. - AnchorBlockHash chainhash.Hash - - // AnchorBlockHeight is the height of the block that mined the anchor - // tx. - AnchorBlockHeight uint32 - - // AnchorOutpoint is the outpoint that commits to the asset. - AnchorOutpoint wire.OutPoint - - // AnchorInternalKey is the raw internal key that was used to create the - // anchor Taproot output key. - AnchorInternalKey *btcec.PublicKey - - // AnchorMerkleRoot is the Taproot merkle root hash of the anchor output - // the asset was committed to. If there is no Tapscript sibling, this is - // equal to the Taproot Asset root commitment hash. - AnchorMerkleRoot []byte - - // AnchorTapscriptSibling is the serialized preimage of a Tapscript - // sibling, if there was one. If this is empty, then the - // AnchorTapscriptSibling hash is equal to the Taproot root hash of the - // anchor output. - AnchorTapscriptSibling []byte - - // AnchorLeaseOwner is the identity of the application that currently - // has a lease on this UTXO. If empty/nil, then the UTXO is not - // currently leased. A lease means that the UTXO is being - // reserved/locked to be spent in an upcoming transaction and that it - // should not be available for coin selection through any of the wallet - // RPCs. - AnchorLeaseOwner [32]byte - - // AnchorLeaseExpiry is the expiry of the lease. If the expiry is nil or - // the time is in the past, then the lease is not valid and the UTXO is - // available for coin selection. - AnchorLeaseExpiry *time.Time -} - // ManagedUTXO holds information about a given UTXO we manage. type ManagedUTXO struct { // OutPoint is the outpoint of the UTXO. @@ -571,9 +521,9 @@ func parseAssetWitness(input AssetWitness) (asset.Witness, error) { // the witnesses of those assets to a set of normal ChainAsset structs needed // by a higher level application. func (a *AssetStore) dbAssetsToChainAssets(dbAssets []ConfirmedAsset, - witnesses assetWitnesses) ([]*ChainAsset, error) { + witnesses assetWitnesses) ([]*asset.ChainAsset, error) { - chainAssets := make([]*ChainAsset, len(dbAssets)) + chainAssets := make([]*asset.ChainAsset, len(dbAssets)) for i := range dbAssets { sprout := dbAssets[i] @@ -764,7 +714,7 @@ func (a *AssetStore) dbAssetsToChainAssets(dbAssets []ConfirmedAsset, "internal key: %w", err) } - chainAssets[i] = &ChainAsset{ + chainAssets[i] = &asset.ChainAsset{ Asset: assetSprout, IsSpent: sprout.Spent, AnchorTx: anchorTx, @@ -1054,7 +1004,8 @@ func (a *AssetStore) FetchGroupedAssets(ctx context.Context) ( // FetchAllAssets fetches the set of confirmed assets stored on disk. func (a *AssetStore) FetchAllAssets(ctx context.Context, includeSpent, - includeLeased bool, query *AssetQueryFilters) ([]*ChainAsset, error) { + includeLeased bool, query *AssetQueryFilters) ([]*asset.ChainAsset, + error) { var ( dbAssets []ConfirmedAsset @@ -1658,7 +1609,7 @@ func (a *AssetStore) RemoveSubscriber( // queryChainAssets queries the database for assets matching the passed filter. // The returned assets have all anchor and witness information populated. func (a *AssetStore) queryChainAssets(ctx context.Context, q ActiveAssetsStore, - filter QueryAssetFilters) ([]*ChainAsset, error) { + filter QueryAssetFilters) ([]*asset.ChainAsset, error) { dbAssets, assetWitnesses, err := fetchAssetsWithWitness( ctx, q, filter, @@ -1821,10 +1772,12 @@ func (a *AssetStore) queryCommitments(ctx context.Context, error) { var ( - matchingAssets []*ChainAsset - chainAnchorToAssets = make(map[wire.OutPoint][]*ChainAsset) - anchorPoints = make(map[wire.OutPoint]AnchorPoint) - err error + matchingAssets []*asset.ChainAsset + chainAnchorToAssets = make( + map[wire.OutPoint][]*asset.ChainAsset, + ) + anchorPoints = make(map[wire.OutPoint]AnchorPoint) + err error ) readOpts := NewAssetStoreReadTx() @@ -1905,7 +1858,7 @@ func (a *AssetStore) queryCommitments(ctx context.Context, // Fetch the asset leaves from each chain asset, and then // build a Taproot Asset commitment from this set of assets. - fetchAsset := func(cAsset *ChainAsset) *asset.Asset { + fetchAsset := func(cAsset *asset.ChainAsset) *asset.Asset { return cAsset.Asset } diff --git a/tapgarden/re-org_watcher_test.go b/tapgarden/re-org_watcher_test.go index d4329e777..29150acbd 100644 --- a/tapgarden/re-org_watcher_test.go +++ b/tapgarden/re-org_watcher_test.go @@ -53,7 +53,7 @@ func newReOrgWatcherHarness(t *testing.T) *reOrgWatcherHarness { ChainBridge: chainBridge, GroupVerifier: GenMockGroupVerifier(), NonBuriedAssetFetcher: func(ctx context.Context, - minHeight int32) ([]*asset.Asset, error) { + minHeight int32) ([]*asset.ChainAsset, error) { return nil, nil }, From 70d3472b716bfe8054868f08738d9625be6d4bd3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:18:59 +0100 Subject: [PATCH 09/19] multi: always specify proof outpoint in locator Since we now require the proof outpoint to be specified in order to fetch the correct proof, we make sure we supply that part of the proof locator in all situations. We also make sure we specify the outpoint when storing proofs. --- rpcserver.go | 24 ++++++++++++++++++++++-- tapcfg/server.go | 14 ++------------ tapdb/assets_store.go | 16 ++++++++++++++++ tapfreighter/chain_porter.go | 10 ++++++++-- tapfreighter/wallet.go | 1 + tapgarden/caretaker.go | 1 + tapgarden/re-org_watcher.go | 9 ++++++--- 7 files changed, 56 insertions(+), 19 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 9a3064ac6..afb442350 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1523,14 +1523,34 @@ func (r *rpcServer) ImportProof(ctx context.Context, return nil, fmt.Errorf("proof file must be specified") } + // We need to parse the proof file and extract the last proof, so we can + // get the locator that is required for storage. + var proofFile proof.File + err := proofFile.Decode(bytes.NewReader(req.ProofFile)) + if err != nil { + return nil, fmt.Errorf("unable to decode proof file: %w", err) + } + + lastProof, err := proofFile.LastProof() + if err != nil { + return nil, fmt.Errorf("error extracting last proof: %w", err) + } + headerVerifier := tapgarden.GenHeaderVerifier(ctx, r.cfg.ChainBridge) groupVerifier := tapgarden.GenGroupVerifier(ctx, r.cfg.MintingStore) // Now that we know the proof file is at least present, we'll attempt // to import it into the main archive. - err := r.cfg.ProofArchive.ImportProofs( + err = r.cfg.ProofArchive.ImportProofs( ctx, headerVerifier, groupVerifier, false, - &proof.AnnotatedProof{Blob: req.ProofFile}, + &proof.AnnotatedProof{ + Locator: proof.Locator{ + AssetID: fn.Ptr(lastProof.Asset.ID()), + ScriptKey: *lastProof.Asset.ScriptKey.PubKey, + OutPoint: fn.Ptr(lastProof.OutPoint()), + }, + Blob: req.ProofFile, + }, ) if err != nil { return nil, err diff --git a/tapcfg/server.go b/tapcfg/server.go index 704f3cc5b..8c06e2ccf 100644 --- a/tapcfg/server.go +++ b/tapcfg/server.go @@ -12,7 +12,6 @@ import ( tap "github.com/lightninglabs/taproot-assets" "github.com/lightninglabs/taproot-assets/address" "github.com/lightninglabs/taproot-assets/asset" - "github.com/lightninglabs/taproot-assets/fn" "github.com/lightninglabs/taproot-assets/proof" "github.com/lightninglabs/taproot-assets/tapdb" "github.com/lightninglabs/taproot-assets/tapdb/sqlc" @@ -238,22 +237,13 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger, ), ProofArchive: proofArchive, NonBuriedAssetFetcher: func(ctx context.Context, - minHeight int32) ([]*asset.Asset, error) { + minHeight int32) ([]*asset.ChainAsset, error) { - assets, err := assetStore.FetchAllAssets( + return assetStore.FetchAllAssets( ctx, false, true, &tapdb.AssetQueryFilters{ MinAnchorHeight: minHeight, }, ) - if err != nil { - return nil, err - } - - return fn.Map( - assets, func(a *asset.ChainAsset) *asset.Asset { - return a.Asset - }, - ), nil }, SafeDepth: cfg.ReOrgSafeDepth, ErrChan: mainErrChan, diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index edf10e44d..54c2294a2 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -1275,10 +1275,26 @@ func (a *AssetStore) FetchProofs(ctx context.Context, "script key: %w", err) } + f := proof.File{} + err = f.Decode(bytes.NewReader(dbRow.ProofFile)) + if err != nil { + return nil, fmt.Errorf("error "+ + "decoding proof file: %w", err) + } + + lastProof, err := f.LastProof() + if err != nil { + return nil, fmt.Errorf("error "+ + "decoding last proof: %w", err) + } + return &proof.AnnotatedProof{ Locator: proof.Locator{ AssetID: &id, ScriptKey: *scriptKey, + OutPoint: fn.Ptr( + lastProof.OutPoint(), + ), }, Blob: dbRow.ProofFile, }, nil diff --git a/tapfreighter/chain_porter.go b/tapfreighter/chain_porter.go index d345cf2c1..c41630bc2 100644 --- a/tapfreighter/chain_porter.go +++ b/tapfreighter/chain_porter.go @@ -333,7 +333,8 @@ func (p *ChainPorter) storeProofs(sendPkg *sendPackage) error { for _, passiveAsset := range sendPkg.PassiveAssets { newAnnotatedProofFile, rawProof, err := p.updateAssetProofFile( ctx, passiveAsset.GenesisID, - passiveAsset.ScriptKey.PubKey, confEvent, + passiveAsset.ScriptKey.PubKey, + &passiveAsset.PrevAnchorPoint, confEvent, passiveAsset.NewProof, ) if err != nil { @@ -515,6 +516,7 @@ func (p *ChainPorter) fetchInputProof(ctx context.Context, inputProofLocator := proof.Locator{ AssetID: &input.ID, ScriptKey: *scriptKey, + OutPoint: &input.OutPoint, } inputProofBytes, err := p.cfg.AssetProofs.FetchProof( ctx, inputProofLocator, @@ -534,13 +536,15 @@ func (p *ChainPorter) fetchInputProof(ctx context.Context, // updateAssetProofFile retrieves and updates the proof file for the given asset // ID and script key with the new proof. func (p *ChainPorter) updateAssetProofFile(ctx context.Context, assetID asset.ID, - scriptKeyPub *btcec.PublicKey, confEvent *chainntnfs.TxConfirmation, + scriptKeyPub *btcec.PublicKey, outPoint *wire.OutPoint, + confEvent *chainntnfs.TxConfirmation, newProof *proof.Proof) (*proof.AnnotatedProof, *proof.Proof, error) { // Retrieve current proof file. locator := proof.Locator{ AssetID: &assetID, ScriptKey: *scriptKeyPub, + OutPoint: outPoint, } currentProofFileBlob, err := p.cfg.AssetProofs.FetchProof(ctx, locator) if err != nil { @@ -581,6 +585,7 @@ func (p *ChainPorter) updateAssetProofFile(ctx context.Context, assetID asset.ID Locator: proof.Locator{ AssetID: &assetID, ScriptKey: *newProof.Asset.ScriptKey.PubKey, + OutPoint: outPoint, }, Blob: newProofFileBuffer.Bytes(), } @@ -729,6 +734,7 @@ func (p *ChainPorter) transferReceiverProof(pkg *sendPackage) error { proofLocator := proof.Locator{ AssetID: &passiveAsset.GenesisID, ScriptKey: *passiveAsset.ScriptKey.PubKey, + OutPoint: &passiveAsset.PrevAnchorPoint, } proofFileBlob, err := p.cfg.AssetProofs.FetchProof( ctx, proofLocator, diff --git a/tapfreighter/wallet.go b/tapfreighter/wallet.go index fd045aaa0..40897c9d6 100644 --- a/tapfreighter/wallet.go +++ b/tapfreighter/wallet.go @@ -976,6 +976,7 @@ func (f *AssetWallet) setVPacketInputs(ctx context.Context, proofLocator := proof.Locator{ AssetID: &assetID, ScriptKey: *assetInput.Asset.ScriptKey.PubKey, + OutPoint: &assetInput.AnchorPoint, } if assetInput.Asset.GroupKey != nil { proofLocator.GroupKey = &assetInput.Asset.GroupKey.GroupPubKey diff --git a/tapgarden/caretaker.go b/tapgarden/caretaker.go index 530333102..df7709316 100644 --- a/tapgarden/caretaker.go +++ b/tapgarden/caretaker.go @@ -1174,6 +1174,7 @@ func (b *BatchCaretaker) storeMintingProof(ctx context.Context, Locator: proof.Locator{ AssetID: &assetID, ScriptKey: *a.ScriptKey.PubKey, + OutPoint: fn.Ptr(mintingProof.OutPoint()), }, Blob: blob, } diff --git a/tapgarden/re-org_watcher.go b/tapgarden/re-org_watcher.go index 3bb20201e..735253269 100644 --- a/tapgarden/re-org_watcher.go +++ b/tapgarden/re-org_watcher.go @@ -73,7 +73,7 @@ type ReOrgWatcherConfig struct { // NonBuriedAssetFetcher is a function that returns all assets that are // not yet sufficiently deep buried. NonBuriedAssetFetcher func(ctx context.Context, - minHeight int32) ([]*asset.Asset, error) + minHeight int32) ([]*asset.ChainAsset, error) // SafeDepth is the number of confirmations we require before we // consider a transaction to be safely buried in the chain. @@ -159,12 +159,15 @@ func (w *ReOrgWatcher) Start() error { locator := proof.Locator{ AssetID: fn.Ptr(assets[idx].ID()), ScriptKey: *assets[idx].ScriptKey.PubKey, + OutPoint: &assets[idx].AnchorOutpoint, } blob, err := w.cfg.ProofArchive.FetchProof(ctx, locator) if err != nil { startErr = fmt.Errorf("unable to fetch proof "+ - "for asset %v: %w", assets[idx].ID(), - err) + "for asset_id=%v, script_key=%x, "+ + "outpoint=%v: %w", assets[idx].ID(), + locator.ScriptKey.SerializeCompressed(), + locator.OutPoint, err) return } From 9e30b9c5c357052fd3abc13ef906492253e961c3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:01 +0100 Subject: [PATCH 10/19] tapdb+tapfreighter: don't use locator hash as map key To get a unique lookup key we mis-used a proof locator's hash as the key to look up passive asset proofs quickly without needing to scan a slice. Because we don't have the same data available when creating the map as we do when accessing it further down in the asset database, we got a mismatch in the hash and proofs couldn't be found (mainly due to not having access to the previous outpoint of the passive assets being re-anchored). As a compromise we now map the proofs by asset ID and have a slice of proofs in case there are multiple passive assets with the same asset ID. This is better than having a completely flat slice of proofs (as we don't have to scan through all of them) but still requires us to do _some_ iterating. --- tapdb/assets_store.go | 33 +++++++++++++++++++-------------- tapfreighter/chain_porter.go | 17 ++++++++--------- tapfreighter/interface.go | 2 +- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index 54c2294a2..3a53c813a 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -2655,9 +2655,12 @@ func (a *AssetStore) ConfirmParcelDelivery(ctx context.Context, finalProof := conf.FinalProofs[localKey] a.eventDistributor.NotifySubscribers(finalProof.Blob) } - for idx := range conf.PassiveAssetProofFiles { - passiveProof := conf.PassiveAssetProofFiles[idx] - a.eventDistributor.NotifySubscribers(passiveProof) + for assetID := range conf.PassiveAssetProofFiles { + passiveProofs := conf.PassiveAssetProofFiles[assetID] + for idx := range passiveProofs { + passiveProof := passiveProofs[idx] + a.eventDistributor.NotifySubscribers(passiveProof.Blob) + } } return nil @@ -2667,7 +2670,7 @@ func (a *AssetStore) ConfirmParcelDelivery(ctx context.Context, // the given transfer output. func (a *AssetStore) reAnchorPassiveAssets(ctx context.Context, q ActiveAssetsStore, transferID int64, - proofFiles map[[32]byte]proof.Blob) error { + proofFiles map[asset.ID][]*proof.AnnotatedProof) error { passiveAssets, err := q.QueryPassiveAssets(ctx, transferID) if err != nil { @@ -2686,18 +2689,20 @@ func (a *AssetStore) reAnchorPassiveAssets(ctx context.Context, return fmt.Errorf("failed to parse script key: %w", err) } - // Fetch the proof file for this asset. - locator := proof.Locator{ - AssetID: &assetID, - ScriptKey: *scriptKey, - } - locatorHash, err := locator.Hash() - if err != nil { - return fmt.Errorf("failed to hash locator: %w", err) + var proofFile proof.Blob + for _, f := range proofFiles[assetID] { + // Check if this proof is for the script key of the + // passive asset. + if f.Locator.ScriptKey == *scriptKey { + proofFile = f.Blob + + break + } } - proofFile := proofFiles[locatorHash] - if proofFile == nil { + // Something wasn't mapped correctly, we should've found a proof + // for each passive asset. + if len(proofFile) == 0 { return fmt.Errorf("failed to find proof file for " + "passive asset") } diff --git a/tapfreighter/chain_porter.go b/tapfreighter/chain_porter.go index c41630bc2..710160108 100644 --- a/tapfreighter/chain_porter.go +++ b/tapfreighter/chain_porter.go @@ -728,7 +728,7 @@ func (p *ChainPorter) transferReceiverProof(pkg *sendPackage) error { pkg.OutboundPkg.AnchorTx.TxHash()) // Load passive asset proof files from archive. - passiveAssetProofFiles := map[[32]byte]proof.Blob{} + passiveAssetProofFiles := map[asset.ID][]*proof.AnnotatedProof{} for idx := range pkg.OutboundPkg.PassiveAssets { passiveAsset := pkg.OutboundPkg.PassiveAssets[idx] proofLocator := proof.Locator{ @@ -744,14 +744,13 @@ func (p *ChainPorter) transferReceiverProof(pkg *sendPackage) error { "proof file: %w", err) } - // Hash proof locator. - hash, err := proofLocator.Hash() - if err != nil { - return fmt.Errorf("error hashing proof locator: %w", - err) - } - - passiveAssetProofFiles[hash] = proofFileBlob + passiveAssetProofFiles[passiveAsset.GenesisID] = append( + passiveAssetProofFiles[passiveAsset.GenesisID], + &proof.AnnotatedProof{ + Locator: proofLocator, + Blob: proofFileBlob, + }, + ) } // At this point we have the confirmation signal, so we can mark the diff --git a/tapfreighter/interface.go b/tapfreighter/interface.go index 8f9f3f2ab..13eddc724 100644 --- a/tapfreighter/interface.go +++ b/tapfreighter/interface.go @@ -271,7 +271,7 @@ type AssetConfirmEvent struct { // PassiveAssetProofFiles is the set of passive asset proof files that // are re-anchored during the parcel confirmation process. - PassiveAssetProofFiles map[[32]byte]proof.Blob + PassiveAssetProofFiles map[asset.ID][]*proof.AnnotatedProof } // PassiveAssetReAnchor includes the information needed to re-anchor a passive From 3e6cbb7db50eafa253bbb8352f98ee018f248391 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:02 +0100 Subject: [PATCH 11/19] taprpc: move OutPoint from assetwalletrpc to taprpc pkg --- taprpc/assetwalletrpc/assetwallet.pb.go | 592 ++++++++---------- taprpc/assetwalletrpc/assetwallet.proto | 16 +- .../assetwalletrpc/assetwallet.swagger.json | 34 +- taprpc/taprootassets.pb.go | 352 +++++++---- taprpc/taprootassets.proto | 12 + 5 files changed, 503 insertions(+), 503 deletions(-) diff --git a/taprpc/assetwalletrpc/assetwallet.pb.go b/taprpc/assetwalletrpc/assetwallet.pb.go index 05762e267..f248222fa 100644 --- a/taprpc/assetwalletrpc/assetwallet.pb.go +++ b/taprpc/assetwalletrpc/assetwallet.pb.go @@ -234,7 +234,7 @@ type PrevId struct { unknownFields protoimpl.UnknownFields // The bitcoin anchor output on chain that contains the input asset. - Outpoint *OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` + Outpoint *taprpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` // The asset ID of the previous asset tree. Id []byte `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` // The tweaked Taproot output key committing to the possible spending @@ -274,7 +274,7 @@ func (*PrevId) Descriptor() ([]byte, []int) { return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{3} } -func (x *PrevId) GetOutpoint() *OutPoint { +func (x *PrevId) GetOutpoint() *taprpc.OutPoint { if x != nil { return x.Outpoint } @@ -295,63 +295,6 @@ func (x *PrevId) GetScriptKey() []byte { return nil } -type OutPoint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Raw bytes representing the transaction id. - Txid []byte `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` - // The index of the output on the transaction. - OutputIndex uint32 `protobuf:"varint,2,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` -} - -func (x *OutPoint) Reset() { - *x = OutPoint{} - if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutPoint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutPoint) ProtoMessage() {} - -func (x *OutPoint) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OutPoint.ProtoReflect.Descriptor instead. -func (*OutPoint) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{4} -} - -func (x *OutPoint) GetTxid() []byte { - if x != nil { - return x.Txid - } - return nil -} - -func (x *OutPoint) GetOutputIndex() uint32 { - if x != nil { - return x.OutputIndex - } - return 0 -} - type SignVirtualPsbtRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -366,7 +309,7 @@ type SignVirtualPsbtRequest struct { func (x *SignVirtualPsbtRequest) Reset() { *x = SignVirtualPsbtRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[5] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -379,7 +322,7 @@ func (x *SignVirtualPsbtRequest) String() string { func (*SignVirtualPsbtRequest) ProtoMessage() {} func (x *SignVirtualPsbtRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[5] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -392,7 +335,7 @@ func (x *SignVirtualPsbtRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SignVirtualPsbtRequest.ProtoReflect.Descriptor instead. func (*SignVirtualPsbtRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{5} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{4} } func (x *SignVirtualPsbtRequest) GetFundedPsbt() []byte { @@ -416,7 +359,7 @@ type SignVirtualPsbtResponse struct { func (x *SignVirtualPsbtResponse) Reset() { *x = SignVirtualPsbtResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[6] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -429,7 +372,7 @@ func (x *SignVirtualPsbtResponse) String() string { func (*SignVirtualPsbtResponse) ProtoMessage() {} func (x *SignVirtualPsbtResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[6] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -442,7 +385,7 @@ func (x *SignVirtualPsbtResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SignVirtualPsbtResponse.ProtoReflect.Descriptor instead. func (*SignVirtualPsbtResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{6} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{5} } func (x *SignVirtualPsbtResponse) GetSignedPsbt() []byte { @@ -472,7 +415,7 @@ type AnchorVirtualPsbtsRequest struct { func (x *AnchorVirtualPsbtsRequest) Reset() { *x = AnchorVirtualPsbtsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[7] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -485,7 +428,7 @@ func (x *AnchorVirtualPsbtsRequest) String() string { func (*AnchorVirtualPsbtsRequest) ProtoMessage() {} func (x *AnchorVirtualPsbtsRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[7] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -498,7 +441,7 @@ func (x *AnchorVirtualPsbtsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AnchorVirtualPsbtsRequest.ProtoReflect.Descriptor instead. func (*AnchorVirtualPsbtsRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{7} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{6} } func (x *AnchorVirtualPsbtsRequest) GetVirtualPsbts() [][]byte { @@ -519,7 +462,7 @@ type NextInternalKeyRequest struct { func (x *NextInternalKeyRequest) Reset() { *x = NextInternalKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[8] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -532,7 +475,7 @@ func (x *NextInternalKeyRequest) String() string { func (*NextInternalKeyRequest) ProtoMessage() {} func (x *NextInternalKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[8] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -545,7 +488,7 @@ func (x *NextInternalKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NextInternalKeyRequest.ProtoReflect.Descriptor instead. func (*NextInternalKeyRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{8} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{7} } func (x *NextInternalKeyRequest) GetKeyFamily() uint32 { @@ -566,7 +509,7 @@ type NextInternalKeyResponse struct { func (x *NextInternalKeyResponse) Reset() { *x = NextInternalKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[9] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -579,7 +522,7 @@ func (x *NextInternalKeyResponse) String() string { func (*NextInternalKeyResponse) ProtoMessage() {} func (x *NextInternalKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[9] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -592,7 +535,7 @@ func (x *NextInternalKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NextInternalKeyResponse.ProtoReflect.Descriptor instead. func (*NextInternalKeyResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{9} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{8} } func (x *NextInternalKeyResponse) GetInternalKey() *taprpc.KeyDescriptor { @@ -613,7 +556,7 @@ type NextScriptKeyRequest struct { func (x *NextScriptKeyRequest) Reset() { *x = NextScriptKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[10] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -626,7 +569,7 @@ func (x *NextScriptKeyRequest) String() string { func (*NextScriptKeyRequest) ProtoMessage() {} func (x *NextScriptKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[10] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -639,7 +582,7 @@ func (x *NextScriptKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NextScriptKeyRequest.ProtoReflect.Descriptor instead. func (*NextScriptKeyRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{10} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{9} } func (x *NextScriptKeyRequest) GetKeyFamily() uint32 { @@ -660,7 +603,7 @@ type NextScriptKeyResponse struct { func (x *NextScriptKeyResponse) Reset() { *x = NextScriptKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[11] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -673,7 +616,7 @@ func (x *NextScriptKeyResponse) String() string { func (*NextScriptKeyResponse) ProtoMessage() {} func (x *NextScriptKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[11] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -686,7 +629,7 @@ func (x *NextScriptKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NextScriptKeyResponse.ProtoReflect.Descriptor instead. func (*NextScriptKeyResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{11} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{10} } func (x *NextScriptKeyResponse) GetScriptKey() *taprpc.ScriptKey { @@ -709,7 +652,7 @@ type QueryInternalKeyRequest struct { func (x *QueryInternalKeyRequest) Reset() { *x = QueryInternalKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[12] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -722,7 +665,7 @@ func (x *QueryInternalKeyRequest) String() string { func (*QueryInternalKeyRequest) ProtoMessage() {} func (x *QueryInternalKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[12] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -735,7 +678,7 @@ func (x *QueryInternalKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryInternalKeyRequest.ProtoReflect.Descriptor instead. func (*QueryInternalKeyRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{12} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{11} } func (x *QueryInternalKeyRequest) GetInternalKey() []byte { @@ -756,7 +699,7 @@ type QueryInternalKeyResponse struct { func (x *QueryInternalKeyResponse) Reset() { *x = QueryInternalKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[13] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -769,7 +712,7 @@ func (x *QueryInternalKeyResponse) String() string { func (*QueryInternalKeyResponse) ProtoMessage() {} func (x *QueryInternalKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[13] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -782,7 +725,7 @@ func (x *QueryInternalKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryInternalKeyResponse.ProtoReflect.Descriptor instead. func (*QueryInternalKeyResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{13} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{12} } func (x *QueryInternalKeyResponse) GetInternalKey() *taprpc.KeyDescriptor { @@ -806,7 +749,7 @@ type QueryScriptKeyRequest struct { func (x *QueryScriptKeyRequest) Reset() { *x = QueryScriptKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[14] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -819,7 +762,7 @@ func (x *QueryScriptKeyRequest) String() string { func (*QueryScriptKeyRequest) ProtoMessage() {} func (x *QueryScriptKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[14] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -832,7 +775,7 @@ func (x *QueryScriptKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryScriptKeyRequest.ProtoReflect.Descriptor instead. func (*QueryScriptKeyRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{14} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{13} } func (x *QueryScriptKeyRequest) GetTweakedScriptKey() []byte { @@ -853,7 +796,7 @@ type QueryScriptKeyResponse struct { func (x *QueryScriptKeyResponse) Reset() { *x = QueryScriptKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[15] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -866,7 +809,7 @@ func (x *QueryScriptKeyResponse) String() string { func (*QueryScriptKeyResponse) ProtoMessage() {} func (x *QueryScriptKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[15] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -879,7 +822,7 @@ func (x *QueryScriptKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use QueryScriptKeyResponse.ProtoReflect.Descriptor instead. func (*QueryScriptKeyResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{15} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{14} } func (x *QueryScriptKeyResponse) GetScriptKey() *taprpc.ScriptKey { @@ -901,7 +844,7 @@ type ProveAssetOwnershipRequest struct { func (x *ProveAssetOwnershipRequest) Reset() { *x = ProveAssetOwnershipRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[16] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -914,7 +857,7 @@ func (x *ProveAssetOwnershipRequest) String() string { func (*ProveAssetOwnershipRequest) ProtoMessage() {} func (x *ProveAssetOwnershipRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[16] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -927,7 +870,7 @@ func (x *ProveAssetOwnershipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProveAssetOwnershipRequest.ProtoReflect.Descriptor instead. func (*ProveAssetOwnershipRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{16} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{15} } func (x *ProveAssetOwnershipRequest) GetAssetId() []byte { @@ -955,7 +898,7 @@ type ProveAssetOwnershipResponse struct { func (x *ProveAssetOwnershipResponse) Reset() { *x = ProveAssetOwnershipResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[17] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -968,7 +911,7 @@ func (x *ProveAssetOwnershipResponse) String() string { func (*ProveAssetOwnershipResponse) ProtoMessage() {} func (x *ProveAssetOwnershipResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[17] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -981,7 +924,7 @@ func (x *ProveAssetOwnershipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ProveAssetOwnershipResponse.ProtoReflect.Descriptor instead. func (*ProveAssetOwnershipResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{17} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{16} } func (x *ProveAssetOwnershipResponse) GetProofWithWitness() []byte { @@ -1002,7 +945,7 @@ type VerifyAssetOwnershipRequest struct { func (x *VerifyAssetOwnershipRequest) Reset() { *x = VerifyAssetOwnershipRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[18] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1015,7 +958,7 @@ func (x *VerifyAssetOwnershipRequest) String() string { func (*VerifyAssetOwnershipRequest) ProtoMessage() {} func (x *VerifyAssetOwnershipRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[18] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1028,7 +971,7 @@ func (x *VerifyAssetOwnershipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyAssetOwnershipRequest.ProtoReflect.Descriptor instead. func (*VerifyAssetOwnershipRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{18} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{17} } func (x *VerifyAssetOwnershipRequest) GetProofWithWitness() []byte { @@ -1049,7 +992,7 @@ type VerifyAssetOwnershipResponse struct { func (x *VerifyAssetOwnershipResponse) Reset() { *x = VerifyAssetOwnershipResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[19] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1062,7 +1005,7 @@ func (x *VerifyAssetOwnershipResponse) String() string { func (*VerifyAssetOwnershipResponse) ProtoMessage() {} func (x *VerifyAssetOwnershipResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[19] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1075,7 +1018,7 @@ func (x *VerifyAssetOwnershipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyAssetOwnershipResponse.ProtoReflect.Descriptor instead. func (*VerifyAssetOwnershipResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{19} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{18} } func (x *VerifyAssetOwnershipResponse) GetValidProof() bool { @@ -1091,13 +1034,13 @@ type RemoveUTXOLeaseRequest struct { unknownFields protoimpl.UnknownFields // The outpoint of the UTXO to remove the lease for. - Outpoint *OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` + Outpoint *taprpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` } func (x *RemoveUTXOLeaseRequest) Reset() { *x = RemoveUTXOLeaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[20] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1110,7 +1053,7 @@ func (x *RemoveUTXOLeaseRequest) String() string { func (*RemoveUTXOLeaseRequest) ProtoMessage() {} func (x *RemoveUTXOLeaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[20] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1123,10 +1066,10 @@ func (x *RemoveUTXOLeaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveUTXOLeaseRequest.ProtoReflect.Descriptor instead. func (*RemoveUTXOLeaseRequest) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{20} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{19} } -func (x *RemoveUTXOLeaseRequest) GetOutpoint() *OutPoint { +func (x *RemoveUTXOLeaseRequest) GetOutpoint() *taprpc.OutPoint { if x != nil { return x.Outpoint } @@ -1142,7 +1085,7 @@ type RemoveUTXOLeaseResponse struct { func (x *RemoveUTXOLeaseResponse) Reset() { *x = RemoveUTXOLeaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[21] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1155,7 +1098,7 @@ func (x *RemoveUTXOLeaseResponse) String() string { func (*RemoveUTXOLeaseResponse) ProtoMessage() {} func (x *RemoveUTXOLeaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[21] + mi := &file_assetwalletrpc_assetwallet_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1168,7 +1111,7 @@ func (x *RemoveUTXOLeaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveUTXOLeaseResponse.ProtoReflect.Descriptor instead. func (*RemoveUTXOLeaseResponse) Descriptor() ([]byte, []int) { - return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{21} + return file_assetwalletrpc_assetwallet_proto_rawDescGZIP(), []int{20} } var File_assetwalletrpc_assetwallet_proto protoreflect.FileDescriptor @@ -1204,162 +1147,157 @@ var file_assetwalletrpc_assetwallet_proto_rawDesc = []byte{ 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6d, 0x0a, 0x06, 0x50, 0x72, 0x65, - 0x76, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, - 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x41, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x39, 0x0a, 0x16, 0x53, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x06, 0x50, 0x72, 0x65, + 0x76, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, + 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, + 0x22, 0x39, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, + 0x73, 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x75, + 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x73, 0x62, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x50, 0x73, 0x62, 0x74, 0x22, 0x5f, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x5f, - 0x70, 0x73, 0x62, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x66, 0x75, 0x6e, 0x64, - 0x65, 0x64, 0x50, 0x73, 0x62, 0x74, 0x22, 0x5f, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, - 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x73, 0x62, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x73, - 0x62, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x40, 0x0a, 0x19, 0x41, 0x6e, 0x63, 0x68, 0x6f, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x5f, 0x70, 0x73, 0x62, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x50, 0x73, 0x62, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x40, 0x0a, 0x19, + 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x69, 0x72, + 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x70, 0x73, 0x62, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x22, 0x37, + 0x0a, 0x16, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, + 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6b, 0x65, + 0x79, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x53, 0x0a, 0x17, 0x4e, 0x65, 0x78, 0x74, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, + 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x35, 0x0a, 0x14, + 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x46, 0x61, 0x6d, + 0x69, 0x6c, 0x79, 0x22, 0x49, 0x0a, 0x15, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x0a, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x4b, 0x65, 0x79, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x3c, + 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x54, 0x0a, 0x18, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x22, 0x45, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, + 0x77, 0x65, 0x61, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x65, 0x64, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x4a, 0x0a, 0x16, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x56, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x4b, 0x0a, + 0x1b, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, + 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, + 0x69, 0x74, 0x68, 0x57, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x4b, 0x0a, 0x1b, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, + 0x6f, 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, 0x74, 0x68, + 0x57, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x3f, 0x0a, 0x1c, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, + 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, + 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x82, 0x08, 0x0a, 0x0b, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x62, 0x0a, 0x0f, 0x46, + 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x12, 0x26, + 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x62, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, + 0x62, 0x74, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, + 0x73, 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, + 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, - 0x70, 0x73, 0x62, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x69, 0x72, - 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x22, 0x37, 0x0a, 0x16, 0x4e, 0x65, 0x78, - 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x46, 0x61, 0x6d, 0x69, - 0x6c, 0x79, 0x22, 0x53, 0x0a, 0x17, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, - 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x35, 0x0a, 0x14, 0x4e, 0x65, 0x78, 0x74, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x49, - 0x0a, 0x15, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x09, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x3c, 0x0a, 0x17, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x54, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, + 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x62, 0x0a, 0x0f, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x45, 0x0a, - 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x65, - 0x64, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x10, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x65, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x4b, 0x65, 0x79, 0x22, 0x4a, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, - 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, - 0x22, 0x56, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, - 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, - 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x4b, 0x0a, 0x1b, 0x50, 0x72, 0x6f, 0x76, - 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, 0x74, 0x68, 0x57, 0x69, - 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x4b, 0x0a, 0x1b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, 0x74, 0x68, 0x57, 0x69, 0x74, 0x6e, 0x65, - 0x73, 0x73, 0x22, 0x3f, 0x0a, 0x1c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x22, 0x4e, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, - 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, - 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, - 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x82, - 0x08, 0x0a, 0x0b, 0x41, 0x73, 0x73, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x62, - 0x0a, 0x0f, 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, - 0x74, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, - 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, - 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x56, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, - 0x6c, 0x50, 0x73, 0x62, 0x74, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, - 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x6e, - 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, - 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, - 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x13, - 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x12, 0x2a, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, - 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x14, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x12, 0x2b, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2c, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, + 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x65, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x13, 0x50, 0x72, 0x6f, + 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x12, 0x2a, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, + 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x14, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x12, 0x2b, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, - 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x62, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, - 0x73, 0x65, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, + 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, + 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, + 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, + 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, + 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1374,31 +1312,31 @@ func file_assetwalletrpc_assetwallet_proto_rawDescGZIP() []byte { return file_assetwalletrpc_assetwallet_proto_rawDescData } -var file_assetwalletrpc_assetwallet_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_assetwalletrpc_assetwallet_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_assetwalletrpc_assetwallet_proto_goTypes = []interface{}{ (*FundVirtualPsbtRequest)(nil), // 0: assetwalletrpc.FundVirtualPsbtRequest (*FundVirtualPsbtResponse)(nil), // 1: assetwalletrpc.FundVirtualPsbtResponse (*TxTemplate)(nil), // 2: assetwalletrpc.TxTemplate (*PrevId)(nil), // 3: assetwalletrpc.PrevId - (*OutPoint)(nil), // 4: assetwalletrpc.OutPoint - (*SignVirtualPsbtRequest)(nil), // 5: assetwalletrpc.SignVirtualPsbtRequest - (*SignVirtualPsbtResponse)(nil), // 6: assetwalletrpc.SignVirtualPsbtResponse - (*AnchorVirtualPsbtsRequest)(nil), // 7: assetwalletrpc.AnchorVirtualPsbtsRequest - (*NextInternalKeyRequest)(nil), // 8: assetwalletrpc.NextInternalKeyRequest - (*NextInternalKeyResponse)(nil), // 9: assetwalletrpc.NextInternalKeyResponse - (*NextScriptKeyRequest)(nil), // 10: assetwalletrpc.NextScriptKeyRequest - (*NextScriptKeyResponse)(nil), // 11: assetwalletrpc.NextScriptKeyResponse - (*QueryInternalKeyRequest)(nil), // 12: assetwalletrpc.QueryInternalKeyRequest - (*QueryInternalKeyResponse)(nil), // 13: assetwalletrpc.QueryInternalKeyResponse - (*QueryScriptKeyRequest)(nil), // 14: assetwalletrpc.QueryScriptKeyRequest - (*QueryScriptKeyResponse)(nil), // 15: assetwalletrpc.QueryScriptKeyResponse - (*ProveAssetOwnershipRequest)(nil), // 16: assetwalletrpc.ProveAssetOwnershipRequest - (*ProveAssetOwnershipResponse)(nil), // 17: assetwalletrpc.ProveAssetOwnershipResponse - (*VerifyAssetOwnershipRequest)(nil), // 18: assetwalletrpc.VerifyAssetOwnershipRequest - (*VerifyAssetOwnershipResponse)(nil), // 19: assetwalletrpc.VerifyAssetOwnershipResponse - (*RemoveUTXOLeaseRequest)(nil), // 20: assetwalletrpc.RemoveUTXOLeaseRequest - (*RemoveUTXOLeaseResponse)(nil), // 21: assetwalletrpc.RemoveUTXOLeaseResponse - nil, // 22: assetwalletrpc.TxTemplate.RecipientsEntry + (*SignVirtualPsbtRequest)(nil), // 4: assetwalletrpc.SignVirtualPsbtRequest + (*SignVirtualPsbtResponse)(nil), // 5: assetwalletrpc.SignVirtualPsbtResponse + (*AnchorVirtualPsbtsRequest)(nil), // 6: assetwalletrpc.AnchorVirtualPsbtsRequest + (*NextInternalKeyRequest)(nil), // 7: assetwalletrpc.NextInternalKeyRequest + (*NextInternalKeyResponse)(nil), // 8: assetwalletrpc.NextInternalKeyResponse + (*NextScriptKeyRequest)(nil), // 9: assetwalletrpc.NextScriptKeyRequest + (*NextScriptKeyResponse)(nil), // 10: assetwalletrpc.NextScriptKeyResponse + (*QueryInternalKeyRequest)(nil), // 11: assetwalletrpc.QueryInternalKeyRequest + (*QueryInternalKeyResponse)(nil), // 12: assetwalletrpc.QueryInternalKeyResponse + (*QueryScriptKeyRequest)(nil), // 13: assetwalletrpc.QueryScriptKeyRequest + (*QueryScriptKeyResponse)(nil), // 14: assetwalletrpc.QueryScriptKeyResponse + (*ProveAssetOwnershipRequest)(nil), // 15: assetwalletrpc.ProveAssetOwnershipRequest + (*ProveAssetOwnershipResponse)(nil), // 16: assetwalletrpc.ProveAssetOwnershipResponse + (*VerifyAssetOwnershipRequest)(nil), // 17: assetwalletrpc.VerifyAssetOwnershipRequest + (*VerifyAssetOwnershipResponse)(nil), // 18: assetwalletrpc.VerifyAssetOwnershipResponse + (*RemoveUTXOLeaseRequest)(nil), // 19: assetwalletrpc.RemoveUTXOLeaseRequest + (*RemoveUTXOLeaseResponse)(nil), // 20: assetwalletrpc.RemoveUTXOLeaseResponse + nil, // 21: assetwalletrpc.TxTemplate.RecipientsEntry + (*taprpc.OutPoint)(nil), // 22: taprpc.OutPoint (*taprpc.KeyDescriptor)(nil), // 23: taprpc.KeyDescriptor (*taprpc.ScriptKey)(nil), // 24: taprpc.ScriptKey (*taprpc.SendAssetResponse)(nil), // 25: taprpc.SendAssetResponse @@ -1406,33 +1344,33 @@ var file_assetwalletrpc_assetwallet_proto_goTypes = []interface{}{ var file_assetwalletrpc_assetwallet_proto_depIdxs = []int32{ 2, // 0: assetwalletrpc.FundVirtualPsbtRequest.raw:type_name -> assetwalletrpc.TxTemplate 3, // 1: assetwalletrpc.TxTemplate.inputs:type_name -> assetwalletrpc.PrevId - 22, // 2: assetwalletrpc.TxTemplate.recipients:type_name -> assetwalletrpc.TxTemplate.RecipientsEntry - 4, // 3: assetwalletrpc.PrevId.outpoint:type_name -> assetwalletrpc.OutPoint + 21, // 2: assetwalletrpc.TxTemplate.recipients:type_name -> assetwalletrpc.TxTemplate.RecipientsEntry + 22, // 3: assetwalletrpc.PrevId.outpoint:type_name -> taprpc.OutPoint 23, // 4: assetwalletrpc.NextInternalKeyResponse.internal_key:type_name -> taprpc.KeyDescriptor 24, // 5: assetwalletrpc.NextScriptKeyResponse.script_key:type_name -> taprpc.ScriptKey 23, // 6: assetwalletrpc.QueryInternalKeyResponse.internal_key:type_name -> taprpc.KeyDescriptor 24, // 7: assetwalletrpc.QueryScriptKeyResponse.script_key:type_name -> taprpc.ScriptKey - 4, // 8: assetwalletrpc.RemoveUTXOLeaseRequest.outpoint:type_name -> assetwalletrpc.OutPoint + 22, // 8: assetwalletrpc.RemoveUTXOLeaseRequest.outpoint:type_name -> taprpc.OutPoint 0, // 9: assetwalletrpc.AssetWallet.FundVirtualPsbt:input_type -> assetwalletrpc.FundVirtualPsbtRequest - 5, // 10: assetwalletrpc.AssetWallet.SignVirtualPsbt:input_type -> assetwalletrpc.SignVirtualPsbtRequest - 7, // 11: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:input_type -> assetwalletrpc.AnchorVirtualPsbtsRequest - 8, // 12: assetwalletrpc.AssetWallet.NextInternalKey:input_type -> assetwalletrpc.NextInternalKeyRequest - 10, // 13: assetwalletrpc.AssetWallet.NextScriptKey:input_type -> assetwalletrpc.NextScriptKeyRequest - 12, // 14: assetwalletrpc.AssetWallet.QueryInternalKey:input_type -> assetwalletrpc.QueryInternalKeyRequest - 14, // 15: assetwalletrpc.AssetWallet.QueryScriptKey:input_type -> assetwalletrpc.QueryScriptKeyRequest - 16, // 16: assetwalletrpc.AssetWallet.ProveAssetOwnership:input_type -> assetwalletrpc.ProveAssetOwnershipRequest - 18, // 17: assetwalletrpc.AssetWallet.VerifyAssetOwnership:input_type -> assetwalletrpc.VerifyAssetOwnershipRequest - 20, // 18: assetwalletrpc.AssetWallet.RemoveUTXOLease:input_type -> assetwalletrpc.RemoveUTXOLeaseRequest + 4, // 10: assetwalletrpc.AssetWallet.SignVirtualPsbt:input_type -> assetwalletrpc.SignVirtualPsbtRequest + 6, // 11: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:input_type -> assetwalletrpc.AnchorVirtualPsbtsRequest + 7, // 12: assetwalletrpc.AssetWallet.NextInternalKey:input_type -> assetwalletrpc.NextInternalKeyRequest + 9, // 13: assetwalletrpc.AssetWallet.NextScriptKey:input_type -> assetwalletrpc.NextScriptKeyRequest + 11, // 14: assetwalletrpc.AssetWallet.QueryInternalKey:input_type -> assetwalletrpc.QueryInternalKeyRequest + 13, // 15: assetwalletrpc.AssetWallet.QueryScriptKey:input_type -> assetwalletrpc.QueryScriptKeyRequest + 15, // 16: assetwalletrpc.AssetWallet.ProveAssetOwnership:input_type -> assetwalletrpc.ProveAssetOwnershipRequest + 17, // 17: assetwalletrpc.AssetWallet.VerifyAssetOwnership:input_type -> assetwalletrpc.VerifyAssetOwnershipRequest + 19, // 18: assetwalletrpc.AssetWallet.RemoveUTXOLease:input_type -> assetwalletrpc.RemoveUTXOLeaseRequest 1, // 19: assetwalletrpc.AssetWallet.FundVirtualPsbt:output_type -> assetwalletrpc.FundVirtualPsbtResponse - 6, // 20: assetwalletrpc.AssetWallet.SignVirtualPsbt:output_type -> assetwalletrpc.SignVirtualPsbtResponse + 5, // 20: assetwalletrpc.AssetWallet.SignVirtualPsbt:output_type -> assetwalletrpc.SignVirtualPsbtResponse 25, // 21: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:output_type -> taprpc.SendAssetResponse - 9, // 22: assetwalletrpc.AssetWallet.NextInternalKey:output_type -> assetwalletrpc.NextInternalKeyResponse - 11, // 23: assetwalletrpc.AssetWallet.NextScriptKey:output_type -> assetwalletrpc.NextScriptKeyResponse - 13, // 24: assetwalletrpc.AssetWallet.QueryInternalKey:output_type -> assetwalletrpc.QueryInternalKeyResponse - 15, // 25: assetwalletrpc.AssetWallet.QueryScriptKey:output_type -> assetwalletrpc.QueryScriptKeyResponse - 17, // 26: assetwalletrpc.AssetWallet.ProveAssetOwnership:output_type -> assetwalletrpc.ProveAssetOwnershipResponse - 19, // 27: assetwalletrpc.AssetWallet.VerifyAssetOwnership:output_type -> assetwalletrpc.VerifyAssetOwnershipResponse - 21, // 28: assetwalletrpc.AssetWallet.RemoveUTXOLease:output_type -> assetwalletrpc.RemoveUTXOLeaseResponse + 8, // 22: assetwalletrpc.AssetWallet.NextInternalKey:output_type -> assetwalletrpc.NextInternalKeyResponse + 10, // 23: assetwalletrpc.AssetWallet.NextScriptKey:output_type -> assetwalletrpc.NextScriptKeyResponse + 12, // 24: assetwalletrpc.AssetWallet.QueryInternalKey:output_type -> assetwalletrpc.QueryInternalKeyResponse + 14, // 25: assetwalletrpc.AssetWallet.QueryScriptKey:output_type -> assetwalletrpc.QueryScriptKeyResponse + 16, // 26: assetwalletrpc.AssetWallet.ProveAssetOwnership:output_type -> assetwalletrpc.ProveAssetOwnershipResponse + 18, // 27: assetwalletrpc.AssetWallet.VerifyAssetOwnership:output_type -> assetwalletrpc.VerifyAssetOwnershipResponse + 20, // 28: assetwalletrpc.AssetWallet.RemoveUTXOLease:output_type -> assetwalletrpc.RemoveUTXOLeaseResponse 19, // [19:29] is the sub-list for method output_type 9, // [9:19] is the sub-list for method input_type 9, // [9:9] is the sub-list for extension type_name @@ -1495,18 +1433,6 @@ func file_assetwalletrpc_assetwallet_proto_init() { } } file_assetwalletrpc_assetwallet_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutPoint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_assetwalletrpc_assetwallet_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignVirtualPsbtRequest); i { case 0: return &v.state @@ -1518,7 +1444,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignVirtualPsbtResponse); i { case 0: return &v.state @@ -1530,7 +1456,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AnchorVirtualPsbtsRequest); i { case 0: return &v.state @@ -1542,7 +1468,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NextInternalKeyRequest); i { case 0: return &v.state @@ -1554,7 +1480,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NextInternalKeyResponse); i { case 0: return &v.state @@ -1566,7 +1492,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NextScriptKeyRequest); i { case 0: return &v.state @@ -1578,7 +1504,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NextScriptKeyResponse); i { case 0: return &v.state @@ -1590,7 +1516,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryInternalKeyRequest); i { case 0: return &v.state @@ -1602,7 +1528,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryInternalKeyResponse); i { case 0: return &v.state @@ -1614,7 +1540,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryScriptKeyRequest); i { case 0: return &v.state @@ -1626,7 +1552,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*QueryScriptKeyResponse); i { case 0: return &v.state @@ -1638,7 +1564,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProveAssetOwnershipRequest); i { case 0: return &v.state @@ -1650,7 +1576,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProveAssetOwnershipResponse); i { case 0: return &v.state @@ -1662,7 +1588,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*VerifyAssetOwnershipRequest); i { case 0: return &v.state @@ -1674,7 +1600,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*VerifyAssetOwnershipResponse); i { case 0: return &v.state @@ -1686,7 +1612,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveUTXOLeaseRequest); i { case 0: return &v.state @@ -1698,7 +1624,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { return nil } } - file_assetwalletrpc_assetwallet_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_assetwalletrpc_assetwallet_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveUTXOLeaseResponse); i { case 0: return &v.state @@ -1721,7 +1647,7 @@ func file_assetwalletrpc_assetwallet_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_assetwalletrpc_assetwallet_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/taprpc/assetwalletrpc/assetwallet.proto b/taprpc/assetwalletrpc/assetwallet.proto index d0a092788..12b8a77d8 100644 --- a/taprpc/assetwalletrpc/assetwallet.proto +++ b/taprpc/assetwalletrpc/assetwallet.proto @@ -137,7 +137,7 @@ message PrevId { /* The bitcoin anchor output on chain that contains the input asset. */ - OutPoint outpoint = 1; + taprpc.OutPoint outpoint = 1; /* The asset ID of the previous asset tree. @@ -151,18 +151,6 @@ message PrevId { bytes script_key = 3; } -message OutPoint { - /* - Raw bytes representing the transaction id. - */ - bytes txid = 1; - - /* - The index of the output on the transaction. - */ - uint32 output_index = 2; -} - message SignVirtualPsbtRequest { /* The PSBT of the virtual transaction that should be signed. The PSBT must @@ -249,7 +237,7 @@ message VerifyAssetOwnershipResponse { message RemoveUTXOLeaseRequest { // The outpoint of the UTXO to remove the lease for. - OutPoint outpoint = 1; + taprpc.OutPoint outpoint = 1; } message RemoveUTXOLeaseResponse { diff --git a/taprpc/assetwalletrpc/assetwallet.swagger.json b/taprpc/assetwalletrpc/assetwallet.swagger.json index 54792917a..65ba60155 100644 --- a/taprpc/assetwalletrpc/assetwallet.swagger.json +++ b/taprpc/assetwalletrpc/assetwallet.swagger.json @@ -425,26 +425,11 @@ } } }, - "assetwalletrpcOutPoint": { - "type": "object", - "properties": { - "txid": { - "type": "string", - "format": "byte", - "description": "Raw bytes representing the transaction id." - }, - "output_index": { - "type": "integer", - "format": "int64", - "description": "The index of the output on the transaction." - } - } - }, "assetwalletrpcPrevId": { "type": "object", "properties": { "outpoint": { - "$ref": "#/definitions/assetwalletrpcOutPoint", + "$ref": "#/definitions/taprpcOutPoint", "description": "The bitcoin anchor output on chain that contains the input asset." }, "id": { @@ -501,7 +486,7 @@ "type": "object", "properties": { "outpoint": { - "$ref": "#/definitions/assetwalletrpcOutPoint", + "$ref": "#/definitions/taprpcOutPoint", "description": "The outpoint of the UTXO to remove the lease for." } } @@ -678,6 +663,21 @@ } } }, + "taprpcOutPoint": { + "type": "object", + "properties": { + "txid": { + "type": "string", + "format": "byte", + "description": "Raw bytes representing the transaction id." + }, + "output_index": { + "type": "integer", + "format": "int64", + "description": "The index of the output on the transaction." + } + } + }, "taprpcOutputType": { "type": "string", "enum": [ diff --git a/taprpc/taprootassets.pb.go b/taprpc/taprootassets.pb.go index a2e31704b..405d45b24 100644 --- a/taprpc/taprootassets.pb.go +++ b/taprpc/taprootassets.pb.go @@ -4885,6 +4885,63 @@ func (x *BurnAssetResponse) GetBurnProof() *DecodedProof { return nil } +type OutPoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Raw bytes representing the transaction id. + Txid []byte `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` + // The index of the output on the transaction. + OutputIndex uint32 `protobuf:"varint,2,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` +} + +func (x *OutPoint) Reset() { + *x = OutPoint{} + if protoimpl.UnsafeEnabled { + mi := &file_taprootassets_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OutPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OutPoint) ProtoMessage() {} + +func (x *OutPoint) ProtoReflect() protoreflect.Message { + mi := &file_taprootassets_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OutPoint.ProtoReflect.Descriptor instead. +func (*OutPoint) Descriptor() ([]byte, []int) { + return file_taprootassets_proto_rawDescGZIP(), []int{64} +} + +func (x *OutPoint) GetTxid() []byte { + if x != nil { + return x.Txid + } + return nil +} + +func (x *OutPoint) GetOutputIndex() uint32 { + if x != nil { + return x.OutputIndex + } + return 0 +} + var File_taprootassets_proto protoreflect.FileDescriptor var file_taprootassets_proto_rawDesc = []byte{ @@ -5520,138 +5577,142 @@ var file_taprootassets_proto_rawDesc = []byte{ 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x09, 0x62, 0x75, - 0x72, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2a, 0x28, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, - 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4c, 0x4c, 0x45, 0x43, 0x54, 0x49, 0x42, 0x4c, 0x45, 0x10, - 0x01, 0x2a, 0x25, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x54, 0x41, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x10, 0x00, 0x2a, 0x3a, 0x0a, 0x0c, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x53, 0x53, 0x45, - 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x30, 0x10, 0x00, 0x12, 0x14, - 0x0a, 0x10, 0x41, 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, - 0x56, 0x31, 0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x4f, - 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, - 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x4f, 0x55, 0x54, 0x50, 0x55, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, 0x41, - 0x53, 0x53, 0x45, 0x54, 0x53, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, - 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, - 0x49, 0x56, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x03, - 0x12, 0x25, 0x0a, 0x21, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, 0x41, - 0x53, 0x53, 0x45, 0x54, 0x53, 0x10, 0x04, 0x2a, 0xd0, 0x01, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x72, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x41, - 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x2a, 0x0a, 0x26, 0x41, 0x44, - 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x54, 0x45, - 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, - 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, - 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x52, - 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x44, 0x44, - 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, - 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x52, 0x0a, 0x11, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, 0x45, - 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, - 0x1b, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, 0x45, 0x52, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x10, 0x01, 0x32, 0x86, - 0x0b, 0x0a, 0x0d, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x12, 0x41, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x18, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, - 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, - 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x41, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2a, 0x28, 0x0a, 0x09, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, + 0x4c, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4c, 0x4c, 0x45, 0x43, 0x54, 0x49, 0x42, + 0x4c, 0x45, 0x10, 0x01, 0x2a, 0x25, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x54, 0x41, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x10, 0x00, 0x2a, 0x3a, 0x0a, 0x0c, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x41, + 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x30, 0x10, + 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, + 0x4f, 0x4e, 0x5f, 0x56, 0x31, 0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1a, + 0x0a, 0x16, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50, + 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x4f, 0x55, + 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, + 0x45, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, + 0x22, 0x0a, 0x1e, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, + 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, + 0x54, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, + 0x45, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x10, 0x04, 0x2a, 0xd0, 0x01, 0x0a, 0x0f, 0x41, + 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, + 0x0a, 0x19, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x2a, 0x0a, + 0x26, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, + 0x45, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x41, 0x44, 0x44, + 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, + 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, + 0x52, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, + 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4f, + 0x46, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, + 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x52, 0x0a, + 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, + 0x53, 0x46, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x00, + 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, + 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x10, + 0x01, 0x32, 0x86, 0x0b, 0x0a, 0x0d, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, + 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, + 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, + 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x12, 0x13, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, - 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, - 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, - 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x12, - 0x16, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, - 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x41, - 0x64, 0x64, 0x72, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x63, - 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x49, 0x0a, 0x0c, - 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x43, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x2e, + 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, + 0x72, 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x41, 0x64, + 0x64, 0x72, 0x12, 0x16, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, + 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x44, 0x65, 0x63, 0x6f, + 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, + 0x49, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x12, + 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, + 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x69, 0x66, - 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, - 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, 0x2e, - 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x40, 0x0a, 0x09, - 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, - 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, - 0x0a, 0x09, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x42, - 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x1c, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2b, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, - 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x1b, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x44, 0x65, 0x63, + 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, + 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x12, + 0x40, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x65, - 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x40, 0x0a, 0x09, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, + 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, + 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x65, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, + 0x2b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, + 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -5667,7 +5728,7 @@ func file_taprootassets_proto_rawDescGZIP() []byte { } var file_taprootassets_proto_enumTypes = make([]protoimpl.EnumInfo, 6) -var file_taprootassets_proto_msgTypes = make([]protoimpl.MessageInfo, 68) +var file_taprootassets_proto_msgTypes = make([]protoimpl.MessageInfo, 69) var file_taprootassets_proto_goTypes = []interface{}{ (AssetType)(0), // 0: taprpc.AssetType (AssetMetaType)(0), // 1: taprpc.AssetMetaType @@ -5739,10 +5800,11 @@ var file_taprootassets_proto_goTypes = []interface{}{ (*FetchAssetMetaRequest)(nil), // 67: taprpc.FetchAssetMetaRequest (*BurnAssetRequest)(nil), // 68: taprpc.BurnAssetRequest (*BurnAssetResponse)(nil), // 69: taprpc.BurnAssetResponse - nil, // 70: taprpc.ListUtxosResponse.ManagedUtxosEntry - nil, // 71: taprpc.ListGroupsResponse.GroupsEntry - nil, // 72: taprpc.ListBalancesResponse.AssetBalancesEntry - nil, // 73: taprpc.ListBalancesResponse.AssetGroupBalancesEntry + (*OutPoint)(nil), // 70: taprpc.OutPoint + nil, // 71: taprpc.ListUtxosResponse.ManagedUtxosEntry + nil, // 72: taprpc.ListGroupsResponse.GroupsEntry + nil, // 73: taprpc.ListBalancesResponse.AssetBalancesEntry + nil, // 74: taprpc.ListBalancesResponse.AssetGroupBalancesEntry } var file_taprootassets_proto_depIdxs = []int32{ 1, // 0: taprpc.AssetMeta.type:type_name -> taprpc.AssetMetaType @@ -5758,14 +5820,14 @@ var file_taprootassets_proto_depIdxs = []int32{ 13, // 10: taprpc.SplitCommitment.root_asset:type_name -> taprpc.Asset 13, // 11: taprpc.ListAssetResponse.assets:type_name -> taprpc.Asset 13, // 12: taprpc.ManagedUtxo.assets:type_name -> taprpc.Asset - 70, // 13: taprpc.ListUtxosResponse.managed_utxos:type_name -> taprpc.ListUtxosResponse.ManagedUtxosEntry + 71, // 13: taprpc.ListUtxosResponse.managed_utxos:type_name -> taprpc.ListUtxosResponse.ManagedUtxosEntry 0, // 14: taprpc.AssetHumanReadable.type:type_name -> taprpc.AssetType 2, // 15: taprpc.AssetHumanReadable.version:type_name -> taprpc.AssetVersion 21, // 16: taprpc.GroupedAssets.assets:type_name -> taprpc.AssetHumanReadable - 71, // 17: taprpc.ListGroupsResponse.groups:type_name -> taprpc.ListGroupsResponse.GroupsEntry + 72, // 17: taprpc.ListGroupsResponse.groups:type_name -> taprpc.ListGroupsResponse.GroupsEntry 9, // 18: taprpc.AssetBalance.asset_genesis:type_name -> taprpc.GenesisInfo - 72, // 19: taprpc.ListBalancesResponse.asset_balances:type_name -> taprpc.ListBalancesResponse.AssetBalancesEntry - 73, // 20: taprpc.ListBalancesResponse.asset_group_balances:type_name -> taprpc.ListBalancesResponse.AssetGroupBalancesEntry + 73, // 19: taprpc.ListBalancesResponse.asset_balances:type_name -> taprpc.ListBalancesResponse.AssetBalancesEntry + 74, // 20: taprpc.ListBalancesResponse.asset_group_balances:type_name -> taprpc.ListBalancesResponse.AssetGroupBalancesEntry 30, // 21: taprpc.ListTransfersResponse.transfers:type_name -> taprpc.AssetTransfer 31, // 22: taprpc.AssetTransfer.inputs:type_name -> taprpc.TransferInput 33, // 23: taprpc.AssetTransfer.outputs:type_name -> taprpc.TransferOutput @@ -6624,6 +6686,18 @@ func file_taprootassets_proto_init() { return nil } } + file_taprootassets_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OutPoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_taprootassets_proto_msgTypes[18].OneofWrappers = []interface{}{ (*ListBalancesRequest_AssetId)(nil), @@ -6653,7 +6727,7 @@ func file_taprootassets_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_taprootassets_proto_rawDesc, NumEnums: 6, - NumMessages: 68, + NumMessages: 69, NumExtensions: 0, NumServices: 1, }, diff --git a/taprpc/taprootassets.proto b/taprpc/taprootassets.proto index 1da0b0f34..ade173f44 100644 --- a/taprpc/taprootassets.proto +++ b/taprpc/taprootassets.proto @@ -1067,3 +1067,15 @@ message BurnAssetResponse { // The burn transition proof for the asset burn output. DecodedProof burn_proof = 2; } + +message OutPoint { + /* + Raw bytes representing the transaction id. + */ + bytes txid = 1; + + /* + The index of the output on the transaction. + */ + uint32 output_index = 2; +} From 73dc12054c4a8cbffb4e407cf978d528dc4afdf1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:03 +0100 Subject: [PATCH 12/19] taprpc+rpcserver: allow proof query by outpoint This commit allows the ExportProof and ProveAssetOwnership RPC methods to be called with an outpoint as well to disambiguate in case of multiple proofs with the same script key (e.g. multiple receives to the same TAP address). --- rpcserver.go | 45 +- taprpc/assetwalletrpc/assetwallet.pb.go | 254 +++--- taprpc/assetwalletrpc/assetwallet.proto | 2 + .../assetwalletrpc/assetwallet.swagger.json | 3 + taprpc/taprootassets.pb.go | 726 +++++++++--------- taprpc/taprootassets.proto | 1 + taprpc/taprootassets.swagger.json | 18 + 7 files changed, 569 insertions(+), 480 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index afb442350..d9af25e3e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1495,12 +1495,32 @@ func (r *rpcServer) ExportProof(ctx context.Context, return nil, fmt.Errorf("asset ID must be 32 bytes") } - var assetID asset.ID + var ( + assetID asset.ID + outPoint *wire.OutPoint + ) copy(assetID[:], req.AssetId) + // The outpoint is optional when querying for a proof file. But if + // multiple proofs exist for the same assetID and script key, then an + // error will be returned and the outpoint needs to be specified to + // disambiguate. + if req.Outpoint != nil { + txid, err := chainhash.NewHash(req.Outpoint.Txid) + if err != nil { + return nil, fmt.Errorf("error parsing outpoint: %w", + err) + } + outPoint = &wire.OutPoint{ + Hash: *txid, + Index: req.Outpoint.OutputIndex, + } + } + proofBlob, err := r.cfg.ProofArchive.FetchProof(ctx, proof.Locator{ AssetID: &assetID, ScriptKey: *scriptKey, + OutPoint: outPoint, }) if err != nil { return nil, err @@ -4394,10 +4414,31 @@ func (r *rpcServer) ProveAssetOwnership(ctx context.Context, return nil, fmt.Errorf("asset ID must be 32 bytes") } - assetID := fn.ToArray[asset.ID](req.AssetId) + var ( + assetID = fn.ToArray[asset.ID](req.AssetId) + outPoint *wire.OutPoint + ) + + // The outpoint is optional when querying for a proof file. But if + // multiple proofs exist for the same assetID and script key, then an + // error will be returned and the outpoint needs to be specified to + // disambiguate. + if req.Outpoint != nil { + txid, err := chainhash.NewHash(req.Outpoint.Txid) + if err != nil { + return nil, fmt.Errorf("error parsing outpoint: %w", + err) + } + outPoint = &wire.OutPoint{ + Hash: *txid, + Index: req.Outpoint.OutputIndex, + } + } + proofBlob, err := r.cfg.ProofArchive.FetchProof(ctx, proof.Locator{ AssetID: &assetID, ScriptKey: *scriptKey, + OutPoint: outPoint, }) if err != nil { return nil, fmt.Errorf("cannot fetch proof: %w", err) diff --git a/taprpc/assetwalletrpc/assetwallet.pb.go b/taprpc/assetwalletrpc/assetwallet.pb.go index f248222fa..572e42f94 100644 --- a/taprpc/assetwalletrpc/assetwallet.pb.go +++ b/taprpc/assetwalletrpc/assetwallet.pb.go @@ -837,8 +837,9 @@ type ProveAssetOwnershipRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` - ScriptKey []byte `protobuf:"bytes,2,opt,name=script_key,json=scriptKey,proto3" json:"script_key,omitempty"` + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + ScriptKey []byte `protobuf:"bytes,2,opt,name=script_key,json=scriptKey,proto3" json:"script_key,omitempty"` + Outpoint *taprpc.OutPoint `protobuf:"bytes,3,opt,name=outpoint,proto3" json:"outpoint,omitempty"` } func (x *ProveAssetOwnershipRequest) Reset() { @@ -887,6 +888,13 @@ func (x *ProveAssetOwnershipRequest) GetScriptKey() []byte { return nil } +func (x *ProveAssetOwnershipRequest) GetOutpoint() *taprpc.OutPoint { + if x != nil { + return x.Outpoint + } + return nil +} + type ProveAssetOwnershipResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1203,101 +1211,104 @@ var file_assetwalletrpc_assetwallet_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x56, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x4b, 0x0a, - 0x1b, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, - 0x69, 0x74, 0x68, 0x57, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x4b, 0x0a, 0x1b, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, 0x74, 0x68, - 0x57, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x3f, 0x0a, 0x1c, 0x56, 0x65, 0x72, 0x69, 0x66, - 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, - 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x82, 0x08, 0x0a, 0x0b, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x62, 0x0a, 0x0f, 0x46, - 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x12, 0x26, - 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, - 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x62, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, - 0x62, 0x74, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, - 0x73, 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, - 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x61, 0x73, 0x73, 0x65, - 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x6e, 0x63, 0x68, 0x6f, - 0x72, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, - 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x62, 0x0a, 0x0f, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, - 0x65, 0x79, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x65, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, - 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x13, 0x50, 0x72, 0x6f, - 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x12, 0x2a, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x14, 0x56, 0x65, 0x72, + 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x84, 0x01, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x2c, + 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, + 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x4b, 0x0a, 0x1b, + 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, + 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, + 0x74, 0x68, 0x57, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x4b, 0x0a, 0x1b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x12, 0x2b, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, - 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x57, 0x69, 0x74, 0x68, 0x57, + 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x22, 0x3f, 0x0a, 0x1c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x46, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, + 0x19, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x82, 0x08, 0x0a, 0x0b, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x62, 0x0a, 0x0f, 0x46, 0x75, + 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x12, 0x26, 0x2e, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, + 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x56, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, + 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, + 0x74, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, + 0x62, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x56, + 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x56, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, + 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x73, 0x62, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, + 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, + 0x0a, 0x0f, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, + 0x79, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x4b, 0x65, 0x79, 0x12, 0x24, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x65, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x76, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, + 0x2a, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, + 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x14, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x12, 0x2b, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, - 0x26, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, - 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, - 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, - 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x54, + 0x58, 0x4f, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, + 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1350,32 +1361,33 @@ var file_assetwalletrpc_assetwallet_proto_depIdxs = []int32{ 24, // 5: assetwalletrpc.NextScriptKeyResponse.script_key:type_name -> taprpc.ScriptKey 23, // 6: assetwalletrpc.QueryInternalKeyResponse.internal_key:type_name -> taprpc.KeyDescriptor 24, // 7: assetwalletrpc.QueryScriptKeyResponse.script_key:type_name -> taprpc.ScriptKey - 22, // 8: assetwalletrpc.RemoveUTXOLeaseRequest.outpoint:type_name -> taprpc.OutPoint - 0, // 9: assetwalletrpc.AssetWallet.FundVirtualPsbt:input_type -> assetwalletrpc.FundVirtualPsbtRequest - 4, // 10: assetwalletrpc.AssetWallet.SignVirtualPsbt:input_type -> assetwalletrpc.SignVirtualPsbtRequest - 6, // 11: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:input_type -> assetwalletrpc.AnchorVirtualPsbtsRequest - 7, // 12: assetwalletrpc.AssetWallet.NextInternalKey:input_type -> assetwalletrpc.NextInternalKeyRequest - 9, // 13: assetwalletrpc.AssetWallet.NextScriptKey:input_type -> assetwalletrpc.NextScriptKeyRequest - 11, // 14: assetwalletrpc.AssetWallet.QueryInternalKey:input_type -> assetwalletrpc.QueryInternalKeyRequest - 13, // 15: assetwalletrpc.AssetWallet.QueryScriptKey:input_type -> assetwalletrpc.QueryScriptKeyRequest - 15, // 16: assetwalletrpc.AssetWallet.ProveAssetOwnership:input_type -> assetwalletrpc.ProveAssetOwnershipRequest - 17, // 17: assetwalletrpc.AssetWallet.VerifyAssetOwnership:input_type -> assetwalletrpc.VerifyAssetOwnershipRequest - 19, // 18: assetwalletrpc.AssetWallet.RemoveUTXOLease:input_type -> assetwalletrpc.RemoveUTXOLeaseRequest - 1, // 19: assetwalletrpc.AssetWallet.FundVirtualPsbt:output_type -> assetwalletrpc.FundVirtualPsbtResponse - 5, // 20: assetwalletrpc.AssetWallet.SignVirtualPsbt:output_type -> assetwalletrpc.SignVirtualPsbtResponse - 25, // 21: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:output_type -> taprpc.SendAssetResponse - 8, // 22: assetwalletrpc.AssetWallet.NextInternalKey:output_type -> assetwalletrpc.NextInternalKeyResponse - 10, // 23: assetwalletrpc.AssetWallet.NextScriptKey:output_type -> assetwalletrpc.NextScriptKeyResponse - 12, // 24: assetwalletrpc.AssetWallet.QueryInternalKey:output_type -> assetwalletrpc.QueryInternalKeyResponse - 14, // 25: assetwalletrpc.AssetWallet.QueryScriptKey:output_type -> assetwalletrpc.QueryScriptKeyResponse - 16, // 26: assetwalletrpc.AssetWallet.ProveAssetOwnership:output_type -> assetwalletrpc.ProveAssetOwnershipResponse - 18, // 27: assetwalletrpc.AssetWallet.VerifyAssetOwnership:output_type -> assetwalletrpc.VerifyAssetOwnershipResponse - 20, // 28: assetwalletrpc.AssetWallet.RemoveUTXOLease:output_type -> assetwalletrpc.RemoveUTXOLeaseResponse - 19, // [19:29] is the sub-list for method output_type - 9, // [9:19] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 22, // 8: assetwalletrpc.ProveAssetOwnershipRequest.outpoint:type_name -> taprpc.OutPoint + 22, // 9: assetwalletrpc.RemoveUTXOLeaseRequest.outpoint:type_name -> taprpc.OutPoint + 0, // 10: assetwalletrpc.AssetWallet.FundVirtualPsbt:input_type -> assetwalletrpc.FundVirtualPsbtRequest + 4, // 11: assetwalletrpc.AssetWallet.SignVirtualPsbt:input_type -> assetwalletrpc.SignVirtualPsbtRequest + 6, // 12: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:input_type -> assetwalletrpc.AnchorVirtualPsbtsRequest + 7, // 13: assetwalletrpc.AssetWallet.NextInternalKey:input_type -> assetwalletrpc.NextInternalKeyRequest + 9, // 14: assetwalletrpc.AssetWallet.NextScriptKey:input_type -> assetwalletrpc.NextScriptKeyRequest + 11, // 15: assetwalletrpc.AssetWallet.QueryInternalKey:input_type -> assetwalletrpc.QueryInternalKeyRequest + 13, // 16: assetwalletrpc.AssetWallet.QueryScriptKey:input_type -> assetwalletrpc.QueryScriptKeyRequest + 15, // 17: assetwalletrpc.AssetWallet.ProveAssetOwnership:input_type -> assetwalletrpc.ProveAssetOwnershipRequest + 17, // 18: assetwalletrpc.AssetWallet.VerifyAssetOwnership:input_type -> assetwalletrpc.VerifyAssetOwnershipRequest + 19, // 19: assetwalletrpc.AssetWallet.RemoveUTXOLease:input_type -> assetwalletrpc.RemoveUTXOLeaseRequest + 1, // 20: assetwalletrpc.AssetWallet.FundVirtualPsbt:output_type -> assetwalletrpc.FundVirtualPsbtResponse + 5, // 21: assetwalletrpc.AssetWallet.SignVirtualPsbt:output_type -> assetwalletrpc.SignVirtualPsbtResponse + 25, // 22: assetwalletrpc.AssetWallet.AnchorVirtualPsbts:output_type -> taprpc.SendAssetResponse + 8, // 23: assetwalletrpc.AssetWallet.NextInternalKey:output_type -> assetwalletrpc.NextInternalKeyResponse + 10, // 24: assetwalletrpc.AssetWallet.NextScriptKey:output_type -> assetwalletrpc.NextScriptKeyResponse + 12, // 25: assetwalletrpc.AssetWallet.QueryInternalKey:output_type -> assetwalletrpc.QueryInternalKeyResponse + 14, // 26: assetwalletrpc.AssetWallet.QueryScriptKey:output_type -> assetwalletrpc.QueryScriptKeyResponse + 16, // 27: assetwalletrpc.AssetWallet.ProveAssetOwnership:output_type -> assetwalletrpc.ProveAssetOwnershipResponse + 18, // 28: assetwalletrpc.AssetWallet.VerifyAssetOwnership:output_type -> assetwalletrpc.VerifyAssetOwnershipResponse + 20, // 29: assetwalletrpc.AssetWallet.RemoveUTXOLease:output_type -> assetwalletrpc.RemoveUTXOLeaseResponse + 20, // [20:30] is the sub-list for method output_type + 10, // [10:20] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_assetwalletrpc_assetwallet_proto_init() } diff --git a/taprpc/assetwalletrpc/assetwallet.proto b/taprpc/assetwalletrpc/assetwallet.proto index 12b8a77d8..c4d21d34b 100644 --- a/taprpc/assetwalletrpc/assetwallet.proto +++ b/taprpc/assetwalletrpc/assetwallet.proto @@ -221,6 +221,8 @@ message ProveAssetOwnershipRequest { bytes asset_id = 1; bytes script_key = 2; + + taprpc.OutPoint outpoint = 3; } message ProveAssetOwnershipResponse { diff --git a/taprpc/assetwalletrpc/assetwallet.swagger.json b/taprpc/assetwalletrpc/assetwallet.swagger.json index 65ba60155..87c2058b0 100644 --- a/taprpc/assetwalletrpc/assetwallet.swagger.json +++ b/taprpc/assetwalletrpc/assetwallet.swagger.json @@ -454,6 +454,9 @@ "script_key": { "type": "string", "format": "byte" + }, + "outpoint": { + "$ref": "#/definitions/taprpcOutPoint" } } }, diff --git a/taprpc/taprootassets.pb.go b/taprpc/taprootassets.pb.go index 405d45b24..05efa426a 100644 --- a/taprpc/taprootassets.pb.go +++ b/taprpc/taprootassets.pb.go @@ -3584,8 +3584,9 @@ type ExportProofRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` - ScriptKey []byte `protobuf:"bytes,2,opt,name=script_key,json=scriptKey,proto3" json:"script_key,omitempty"` + AssetId []byte `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` + ScriptKey []byte `protobuf:"bytes,2,opt,name=script_key,json=scriptKey,proto3" json:"script_key,omitempty"` + Outpoint *OutPoint `protobuf:"bytes,3,opt,name=outpoint,proto3" json:"outpoint,omitempty"` } func (x *ExportProofRequest) Reset() { @@ -3634,6 +3635,13 @@ func (x *ExportProofRequest) GetScriptKey() []byte { return nil } +func (x *ExportProofRequest) GetOutpoint() *OutPoint { + if x != nil { + return x.Outpoint + } + return nil +} + type AddrEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -5412,307 +5420,310 @@ var file_taprootassets_proto_rawDesc = []byte{ 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x0c, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x4e, 0x0a, 0x12, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x7c, 0x0a, 0x12, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x22, 0xd0, 0x02, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x1a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x12, 0x20, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x04, - 0x61, 0x64, 0x64, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x74, 0x78, 0x6f, 0x5f, 0x61, 0x6d, 0x74, 0x5f, 0x73, 0x61, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x74, 0x78, 0x6f, 0x41, 0x6d, 0x74, - 0x53, 0x61, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x73, - 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x61, - 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x13, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x68, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x74, 0x0a, 0x13, 0x41, 0x64, - 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x64, - 0x64, 0x72, 0x12, 0x3c, 0x0a, 0x0d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x0c, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x22, 0x41, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x4a, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x70, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x70, 0x41, - 0x64, 0x64, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22, - 0x85, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, - 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x22, - 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x9b, 0x02, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x1f, 0x0a, 0x0b, 0x6c, 0x6e, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x6e, - 0x64, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x6e, 0x64, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, - 0x64, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x6e, 0x6f, 0x64, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0d, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x73, 0x79, 0x6e, 0x63, 0x54, 0x6f, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x22, - 0x25, 0x0a, 0x23, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe6, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x18, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x71, 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x77, 0x61, - 0x69, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, - 0x54, 0x0a, 0x15, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x64, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xbc, 0x01, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, - 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x12, - 0x23, 0x0a, 0x0d, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x26, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d, - 0x0a, 0x19, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x26, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x61, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0xf5, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x71, 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x77, 0x61, - 0x69, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, + 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0xd0, 0x02, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x1a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, + 0x12, 0x20, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x04, 0x61, 0x64, + 0x64, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x20, 0x0a, 0x0c, 0x75, 0x74, 0x78, 0x6f, 0x5f, 0x61, 0x6d, 0x74, 0x5f, 0x73, 0x61, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x74, 0x78, 0x6f, 0x41, 0x6d, 0x74, 0x53, 0x61, + 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x73, 0x69, 0x62, + 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x61, 0x70, 0x72, + 0x6f, 0x6f, 0x74, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x13, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x68, + 0x61, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x68, 0x61, 0x73, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x74, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, + 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x3c, 0x0a, 0x0d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x41, 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x0c, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x41, + 0x0a, 0x14, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x41, 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x22, 0x4a, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x70, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x70, 0x41, 0x64, 0x64, + 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22, 0x85, 0x01, + 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x52, 0x08, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x22, 0x10, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x9b, 0x02, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, + 0x0b, 0x6c, 0x6e, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6e, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x6e, 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, + 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, + 0x64, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x73, 0x79, 0x6e, 0x63, 0x54, 0x6f, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x22, 0x25, 0x0a, + 0x23, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0xe6, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x71, 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x77, 0x61, 0x69, 0x74, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x54, 0x0a, + 0x15, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x22, 0xbc, 0x01, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x1c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x19, 0x61, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x43, - 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x15, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1b, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09, - 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, - 0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x53, 0x74, 0x72, 0x12, - 0x24, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x73, 0x74, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x61, - 0x73, 0x68, 0x53, 0x74, 0x72, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0xaf, - 0x01, 0x0a, 0x10, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, - 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, - 0x64, 0x53, 0x74, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, - 0x6f, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, - 0x22, 0x84, 0x01, 0x0a, 0x11, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x66, 0x65, 0x72, 0x52, 0x0c, 0x62, 0x75, 0x72, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x09, 0x62, 0x75, - 0x72, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x41, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2a, 0x28, 0x0a, 0x09, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, - 0x4c, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4c, 0x4c, 0x45, 0x43, 0x54, 0x49, 0x42, - 0x4c, 0x45, 0x10, 0x01, 0x2a, 0x25, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x54, 0x41, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x10, 0x00, 0x2a, 0x3a, 0x0a, 0x0c, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x41, - 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x30, 0x10, - 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, - 0x4f, 0x4e, 0x5f, 0x56, 0x31, 0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1a, - 0x0a, 0x16, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50, - 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x4f, 0x55, - 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, - 0x45, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, - 0x22, 0x0a, 0x1e, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, - 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, - 0x54, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, - 0x45, 0x5f, 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x10, 0x04, 0x2a, 0xd0, 0x01, 0x0a, 0x0f, 0x41, - 0x64, 0x64, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, - 0x0a, 0x19, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x2a, 0x0a, - 0x26, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, - 0x45, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x41, 0x44, 0x44, - 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, - 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, - 0x52, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, - 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4f, - 0x46, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x12, 0x23, 0x0a, + 0x0d, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x79, + 0x70, 0x65, 0x22, 0x28, 0x0a, 0x26, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d, 0x0a, 0x19, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x26, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0xf5, 0x01, 0x0a, 0x11, + 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x71, 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x77, 0x61, 0x69, 0x74, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x66, 0x65, 0x72, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x57, 0x61, 0x69, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x1c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x19, 0x61, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x15, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, + 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, + 0x00, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x6d, 0x65, + 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x53, 0x74, 0x72, 0x12, 0x24, 0x0a, + 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, + 0x53, 0x74, 0x72, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0xaf, 0x01, 0x0a, + 0x10, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1b, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x22, + 0x0a, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x49, 0x64, 0x53, + 0x74, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x5f, + 0x62, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x54, 0x6f, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x65, 0x78, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0x84, + 0x01, 0x0a, 0x11, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x61, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, + 0x65, 0x72, 0x52, 0x0c, 0x62, 0x75, 0x72, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x12, 0x33, 0x0a, 0x0a, 0x62, 0x75, 0x72, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, + 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x09, 0x62, 0x75, 0x72, 0x6e, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x41, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2a, 0x28, 0x0a, 0x09, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, + 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4c, 0x4c, 0x45, 0x43, 0x54, 0x49, 0x42, 0x4c, 0x45, + 0x10, 0x01, 0x2a, 0x25, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x54, 0x41, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x10, 0x00, 0x2a, 0x3a, 0x0a, 0x0c, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x53, 0x53, + 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x30, 0x10, 0x00, 0x12, + 0x14, 0x0a, 0x10, 0x41, 0x53, 0x53, 0x45, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, + 0x5f, 0x56, 0x31, 0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, + 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, + 0x54, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x4f, 0x55, 0x54, 0x50, + 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, + 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x22, 0x0a, + 0x1e, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x41, 0x53, + 0x53, 0x49, 0x56, 0x45, 0x5f, 0x53, 0x50, 0x4c, 0x49, 0x54, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, + 0x03, 0x12, 0x25, 0x0a, 0x21, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x56, 0x45, 0x5f, + 0x41, 0x53, 0x53, 0x45, 0x54, 0x53, 0x10, 0x04, 0x2a, 0xd0, 0x01, 0x0a, 0x0f, 0x41, 0x64, 0x64, + 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x52, 0x0a, - 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, - 0x53, 0x46, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x00, - 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, - 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x10, - 0x01, 0x32, 0x86, 0x0b, 0x0a, 0x0d, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, - 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, - 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x2a, 0x0a, 0x26, 0x41, + 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, + 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x54, + 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x41, 0x44, 0x44, 0x52, 0x5f, + 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, 0x52, 0x41, + 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, + 0x45, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, + 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, + 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x44, + 0x44, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, + 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x52, 0x0a, 0x11, 0x50, + 0x72, 0x6f, 0x6f, 0x66, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, + 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x1f, + 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, 0x45, 0x52, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x10, 0x01, 0x32, + 0x86, 0x0b, 0x0a, 0x0d, 0x54, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, + 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, + 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, + 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x4c, + 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x74, 0x61, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x43, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x2e, - 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, - 0x72, 0x73, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x41, 0x64, - 0x64, 0x72, 0x12, 0x16, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, - 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x44, 0x65, 0x63, 0x6f, - 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, - 0x49, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x12, - 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x1b, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x44, 0x65, 0x63, - 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x12, - 0x40, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, + 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x74, 0x61, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x73, + 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, + 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x16, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, + 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, + 0x63, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x0c, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x49, 0x0a, + 0x0c, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x12, 0x1b, 0x2e, + 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x44, 0x65, 0x63, 0x6f, 0x64, + 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x63, 0x6f, + 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3c, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1a, + 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x40, 0x0a, + 0x09, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, + 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x40, 0x0a, 0x09, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x40, 0x0a, 0x09, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x18, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, - 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x65, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, - 0x2b, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, - 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, - 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, - 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, - 0x73, 0x73, 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x42, 0x75, 0x72, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x74, + 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, + 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2b, 0x2e, + 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, + 0x66, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x61, 0x70, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x74, 0x66, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x73, 0x2f, 0x74, 0x61, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -5848,68 +5859,69 @@ var file_taprootassets_proto_depIdxs = []int32{ 11, // 38: taprpc.DecodedProof.group_key_reveal:type_name -> taprpc.GroupKeyReveal 47, // 39: taprpc.VerifyProofResponse.decoded_proof:type_name -> taprpc.DecodedProof 47, // 40: taprpc.DecodeProofResponse.decoded_proof:type_name -> taprpc.DecodedProof - 38, // 41: taprpc.AddrEvent.addr:type_name -> taprpc.Addr - 4, // 42: taprpc.AddrEvent.status:type_name -> taprpc.AddrEventStatus - 4, // 43: taprpc.AddrReceivesRequest.filter_status:type_name -> taprpc.AddrEventStatus - 52, // 44: taprpc.AddrReceivesResponse.events:type_name -> taprpc.AddrEvent - 30, // 45: taprpc.SendAssetResponse.transfer:type_name -> taprpc.AssetTransfer - 62, // 46: taprpc.SendAssetEvent.execute_send_state_event:type_name -> taprpc.ExecuteSendStateEvent - 63, // 47: taprpc.SendAssetEvent.proof_transfer_backoff_wait_event:type_name -> taprpc.ProofTransferBackoffWaitEvent - 5, // 48: taprpc.ProofTransferBackoffWaitEvent.transfer_type:type_name -> taprpc.ProofTransferType - 38, // 49: taprpc.AssetReceiveCompleteEvent.address:type_name -> taprpc.Addr - 63, // 50: taprpc.ReceiveAssetEvent.proof_transfer_backoff_wait_event:type_name -> taprpc.ProofTransferBackoffWaitEvent - 65, // 51: taprpc.ReceiveAssetEvent.asset_receive_complete_event:type_name -> taprpc.AssetReceiveCompleteEvent - 30, // 52: taprpc.BurnAssetResponse.burn_transfer:type_name -> taprpc.AssetTransfer - 47, // 53: taprpc.BurnAssetResponse.burn_proof:type_name -> taprpc.DecodedProof - 18, // 54: taprpc.ListUtxosResponse.ManagedUtxosEntry.value:type_name -> taprpc.ManagedUtxo - 22, // 55: taprpc.ListGroupsResponse.GroupsEntry.value:type_name -> taprpc.GroupedAssets - 25, // 56: taprpc.ListBalancesResponse.AssetBalancesEntry.value:type_name -> taprpc.AssetBalance - 26, // 57: taprpc.ListBalancesResponse.AssetGroupBalancesEntry.value:type_name -> taprpc.AssetGroupBalance - 7, // 58: taprpc.TaprootAssets.ListAssets:input_type -> taprpc.ListAssetRequest - 17, // 59: taprpc.TaprootAssets.ListUtxos:input_type -> taprpc.ListUtxosRequest - 20, // 60: taprpc.TaprootAssets.ListGroups:input_type -> taprpc.ListGroupsRequest - 24, // 61: taprpc.TaprootAssets.ListBalances:input_type -> taprpc.ListBalancesRequest - 28, // 62: taprpc.TaprootAssets.ListTransfers:input_type -> taprpc.ListTransfersRequest - 34, // 63: taprpc.TaprootAssets.StopDaemon:input_type -> taprpc.StopRequest - 36, // 64: taprpc.TaprootAssets.DebugLevel:input_type -> taprpc.DebugLevelRequest - 39, // 65: taprpc.TaprootAssets.QueryAddrs:input_type -> taprpc.QueryAddrRequest - 41, // 66: taprpc.TaprootAssets.NewAddr:input_type -> taprpc.NewAddrRequest - 45, // 67: taprpc.TaprootAssets.DecodeAddr:input_type -> taprpc.DecodeAddrRequest - 53, // 68: taprpc.TaprootAssets.AddrReceives:input_type -> taprpc.AddrReceivesRequest - 46, // 69: taprpc.TaprootAssets.VerifyProof:input_type -> taprpc.ProofFile - 49, // 70: taprpc.TaprootAssets.DecodeProof:input_type -> taprpc.DecodeProofRequest - 51, // 71: taprpc.TaprootAssets.ExportProof:input_type -> taprpc.ExportProofRequest - 55, // 72: taprpc.TaprootAssets.SendAsset:input_type -> taprpc.SendAssetRequest - 68, // 73: taprpc.TaprootAssets.BurnAsset:input_type -> taprpc.BurnAssetRequest - 58, // 74: taprpc.TaprootAssets.GetInfo:input_type -> taprpc.GetInfoRequest - 60, // 75: taprpc.TaprootAssets.SubscribeSendAssetEventNtfns:input_type -> taprpc.SubscribeSendAssetEventNtfnsRequest - 64, // 76: taprpc.TaprootAssets.SubscribeReceiveAssetEventNtfns:input_type -> taprpc.SubscribeReceiveAssetEventNtfnsRequest - 67, // 77: taprpc.TaprootAssets.FetchAssetMeta:input_type -> taprpc.FetchAssetMetaRequest - 16, // 78: taprpc.TaprootAssets.ListAssets:output_type -> taprpc.ListAssetResponse - 19, // 79: taprpc.TaprootAssets.ListUtxos:output_type -> taprpc.ListUtxosResponse - 23, // 80: taprpc.TaprootAssets.ListGroups:output_type -> taprpc.ListGroupsResponse - 27, // 81: taprpc.TaprootAssets.ListBalances:output_type -> taprpc.ListBalancesResponse - 29, // 82: taprpc.TaprootAssets.ListTransfers:output_type -> taprpc.ListTransfersResponse - 35, // 83: taprpc.TaprootAssets.StopDaemon:output_type -> taprpc.StopResponse - 37, // 84: taprpc.TaprootAssets.DebugLevel:output_type -> taprpc.DebugLevelResponse - 40, // 85: taprpc.TaprootAssets.QueryAddrs:output_type -> taprpc.QueryAddrResponse - 38, // 86: taprpc.TaprootAssets.NewAddr:output_type -> taprpc.Addr - 38, // 87: taprpc.TaprootAssets.DecodeAddr:output_type -> taprpc.Addr - 54, // 88: taprpc.TaprootAssets.AddrReceives:output_type -> taprpc.AddrReceivesResponse - 48, // 89: taprpc.TaprootAssets.VerifyProof:output_type -> taprpc.VerifyProofResponse - 50, // 90: taprpc.TaprootAssets.DecodeProof:output_type -> taprpc.DecodeProofResponse - 46, // 91: taprpc.TaprootAssets.ExportProof:output_type -> taprpc.ProofFile - 57, // 92: taprpc.TaprootAssets.SendAsset:output_type -> taprpc.SendAssetResponse - 69, // 93: taprpc.TaprootAssets.BurnAsset:output_type -> taprpc.BurnAssetResponse - 59, // 94: taprpc.TaprootAssets.GetInfo:output_type -> taprpc.GetInfoResponse - 61, // 95: taprpc.TaprootAssets.SubscribeSendAssetEventNtfns:output_type -> taprpc.SendAssetEvent - 66, // 96: taprpc.TaprootAssets.SubscribeReceiveAssetEventNtfns:output_type -> taprpc.ReceiveAssetEvent - 6, // 97: taprpc.TaprootAssets.FetchAssetMeta:output_type -> taprpc.AssetMeta - 78, // [78:98] is the sub-list for method output_type - 58, // [58:78] is the sub-list for method input_type - 58, // [58:58] is the sub-list for extension type_name - 58, // [58:58] is the sub-list for extension extendee - 0, // [0:58] is the sub-list for field type_name + 70, // 41: taprpc.ExportProofRequest.outpoint:type_name -> taprpc.OutPoint + 38, // 42: taprpc.AddrEvent.addr:type_name -> taprpc.Addr + 4, // 43: taprpc.AddrEvent.status:type_name -> taprpc.AddrEventStatus + 4, // 44: taprpc.AddrReceivesRequest.filter_status:type_name -> taprpc.AddrEventStatus + 52, // 45: taprpc.AddrReceivesResponse.events:type_name -> taprpc.AddrEvent + 30, // 46: taprpc.SendAssetResponse.transfer:type_name -> taprpc.AssetTransfer + 62, // 47: taprpc.SendAssetEvent.execute_send_state_event:type_name -> taprpc.ExecuteSendStateEvent + 63, // 48: taprpc.SendAssetEvent.proof_transfer_backoff_wait_event:type_name -> taprpc.ProofTransferBackoffWaitEvent + 5, // 49: taprpc.ProofTransferBackoffWaitEvent.transfer_type:type_name -> taprpc.ProofTransferType + 38, // 50: taprpc.AssetReceiveCompleteEvent.address:type_name -> taprpc.Addr + 63, // 51: taprpc.ReceiveAssetEvent.proof_transfer_backoff_wait_event:type_name -> taprpc.ProofTransferBackoffWaitEvent + 65, // 52: taprpc.ReceiveAssetEvent.asset_receive_complete_event:type_name -> taprpc.AssetReceiveCompleteEvent + 30, // 53: taprpc.BurnAssetResponse.burn_transfer:type_name -> taprpc.AssetTransfer + 47, // 54: taprpc.BurnAssetResponse.burn_proof:type_name -> taprpc.DecodedProof + 18, // 55: taprpc.ListUtxosResponse.ManagedUtxosEntry.value:type_name -> taprpc.ManagedUtxo + 22, // 56: taprpc.ListGroupsResponse.GroupsEntry.value:type_name -> taprpc.GroupedAssets + 25, // 57: taprpc.ListBalancesResponse.AssetBalancesEntry.value:type_name -> taprpc.AssetBalance + 26, // 58: taprpc.ListBalancesResponse.AssetGroupBalancesEntry.value:type_name -> taprpc.AssetGroupBalance + 7, // 59: taprpc.TaprootAssets.ListAssets:input_type -> taprpc.ListAssetRequest + 17, // 60: taprpc.TaprootAssets.ListUtxos:input_type -> taprpc.ListUtxosRequest + 20, // 61: taprpc.TaprootAssets.ListGroups:input_type -> taprpc.ListGroupsRequest + 24, // 62: taprpc.TaprootAssets.ListBalances:input_type -> taprpc.ListBalancesRequest + 28, // 63: taprpc.TaprootAssets.ListTransfers:input_type -> taprpc.ListTransfersRequest + 34, // 64: taprpc.TaprootAssets.StopDaemon:input_type -> taprpc.StopRequest + 36, // 65: taprpc.TaprootAssets.DebugLevel:input_type -> taprpc.DebugLevelRequest + 39, // 66: taprpc.TaprootAssets.QueryAddrs:input_type -> taprpc.QueryAddrRequest + 41, // 67: taprpc.TaprootAssets.NewAddr:input_type -> taprpc.NewAddrRequest + 45, // 68: taprpc.TaprootAssets.DecodeAddr:input_type -> taprpc.DecodeAddrRequest + 53, // 69: taprpc.TaprootAssets.AddrReceives:input_type -> taprpc.AddrReceivesRequest + 46, // 70: taprpc.TaprootAssets.VerifyProof:input_type -> taprpc.ProofFile + 49, // 71: taprpc.TaprootAssets.DecodeProof:input_type -> taprpc.DecodeProofRequest + 51, // 72: taprpc.TaprootAssets.ExportProof:input_type -> taprpc.ExportProofRequest + 55, // 73: taprpc.TaprootAssets.SendAsset:input_type -> taprpc.SendAssetRequest + 68, // 74: taprpc.TaprootAssets.BurnAsset:input_type -> taprpc.BurnAssetRequest + 58, // 75: taprpc.TaprootAssets.GetInfo:input_type -> taprpc.GetInfoRequest + 60, // 76: taprpc.TaprootAssets.SubscribeSendAssetEventNtfns:input_type -> taprpc.SubscribeSendAssetEventNtfnsRequest + 64, // 77: taprpc.TaprootAssets.SubscribeReceiveAssetEventNtfns:input_type -> taprpc.SubscribeReceiveAssetEventNtfnsRequest + 67, // 78: taprpc.TaprootAssets.FetchAssetMeta:input_type -> taprpc.FetchAssetMetaRequest + 16, // 79: taprpc.TaprootAssets.ListAssets:output_type -> taprpc.ListAssetResponse + 19, // 80: taprpc.TaprootAssets.ListUtxos:output_type -> taprpc.ListUtxosResponse + 23, // 81: taprpc.TaprootAssets.ListGroups:output_type -> taprpc.ListGroupsResponse + 27, // 82: taprpc.TaprootAssets.ListBalances:output_type -> taprpc.ListBalancesResponse + 29, // 83: taprpc.TaprootAssets.ListTransfers:output_type -> taprpc.ListTransfersResponse + 35, // 84: taprpc.TaprootAssets.StopDaemon:output_type -> taprpc.StopResponse + 37, // 85: taprpc.TaprootAssets.DebugLevel:output_type -> taprpc.DebugLevelResponse + 40, // 86: taprpc.TaprootAssets.QueryAddrs:output_type -> taprpc.QueryAddrResponse + 38, // 87: taprpc.TaprootAssets.NewAddr:output_type -> taprpc.Addr + 38, // 88: taprpc.TaprootAssets.DecodeAddr:output_type -> taprpc.Addr + 54, // 89: taprpc.TaprootAssets.AddrReceives:output_type -> taprpc.AddrReceivesResponse + 48, // 90: taprpc.TaprootAssets.VerifyProof:output_type -> taprpc.VerifyProofResponse + 50, // 91: taprpc.TaprootAssets.DecodeProof:output_type -> taprpc.DecodeProofResponse + 46, // 92: taprpc.TaprootAssets.ExportProof:output_type -> taprpc.ProofFile + 57, // 93: taprpc.TaprootAssets.SendAsset:output_type -> taprpc.SendAssetResponse + 69, // 94: taprpc.TaprootAssets.BurnAsset:output_type -> taprpc.BurnAssetResponse + 59, // 95: taprpc.TaprootAssets.GetInfo:output_type -> taprpc.GetInfoResponse + 61, // 96: taprpc.TaprootAssets.SubscribeSendAssetEventNtfns:output_type -> taprpc.SendAssetEvent + 66, // 97: taprpc.TaprootAssets.SubscribeReceiveAssetEventNtfns:output_type -> taprpc.ReceiveAssetEvent + 6, // 98: taprpc.TaprootAssets.FetchAssetMeta:output_type -> taprpc.AssetMeta + 79, // [79:99] is the sub-list for method output_type + 59, // [59:79] is the sub-list for method input_type + 59, // [59:59] is the sub-list for extension type_name + 59, // [59:59] is the sub-list for extension extendee + 0, // [0:59] is the sub-list for field type_name } func init() { file_taprootassets_proto_init() } diff --git a/taprpc/taprootassets.proto b/taprpc/taprootassets.proto index ade173f44..ea9d1f8e3 100644 --- a/taprpc/taprootassets.proto +++ b/taprpc/taprootassets.proto @@ -852,6 +852,7 @@ message DecodeProofResponse { message ExportProofRequest { bytes asset_id = 1; bytes script_key = 2; + OutPoint outpoint = 3; // TODO(roasbeef): specify information to make new state transition in proof // file? diff --git a/taprpc/taprootassets.swagger.json b/taprpc/taprootassets.swagger.json index 055a248ec..6ab3da04a 100644 --- a/taprpc/taprootassets.swagger.json +++ b/taprpc/taprootassets.swagger.json @@ -1490,6 +1490,9 @@ "script_key": { "type": "string", "format": "byte" + }, + "outpoint": { + "$ref": "#/definitions/taprpcOutPoint" } } }, @@ -1759,6 +1762,21 @@ } } }, + "taprpcOutPoint": { + "type": "object", + "properties": { + "txid": { + "type": "string", + "format": "byte", + "description": "Raw bytes representing the transaction id." + }, + "output_index": { + "type": "integer", + "format": "int64", + "description": "The index of the output on the transaction." + } + } + }, "taprpcOutputType": { "type": "string", "enum": [ From 46de474a1fd6178ad29b10027bc689425c28ea96 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:04 +0100 Subject: [PATCH 13/19] proof+tapdb: turn FetchAssetProof into :many query --- proof/archive.go | 9 ++- tapdb/addrs.go | 25 +++++++-- tapdb/asset_minting_test.go | 12 ++-- tapdb/assets_store.go | 102 ++++++++++++++++++++++++---------- tapdb/assets_store_test.go | 2 +- tapdb/sqlc/assets.sql.go | 40 +++++++++---- tapdb/sqlc/querier.go | 2 +- tapdb/sqlc/queries/assets.sql | 2 +- 8 files changed, 138 insertions(+), 56 deletions(-) diff --git a/proof/archive.go b/proof/archive.go index 7506cbc84..d4de97bcd 100644 --- a/proof/archive.go +++ b/proof/archive.go @@ -140,7 +140,9 @@ type Archiver interface { // passed ProofIdentifier. // // If a proof cannot be found, then ErrProofNotFound should be - // returned. + // returned. If multiple proofs exist for the given fields of the + // locator then ErrMultipleProofs should be returned to indicate more + // specific fields need to be set in the Locator (e.g. the OutPoint). FetchProof(ctx context.Context, id Locator) (Blob, error) // HasProof returns true if the proof for the given locator exists. This @@ -499,7 +501,10 @@ func migrateOldFileNames(rootPath string) error { // FetchProof fetches a proof for an asset uniquely identified by the passed // ProofIdentifier. // -// If a proof cannot be found, then ErrProofNotFound should be returned. +// If a proof cannot be found, then ErrProofNotFound should be returned. If +// multiple proofs exist for the given fields of the locator then +// ErrMultipleProofs is returned to indicate more specific fields need to be set +// in the Locator (e.g. the OutPoint). // // NOTE: This implements the Archiver interface. func (f *FileArchiver) FetchProof(_ context.Context, id Locator) (Blob, error) { diff --git a/tapdb/addrs.go b/tapdb/addrs.go index 1abd8cd2c..26921fb25 100644 --- a/tapdb/addrs.go +++ b/tapdb/addrs.go @@ -20,6 +20,7 @@ import ( "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/commitment" "github.com/lightninglabs/taproot-assets/fn" + "github.com/lightninglabs/taproot-assets/proof" "github.com/lightninglabs/taproot-assets/tapdb/sqlc" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/keychain" @@ -131,8 +132,8 @@ type AddrBook interface { // FetchAssetProof fetches the asset proof for a given asset identified // by its script key. - FetchAssetProof(ctx context.Context, arg FetchAssetProof) (AssetProofI, - error) + FetchAssetProof(ctx context.Context, + arg FetchAssetProof) ([]AssetProofI, error) // FetchGenesisByAssetID attempts to fetch asset genesis information // for a given asset ID. @@ -912,6 +913,22 @@ func (t *TapAddressBook) CompleteEvent(ctx context.Context, return fmt.Errorf("error fetching asset proof: %w", err) } + switch { + // We have no proof for this script key and outpoint. + case len(proofData) == 0: + return fmt.Errorf("proof for script key %x and "+ + "outpoint %v not found: %w", + args.TweakedScriptKey, anchorPoint, + proof.ErrProofNotFound) + + // Something is quite wrong if we have multiple proofs for the + // same script key and outpoint. + case len(proofData) > 1: + return fmt.Errorf("expected exactly one proof, got "+ + "%d: %w", len(proofData), + proof.ErrMultipleProofs) + } + _, err = db.UpsertAddrEvent(ctx, UpsertAddrEvent{ TaprootOutputKey: schnorr.SerializePubKey( &event.Addr.TaprootOutputKey, @@ -919,8 +936,8 @@ func (t *TapAddressBook) CompleteEvent(ctx context.Context, Status: int16(status), Txid: anchorPoint.Hash[:], ChainTxnOutputIndex: int32(anchorPoint.Index), - AssetProofID: sqlInt64(proofData.ProofID), - AssetID: sqlInt64(proofData.AssetID), + AssetProofID: sqlInt64(proofData[0].ProofID), + AssetID: sqlInt64(proofData[0].AssetID), }) return err }) diff --git a/tapdb/asset_minting_test.go b/tapdb/asset_minting_test.go index f984136c0..750024c4e 100644 --- a/tapdb/asset_minting_test.go +++ b/tapdb/asset_minting_test.go @@ -809,15 +809,17 @@ func TestCommitBatchChainActions(t *testing.T) { // If we look up all the proofs by their specific script key, we should // get the same set of proofs. - scriptKeys := fMapKeys( - assetProofs, func(k asset.SerializedKey) *btcec.PublicKey { - parsed, err := btcec.ParsePubKey(k.CopyBytes()) + proofLocators := fMapKeys( + assetProofs, func(k asset.SerializedKey) proof.Locator { + parsedScriptKey, err := btcec.ParsePubKey(k.CopyBytes()) require.NoError(t, err) - return parsed + return proof.Locator{ + ScriptKey: *parsedScriptKey, + } }, ) - diskProofs, err = confAssets.FetchAssetProofs(ctx, scriptKeys...) + diskProofs, err = confAssets.FetchAssetProofs(ctx, proofLocators...) require.NoError(t, err) require.Equal(t, assetProofs, diskProofs) diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index 3a53c813a..90f5db4d0 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -176,7 +176,7 @@ type ActiveAssetsStore interface { // FetchAssetProof fetches the asset proof for a given asset identified // by its script key. FetchAssetProof(ctx context.Context, - arg FetchAssetProof) (AssetProofI, error) + arg FetchAssetProof) ([]AssetProofI, error) // HasAssetProof returns true if we have proof for a given asset // identified by its script key. @@ -1106,7 +1106,7 @@ func (a *AssetStore) FetchManagedUTXOs(ctx context.Context) ( // TODO(roasbeef): potentially have a version that writes thru a reader // instead? func (a *AssetStore) FetchAssetProofs(ctx context.Context, - targetAssets ...*btcec.PublicKey) (proof.AssetBlobs, error) { + targetAssets ...proof.Locator) (proof.AssetBlobs, error) { proofs := make(proof.AssetBlobs) @@ -1139,21 +1139,32 @@ func (a *AssetStore) FetchAssetProofs(ctx context.Context, // TODO(roasbeef): can modify the query to use IN somewhere // instead? then would take input params and insert into // virtual rows to use - for _, scriptKey := range targetAssets { - scriptKey := scriptKey - serializedKey := asset.ToSerialized(scriptKey) + for _, locator := range targetAssets { + args, err := locatorToProofQuery(locator) + if err != nil { + return err + } - assetProof, err := q.FetchAssetProof( - ctx, FetchAssetProof{ - TweakedScriptKey: serializedKey[:], - }, - ) + assetProofs, err := q.FetchAssetProof(ctx, args) if err != nil { return fmt.Errorf("unable to fetch asset "+ "proof: %w", err) } - proofs[serializedKey] = assetProof.ProofFile + switch { + // We have no proof for this script key. + case len(assetProofs) == 0: + return proof.ErrProofNotFound + + // Something went wrong, presumably because the outpoint + // was not specified in the locator, and we got multiple + // proofs. + case len(assetProofs) > 1: + return proof.ErrMultipleProofs + } + + serializedKey := asset.ToSerialized(&locator.ScriptKey) + proofs[serializedKey] = assetProofs[0].ProofFile } return nil }) @@ -1167,41 +1178,48 @@ func (a *AssetStore) FetchAssetProofs(ctx context.Context, // FetchProof fetches a proof for an asset uniquely identified by the passed // ProofIdentifier. // +// If a proof cannot be found, then ErrProofNotFound should be returned. If +// multiple proofs exist for the given fields of the locator then +// ErrMultipleProofs is returned to indicate more specific fields need to be set +// in the Locator (e.g. the OutPoint). +// // NOTE: This implements the proof.Archiver interface. func (a *AssetStore) FetchProof(ctx context.Context, locator proof.Locator) (proof.Blob, error) { - // We have an on-disk index for all proofs we store, so we can use the - // script key as the primary identifier. - args := FetchAssetProof{ - TweakedScriptKey: locator.ScriptKey.SerializeCompressed(), - } - - // But script keys aren't unique, so if the locator explicitly specifies - // an outpoint, we'll use that as well. - if locator.OutPoint != nil { - outpoint, err := encodeOutpoint(*locator.OutPoint) - if err != nil { - return nil, fmt.Errorf("unable to encode outpoint: %w", - err) - } - - args.Outpoint = outpoint + args, err := locatorToProofQuery(locator) + if err != nil { + return nil, err } var diskProof proof.Blob readOpts := NewAssetStoreReadTx() dbErr := a.db.ExecTx(ctx, &readOpts, func(q ActiveAssetsStore) error { - assetProof, err := q.FetchAssetProof(ctx, args) + assetProofs, err := q.FetchAssetProof(ctx, args) if err != nil { return fmt.Errorf("unable to fetch asset proof: %w", err) } - diskProof = assetProof.ProofFile + switch { + // We have no proof for this script key. + case len(assetProofs) == 0: + return proof.ErrProofNotFound - return nil + // If the query without the outpoint returns exactly one proof + // then we're fine. If there actually are multiple proofs, we + // require the user to specify the outpoint as well. + case len(assetProofs) == 1: + diskProof = assetProofs[0].ProofFile + + return nil + + // User needs to specify the outpoint as well, since we have + // multiple proofs for this script key. + default: + return proof.ErrMultipleProofs + } }) switch { case errors.Is(dbErr, sql.ErrNoRows): @@ -1213,6 +1231,30 @@ func (a *AssetStore) FetchProof(ctx context.Context, return diskProof, nil } +// locatorToProofQuery turns a proof locator into a FetchAssetProof query +// struct. +func locatorToProofQuery(locator proof.Locator) (FetchAssetProof, error) { + // We have an on-disk index for all proofs we store, so we can use the + // script key as the primary identifier. + args := FetchAssetProof{ + TweakedScriptKey: locator.ScriptKey.SerializeCompressed(), + } + + // But script keys aren't unique, so if the locator explicitly specifies + // an outpoint, we'll use that as well. + if locator.OutPoint != nil { + outpoint, err := encodeOutpoint(*locator.OutPoint) + if err != nil { + return args, fmt.Errorf("unable to encode outpoint: %w", + err) + } + + args.Outpoint = outpoint + } + + return args, nil +} + // HasProof returns true if the proof for the given locator exists. This is // intended to be a performance optimized lookup compared to fetching a proof // and checking for ErrProofNotFound. diff --git a/tapdb/assets_store_test.go b/tapdb/assets_store_test.go index 4fd0b7f50..ddbd60bb3 100644 --- a/tapdb/assets_store_test.go +++ b/tapdb/assets_store_test.go @@ -1459,7 +1459,7 @@ func TestAssetExportLog(t *testing.T) { TweakedScriptKey: newScriptKey.PubKey.SerializeCompressed(), }) require.NoError(t, err) - require.Equal(t, receiverBlob, diskSenderBlob.ProofFile) + require.Equal(t, receiverBlob, diskSenderBlob[0].ProofFile) // If we fetch the chain transaction again, then it should have the // conf information populated. diff --git a/tapdb/sqlc/assets.sql.go b/tapdb/sqlc/assets.sql.go index f84138bb7..436719678 100644 --- a/tapdb/sqlc/assets.sql.go +++ b/tapdb/sqlc/assets.sql.go @@ -506,7 +506,7 @@ func (q *Queries) FetchAssetMetaForAsset(ctx context.Context, assetID []byte) (F return i, err } -const fetchAssetProof = `-- name: FetchAssetProof :one +const fetchAssetProof = `-- name: FetchAssetProof :many WITH asset_info AS ( SELECT assets.asset_id, script_keys.tweaked_script_key, utxos.outpoint FROM assets @@ -538,17 +538,33 @@ type FetchAssetProofRow struct { Outpoint []byte } -func (q *Queries) FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) (FetchAssetProofRow, error) { - row := q.db.QueryRowContext(ctx, fetchAssetProof, arg.TweakedScriptKey, arg.Outpoint) - var i FetchAssetProofRow - err := row.Scan( - &i.ScriptKey, - &i.ProofFile, - &i.AssetID, - &i.ProofID, - &i.Outpoint, - ) - return i, err +func (q *Queries) FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) ([]FetchAssetProofRow, error) { + rows, err := q.db.QueryContext(ctx, fetchAssetProof, arg.TweakedScriptKey, arg.Outpoint) + if err != nil { + return nil, err + } + defer rows.Close() + var items []FetchAssetProofRow + for rows.Next() { + var i FetchAssetProofRow + if err := rows.Scan( + &i.ScriptKey, + &i.ProofFile, + &i.AssetID, + &i.ProofID, + &i.Outpoint, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil } const fetchAssetProofs = `-- name: FetchAssetProofs :many diff --git a/tapdb/sqlc/querier.go b/tapdb/sqlc/querier.go index 56f83238f..38c0514ad 100644 --- a/tapdb/sqlc/querier.go +++ b/tapdb/sqlc/querier.go @@ -42,7 +42,7 @@ type Querier interface { FetchAssetMeta(ctx context.Context, metaID int64) (FetchAssetMetaRow, error) FetchAssetMetaByHash(ctx context.Context, metaDataHash []byte) (FetchAssetMetaByHashRow, error) FetchAssetMetaForAsset(ctx context.Context, assetID []byte) (FetchAssetMetaForAssetRow, error) - FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) (FetchAssetProofRow, error) + FetchAssetProof(ctx context.Context, arg FetchAssetProofParams) ([]FetchAssetProofRow, error) FetchAssetProofs(ctx context.Context) ([]FetchAssetProofsRow, error) FetchAssetProofsByAssetID(ctx context.Context, assetID []byte) ([]FetchAssetProofsByAssetIDRow, error) FetchAssetWitnesses(ctx context.Context, assetID sql.NullInt64) ([]FetchAssetWitnessesRow, error) diff --git a/tapdb/sqlc/queries/assets.sql b/tapdb/sqlc/queries/assets.sql index b995c729a..556b954da 100644 --- a/tapdb/sqlc/queries/assets.sql +++ b/tapdb/sqlc/queries/assets.sql @@ -684,7 +684,7 @@ FROM asset_proofs JOIN asset_info ON asset_info.asset_id = asset_proofs.asset_id; --- name: FetchAssetProof :one +-- name: FetchAssetProof :many WITH asset_info AS ( SELECT assets.asset_id, script_keys.tweaked_script_key, utxos.outpoint FROM assets From 4c6f042e6bbaece304734e5ffe9787c22871e4d1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:05 +0100 Subject: [PATCH 14/19] tapdb: turn InsertAssetWitness into UpsertAssetWitness Because we can now end up importing proofs that we already have (for example when sending to our own TAP address using a universe courier, we will pull the proof from the local universe and import it into our store again). Before turning this into an upsert, we would end up with an asset that had two identical entries in the previous witness list. To make sure the order of multiple witnesses is kept, we also need to add a witness_index field that we can use for sorting. Unfortunately that breaks the data migration demo test as the FetchAllAssets query also loads the witness and the query for that uses the witness_index field that doesn't exist at that point. Since the current test is only a demo we just change it to fetch the (unchanged) managed UTXOs instead. --- tapdb/assets_store.go | 11 ++- tapdb/migrations_test.go | 12 ++-- tapdb/sqlc/assets.sql.go | 69 +++++++++++-------- .../000015_asset_witnesses.down.sql | 2 + .../migrations/000015_asset_witnesses.up.sql | 11 +++ tapdb/sqlc/models.go | 1 + tapdb/sqlc/querier.go | 2 +- tapdb/sqlc/queries/assets.sql | 17 +++-- 8 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 tapdb/sqlc/migrations/000015_asset_witnesses.down.sql create mode 100644 tapdb/sqlc/migrations/000015_asset_witnesses.up.sql diff --git a/tapdb/assets_store.go b/tapdb/assets_store.go index 90f5db4d0..0f0186a3a 100644 --- a/tapdb/assets_store.go +++ b/tapdb/assets_store.go @@ -54,7 +54,7 @@ type ( // PrevInput stores the full input information including the prev out, // and also the witness information itself. - PrevInput = sqlc.InsertAssetWitnessParams + PrevInput = sqlc.UpsertAssetWitnessParams // AssetWitness is the full prev input for an asset that also couples // along the asset ID that the witness belong to. @@ -207,9 +207,9 @@ type ActiveAssetsStore interface { // proof on disk. UpsertAssetProofByID(ctx context.Context, arg ProofUpdateByID) error - // InsertAssetWitness inserts a new prev input for an asset into the + // UpsertAssetWitness upserts a new prev input for an asset into the // database. - InsertAssetWitness(context.Context, PrevInput) error + UpsertAssetWitness(context.Context, PrevInput) error // FetchAssetWitnesses attempts to fetch either all the asset witnesses // on disk (NULL param), or the witness for a given asset ID. @@ -1360,8 +1360,6 @@ func (a *AssetStore) FetchProofs(ctx context.Context, // insertAssetWitnesses attempts to insert the set of asset witnesses in to the // database, referencing the passed asset primary key. -// -// TODO(ffranr): Change insert function into an upsert. func (a *AssetStore) insertAssetWitnesses(ctx context.Context, db ActiveAssetsStore, assetID int64, inputs []asset.Witness) error { @@ -1404,13 +1402,14 @@ func (a *AssetStore) insertAssetWitnesses(ctx context.Context, copy(splitCommitmentProof, b.Bytes()) } - err = db.InsertAssetWitness(ctx, PrevInput{ + err = db.UpsertAssetWitness(ctx, PrevInput{ AssetID: assetID, PrevOutPoint: prevOutpoint, PrevAssetID: prevID.ID[:], PrevScriptKey: prevID.ScriptKey.CopyBytes(), WitnessStack: witnessStack, SplitCommitmentProof: splitCommitmentProof, + WitnessIndex: int32(idx), }) if err != nil { return fmt.Errorf("unable to insert witness: %v", err) diff --git a/tapdb/migrations_test.go b/tapdb/migrations_test.go index 6eda94381..dde9be5ba 100644 --- a/tapdb/migrations_test.go +++ b/tapdb/migrations_test.go @@ -18,17 +18,17 @@ func TestMigrationSteps(t *testing.T) { db := NewTestDBWithVersion(t, 1) // If we create an assets store now, there should be no tables for the - // assets yet. + // managed UTXOs yet. _, assetStore := newAssetStoreFromDB(db.BaseDB) - _, err := assetStore.FetchAllAssets(ctx, true, true, nil) + _, err := assetStore.FetchManagedUTXOs(ctx) require.True(t, IsSchemaError(MapSQLError(err))) // We now migrate to a later but not yet latest version. err = db.ExecuteMigrations(TargetVersion(11)) require.NoError(t, err) - // Now there should be an asset table. - _, err = assetStore.FetchAllAssets(ctx, true, true, nil) + // Now there should be a managed UTXOs table. + _, err = assetStore.FetchManagedUTXOs(ctx) require.NoError(t, err) // Assuming the next version does some changes to the data within the @@ -37,9 +37,9 @@ func TestMigrationSteps(t *testing.T) { InsertTestdata(t, db.BaseDB, "migrations_test_00011_dummy_data.sql") // Make sure we now have actual assets in the database. - dbAssets, err := assetStore.FetchAllAssets(ctx, true, true, nil) + utxos, err := assetStore.FetchManagedUTXOs(ctx) require.NoError(t, err) - require.Len(t, dbAssets, 4) + require.Len(t, utxos, 2) // And now that we have test data inserted, we can migrate to the latest // version. diff --git a/tapdb/sqlc/assets.sql.go b/tapdb/sqlc/assets.sql.go index 436719678..7fc8eb243 100644 --- a/tapdb/sqlc/assets.sql.go +++ b/tapdb/sqlc/assets.sql.go @@ -662,6 +662,7 @@ JOIN assets WHERE ( (assets.asset_id = $1) OR ($1 IS NULL) ) +ORDER BY witness_index ` type FetchAssetWitnessesRow struct { @@ -1749,36 +1750,6 @@ func (q *Queries) InsertAssetSeedlingIntoBatch(ctx context.Context, arg InsertAs return err } -const insertAssetWitness = `-- name: InsertAssetWitness :exec -INSERT INTO asset_witnesses ( - asset_id, prev_out_point, prev_asset_id, prev_script_key, witness_stack, - split_commitment_proof -) VALUES ( - $1, $2, $3, $4, $5, $6 -) -` - -type InsertAssetWitnessParams struct { - AssetID int64 - PrevOutPoint []byte - PrevAssetID []byte - PrevScriptKey []byte - WitnessStack []byte - SplitCommitmentProof []byte -} - -func (q *Queries) InsertAssetWitness(ctx context.Context, arg InsertAssetWitnessParams) error { - _, err := q.db.ExecContext(ctx, insertAssetWitness, - arg.AssetID, - arg.PrevOutPoint, - arg.PrevAssetID, - arg.PrevScriptKey, - arg.WitnessStack, - arg.SplitCommitmentProof, - ) - return err -} - const insertNewAsset = `-- name: InsertNewAsset :one INSERT INTO assets ( genesis_id, version, script_key_id, asset_group_witness_id, script_version, @@ -2393,6 +2364,44 @@ func (q *Queries) UpsertAssetProofByID(ctx context.Context, arg UpsertAssetProof return err } +const upsertAssetWitness = `-- name: UpsertAssetWitness :exec +INSERT INTO asset_witnesses ( + asset_id, prev_out_point, prev_asset_id, prev_script_key, witness_stack, + split_commitment_proof, witness_index +) VALUES ( + $1, $2, $3, $4, $5, $6, $7 +) ON CONFLICT (asset_id, witness_index) + -- We overwrite the witness with the new one. + DO UPDATE SET prev_out_point = EXCLUDED.prev_out_point, + prev_asset_id = EXCLUDED.prev_asset_id, + prev_script_key = EXCLUDED.prev_script_key, + witness_stack = EXCLUDED.witness_stack, + split_commitment_proof = EXCLUDED.split_commitment_proof +` + +type UpsertAssetWitnessParams struct { + AssetID int64 + PrevOutPoint []byte + PrevAssetID []byte + PrevScriptKey []byte + WitnessStack []byte + SplitCommitmentProof []byte + WitnessIndex int32 +} + +func (q *Queries) UpsertAssetWitness(ctx context.Context, arg UpsertAssetWitnessParams) error { + _, err := q.db.ExecContext(ctx, upsertAssetWitness, + arg.AssetID, + arg.PrevOutPoint, + arg.PrevAssetID, + arg.PrevScriptKey, + arg.WitnessStack, + arg.SplitCommitmentProof, + arg.WitnessIndex, + ) + return err +} + const upsertChainTx = `-- name: UpsertChainTx :one INSERT INTO chain_txns ( txid, raw_tx, chain_fees, block_height, block_hash, tx_index diff --git a/tapdb/sqlc/migrations/000015_asset_witnesses.down.sql b/tapdb/sqlc/migrations/000015_asset_witnesses.down.sql new file mode 100644 index 000000000..9e487c47c --- /dev/null +++ b/tapdb/sqlc/migrations/000015_asset_witnesses.down.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS asset_witnesses_asset_id_witness_index_unique; +ALTER TABLE asset_witnesses DROP COLUMN witness_index; diff --git a/tapdb/sqlc/migrations/000015_asset_witnesses.up.sql b/tapdb/sqlc/migrations/000015_asset_witnesses.up.sql new file mode 100644 index 000000000..4cb82f0c4 --- /dev/null +++ b/tapdb/sqlc/migrations/000015_asset_witnesses.up.sql @@ -0,0 +1,11 @@ +-- The witness index indicates the order of the witness in the list of witnesses +-- for a given asset. We didn't really support more than one witness before, so +-- the default value of 0 should be fine for all existing assets. +ALTER TABLE asset_witnesses ADD COLUMN witness_index INTEGER NOT NULL DEFAULT 0; + +-- We need to be able to upsert witnesses, so we need a unique constraint on +-- (asset_id, witness_index). +CREATE UNIQUE INDEX asset_witnesses_asset_id_witness_index_unique +ON asset_witnesses ( + asset_id, witness_index +); diff --git a/tapdb/sqlc/models.go b/tapdb/sqlc/models.go index 784ab41d9..cebf2d494 100644 --- a/tapdb/sqlc/models.go +++ b/tapdb/sqlc/models.go @@ -139,6 +139,7 @@ type AssetWitness struct { PrevScriptKey []byte WitnessStack []byte SplitCommitmentProof []byte + WitnessIndex int32 } type AssetsMetum struct { diff --git a/tapdb/sqlc/querier.go b/tapdb/sqlc/querier.go index 38c0514ad..bc018d91e 100644 --- a/tapdb/sqlc/querier.go +++ b/tapdb/sqlc/querier.go @@ -89,7 +89,6 @@ type Querier interface { InsertAssetTransfer(ctx context.Context, arg InsertAssetTransferParams) (int64, error) InsertAssetTransferInput(ctx context.Context, arg InsertAssetTransferInputParams) error InsertAssetTransferOutput(ctx context.Context, arg InsertAssetTransferOutputParams) error - InsertAssetWitness(ctx context.Context, arg InsertAssetWitnessParams) error InsertBranch(ctx context.Context, arg InsertBranchParams) error InsertCompactedLeaf(ctx context.Context, arg InsertCompactedLeafParams) error InsertLeaf(ctx context.Context, arg InsertLeafParams) error @@ -153,6 +152,7 @@ type Querier interface { UpsertAssetMeta(ctx context.Context, arg UpsertAssetMetaParams) (int64, error) UpsertAssetProof(ctx context.Context, arg UpsertAssetProofParams) error UpsertAssetProofByID(ctx context.Context, arg UpsertAssetProofByIDParams) error + UpsertAssetWitness(ctx context.Context, arg UpsertAssetWitnessParams) error UpsertChainTx(ctx context.Context, arg UpsertChainTxParams) (int64, error) UpsertFederationGlobalSyncConfig(ctx context.Context, arg UpsertFederationGlobalSyncConfigParams) error UpsertFederationProofSyncLog(ctx context.Context, arg UpsertFederationProofSyncLogParams) (int64, error) diff --git a/tapdb/sqlc/queries/assets.sql b/tapdb/sqlc/queries/assets.sql index 556b954da..d81d879aa 100644 --- a/tapdb/sqlc/queries/assets.sql +++ b/tapdb/sqlc/queries/assets.sql @@ -715,13 +715,19 @@ FROM asset_proofs JOIN asset_info ON asset_info.asset_id = asset_proofs.asset_id; --- name: InsertAssetWitness :exec +-- name: UpsertAssetWitness :exec INSERT INTO asset_witnesses ( asset_id, prev_out_point, prev_asset_id, prev_script_key, witness_stack, - split_commitment_proof + split_commitment_proof, witness_index ) VALUES ( - $1, $2, $3, $4, $5, $6 -); + $1, $2, $3, $4, $5, $6, $7 +) ON CONFLICT (asset_id, witness_index) + -- We overwrite the witness with the new one. + DO UPDATE SET prev_out_point = EXCLUDED.prev_out_point, + prev_asset_id = EXCLUDED.prev_asset_id, + prev_script_key = EXCLUDED.prev_script_key, + witness_stack = EXCLUDED.witness_stack, + split_commitment_proof = EXCLUDED.split_commitment_proof; -- name: FetchAssetWitnesses :many SELECT @@ -732,7 +738,8 @@ JOIN assets ON asset_witnesses.asset_id = assets.asset_id WHERE ( (assets.asset_id = sqlc.narg('asset_id')) OR (sqlc.narg('asset_id') IS NULL) -); +) +ORDER BY witness_index; -- name: DeleteManagedUTXO :exec DELETE FROM managed_utxos From 387d99e07dd236938dcb26d4d8eea45dd7dde048 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:06 +0100 Subject: [PATCH 15/19] tapgarden: detect startup errors in custodian test When starting the custodian and we get an error, we actually want to inspect the error. Otherwise we just get a timeout when listening for the subscription signals which doesn't really tell us what's wrong. This helped us debug an issue with a unit test in the previous commit. --- tapgarden/custodian_test.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tapgarden/custodian_test.go b/tapgarden/custodian_test.go index aa347dd1a..82c2a4e4e 100644 --- a/tapgarden/custodian_test.go +++ b/tapgarden/custodian_test.go @@ -85,6 +85,7 @@ type custodianHarness struct { t *testing.T c *tapgarden.Custodian cfg *tapgarden.CustodianConfig + errChan chan error chainBridge *tapgarden.MockChainBridge walletAnchor *tapgarden.MockWalletAnchor keyRing *tapgarden.MockKeyRing @@ -103,11 +104,27 @@ func (h *custodianHarness) assertStartup() { ) require.NoError(h.t, err) + // Make sure we don't have an error on startup. + select { + case err := <-h.errChan: + require.NoError(h.t, err) + + case <-time.After(testPollInterval): + } + // Make sure ListTransactions is called on startup. _, err = fn.RecvOrTimeout( h.walletAnchor.ListTxnsSignal, testTimeout, ) require.NoError(h.t, err) + + // Make sure we don't have an error on startup. + select { + case err := <-h.errChan: + require.NoError(h.t, err) + + case <-time.After(testPollInterval): + } } // eventually is a shortcut for require.Eventually with the timeout and poll @@ -197,6 +214,7 @@ func newHarness(t *testing.T, require.NoError(t, err) } + errChan := make(chan error, 1) cfg := &tapgarden.CustodianConfig{ ChainParams: chainParams, ChainBridge: chainBridge, @@ -206,12 +224,13 @@ func newHarness(t *testing.T, ProofNotifier: assetDB, ProofCourierDispatcher: courierDispatch, ProofWatcher: proofWatcher, - ErrChan: make(chan error, 1), + ErrChan: errChan, } return &custodianHarness{ t: t, c: tapgarden.NewCustodian(cfg), cfg: cfg, + errChan: errChan, chainBridge: chainBridge, walletAnchor: walletAnchor, keyRing: keyRing, From dbb80f6e71ecd810721e3eda2600d1e40730bd9e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:08 +0100 Subject: [PATCH 16/19] tapfreighter: fix wrong proof outpoint being used This fixes a couple of instances where the porter used the wrong outpoint for proof locators when creating new proofs for a send package. This was previously not noticed because the outpoint in the locator was ignored by both the file based and database archive. With the outpoint now being mandatory, this lead to failures in the integration tests. --- tapfreighter/chain_porter.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tapfreighter/chain_porter.go b/tapfreighter/chain_porter.go index 710160108..f0bde0ee6 100644 --- a/tapfreighter/chain_porter.go +++ b/tapfreighter/chain_porter.go @@ -458,7 +458,7 @@ func (p *ChainPorter) storeProofs(sendPkg *sendPackage) error { outputProofLocator := proof.Locator{ AssetID: &firstInput.ID, ScriptKey: *out.ScriptKey.PubKey, - OutPoint: &firstInput.OutPoint, + OutPoint: fn.Ptr(proofSuffix.OutPoint()), } outputProof := &proof.AnnotatedProof{ Locator: outputProofLocator, @@ -536,7 +536,7 @@ func (p *ChainPorter) fetchInputProof(ctx context.Context, // updateAssetProofFile retrieves and updates the proof file for the given asset // ID and script key with the new proof. func (p *ChainPorter) updateAssetProofFile(ctx context.Context, assetID asset.ID, - scriptKeyPub *btcec.PublicKey, outPoint *wire.OutPoint, + scriptKeyPub *btcec.PublicKey, oldOutPoint *wire.OutPoint, confEvent *chainntnfs.TxConfirmation, newProof *proof.Proof) (*proof.AnnotatedProof, *proof.Proof, error) { @@ -544,11 +544,12 @@ func (p *ChainPorter) updateAssetProofFile(ctx context.Context, assetID asset.ID locator := proof.Locator{ AssetID: &assetID, ScriptKey: *scriptKeyPub, - OutPoint: outPoint, + OutPoint: oldOutPoint, } currentProofFileBlob, err := p.cfg.AssetProofs.FetchProof(ctx, locator) if err != nil { - return nil, nil, fmt.Errorf("error fetching proof: %w", err) + return nil, nil, fmt.Errorf("error fetching current proof: %w", + err) } currentProofFile := proof.NewEmptyFile(proof.V0) err = currentProofFile.Decode(bytes.NewReader(currentProofFileBlob)) @@ -585,7 +586,7 @@ func (p *ChainPorter) updateAssetProofFile(ctx context.Context, assetID asset.ID Locator: proof.Locator{ AssetID: &assetID, ScriptKey: *newProof.Asset.ScriptKey.PubKey, - OutPoint: outPoint, + OutPoint: fn.Ptr(newProof.OutPoint()), }, Blob: newProofFileBuffer.Bytes(), } @@ -734,7 +735,7 @@ func (p *ChainPorter) transferReceiverProof(pkg *sendPackage) error { proofLocator := proof.Locator{ AssetID: &passiveAsset.GenesisID, ScriptKey: *passiveAsset.ScriptKey.PubKey, - OutPoint: &passiveAsset.PrevAnchorPoint, + OutPoint: fn.Ptr(passiveAsset.NewProof.OutPoint()), } proofFileBlob, err := p.cfg.AssetProofs.FetchProof( ctx, proofLocator, From 171535dfac72597bf95435f9919014e9dfd7033c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 13:19:09 +0100 Subject: [PATCH 17/19] itest: always specify outpoint in sendProof --- itest/addrs_test.go | 21 ++++++++++++++++++++- itest/psbt_test.go | 18 +++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index b03ddfbc9..6fa71950b 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -5,6 +5,7 @@ import ( "context" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/wire" tap "github.com/lightninglabs/taproot-assets" "github.com/lightninglabs/taproot-assets/fn" "github.com/lightninglabs/taproot-assets/internal/test" @@ -515,16 +516,34 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice, // sendProof manually exports a proof from the given source node and imports it // using the development only ImportProof RPC on the destination node. -func sendProof(t *harnessTest, src, dst *tapdHarness, scriptKey []byte, +func sendProof(t *harnessTest, src, dst *tapdHarness, + sendResp *taprpc.SendAssetResponse, scriptKey []byte, genInfo *taprpc.GenesisInfo) *tapdevrpc.ImportProofResponse { ctxb := context.Background() + // We need to find the outpoint of the asset we sent to the address. + var outpoint *taprpc.OutPoint + for _, out := range sendResp.Transfer.Outputs { + if bytes.Equal(out.ScriptKey, scriptKey) { + wireOutPoint, err := wire.NewOutPointFromString( + out.Anchor.Outpoint, + ) + require.NoError(t.t, err) + + outpoint = &taprpc.OutPoint{ + Txid: wireOutPoint.Hash[:], + OutputIndex: wireOutPoint.Index, + } + } + } + var proofResp *taprpc.ProofFile waitErr := wait.NoError(func() error { resp, err := src.ExportProof(ctxb, &taprpc.ExportProofRequest{ AssetId: genInfo.AssetId, ScriptKey: scriptKey, + Outpoint: outpoint, }) if err != nil { return err diff --git a/itest/psbt_test.go b/itest/psbt_test.go index 0b0639ce7..0858c9101 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -132,7 +132,7 @@ func testPsbtScriptHashLockSend(t *harnessTest) { // This is an interactive/PSBT based transfer, so we do need to manually // send the proof from the sender to the receiver because the proof // courier address gets lost in the address->PSBT conversion. - _ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo) + _ = sendProof(t, bob, alice, sendResp, aliceAddr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, alice, 1) aliceAssets, err := alice.ListAssets(ctxb, &taprpc.ListAssetRequest{ @@ -258,7 +258,7 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { // This is an interactive/PSBT based transfer, so we do need to manually // send the proof from the sender to the receiver because the proof // courier address gets lost in the address->PSBT conversion. - _ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo) + _ = sendProof(t, bob, alice, sendResp, aliceAddr.ScriptKey, genInfo) AssertNonInteractiveRecvComplete(t.t, alice, 1) aliceAssets, err := alice.ListAssets(ctxb, &taprpc.ListAssetRequest{ @@ -434,7 +434,7 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, // This is an interactive transfer, so we do need to manually // send the proof from the sender to the receiver. _ = sendProof( - t, sender, receiver, + t, sender, receiver, sendResp, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, ) @@ -647,7 +647,7 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, // This is an interactive transfer, so we do need to manually // send the proof from the sender to the receiver. _ = sendProof( - t, sender, receiver, + t, sender, receiver, sendResp, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, ) @@ -769,7 +769,7 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { // This is an interactive transfer, so we do need to manually send the // proof from the sender to the receiver. _ = sendProof( - t, alice, bob, + t, alice, bob, sendResp, receiverScriptKey.PubKey.SerializeCompressed(), genInfo, ) @@ -916,11 +916,11 @@ func testPsbtMultiSend(t *harnessTest) { // This is an interactive transfer, so we do need to manually send the // proof from the sender to the receiver. _ = sendProof( - t, sender, receiver, + t, sender, receiver, sendResp, receiverScriptKey1.PubKey.SerializeCompressed(), genInfo, ) _ = sendProof( - t, sender, receiver, + t, sender, receiver, sendResp, receiverScriptKey2.PubKey.SerializeCompressed(), genInfo, ) @@ -1158,7 +1158,7 @@ func testMultiInputPsbtSingleAssetID(t *harnessTest) { // This is an interactive transfer. Therefore, we will manually transfer // the proof from the sender to the receiver. _ = sendProof( - t, secondaryTapd, primaryTapd, + t, secondaryTapd, primaryTapd, sendResp, primaryNodeScriptKey.PubKey.SerializeCompressed(), genInfo, ) @@ -1233,7 +1233,7 @@ func testMultiInputPsbtSingleAssetID(t *harnessTest) { // This is an interactive transfer. Therefore, we will manually transfer // the proof from the sender to the receiver. _ = sendProof( - t, secondaryTapd, primaryTapd, + t, secondaryTapd, primaryTapd, sendResp, primaryNodeScriptKey.PubKey.SerializeCompressed(), genInfo, ) From e532f2c699bf67b0be9fbc279745f08452c484a2 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 2 Feb 2024 15:31:54 +0100 Subject: [PATCH 18/19] tapgarden: fix proof not found bug This fixes a bug reported by a user running v0.3.3-rc1. Although the situation can only happen if the daemon is shut down in exactly the wrong moment (or, more likely, due to an otherwise inconsistent database state), it can happen that the multiverse reports a proof is available but it wasn't yet imported into the local archive. To make sure we can definitely rely on the proof being in the asset DB when trying to complete a receive event, we double check and re-import the proof if necessary. --- tapgarden/custodian.go | 75 +++++++++++------ tapgarden/custodian_test.go | 155 ++++++++++++++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 29 deletions(-) diff --git a/tapgarden/custodian.go b/tapgarden/custodian.go index 0b87d24a6..4daea3a87 100644 --- a/tapgarden/custodian.go +++ b/tapgarden/custodian.go @@ -647,12 +647,13 @@ func (c *Custodian) checkProofAvailable(event *address.Event) (bool, error) { // be a multi archiver that includes file based storage) to make sure // the proof is available in the relational database. If the proof is // not in the DB, we can't update the event. - blob, err := c.cfg.ProofNotifier.FetchProof(ctxt, proof.Locator{ + locator := proof.Locator{ AssetID: fn.Ptr(event.Addr.AssetID), GroupKey: event.Addr.GroupKey, ScriptKey: event.Addr.ScriptKey, OutPoint: &event.Outpoint, - }) + } + blob, err := c.cfg.ProofNotifier.FetchProof(ctxt, locator) switch { case errors.Is(err, proof.ErrProofNotFound): return false, nil @@ -671,6 +672,19 @@ func (c *Custodian) checkProofAvailable(event *address.Event) (bool, error) { "but got something else") } + // In case we missed a notification from the local universe and didn't + // previously import the proof (for example because we were shutting + // down), we could be in a situation where the local database doesn't + // have the proof yet. So we make sure to import it now. + err = c.assertProofInLocalArchive(&proof.AnnotatedProof{ + Locator: locator, + Blob: blob, + }) + if err != nil { + return false, fmt.Errorf("error asserting proof in local "+ + "archive: %w", err) + } + file, err := blob.AsFile() if err != nil { return false, fmt.Errorf("error extracting proof file: %w", err) @@ -755,29 +769,13 @@ func (c *Custodian) mapProofToEvent(p proof.Blob) error { // local universe instead of the local proof archive (which the // couriers use). This is mainly an optimization to make sure we // don't unnecessarily overwrite the proofs in our main archive. - haveProof, err := c.cfg.ProofArchive.HasProof(ctxt, loc) + err := c.assertProofInLocalArchive(&proof.AnnotatedProof{ + Locator: loc, + Blob: proofBlob, + }) if err != nil { - return fmt.Errorf("error checking if proof is "+ - "available: %w", err) - } - - // We don't have the proof yet, or not in all backends, so we - // need to import it now. - if !haveProof { - headerVerifier := GenHeaderVerifier( - ctxt, c.cfg.ChainBridge, - ) - err = c.cfg.ProofArchive.ImportProofs( - ctxt, headerVerifier, c.cfg.GroupVerifier, - false, &proof.AnnotatedProof{ - Locator: loc, - Blob: proofBlob, - }, - ) - if err != nil { - return fmt.Errorf("error importing proof "+ - "file into main archive: %w", err) - } + return fmt.Errorf("error asserting proof in local "+ + "archive: %w", err) } } @@ -828,6 +826,35 @@ func (c *Custodian) mapProofToEvent(p proof.Blob) error { return nil } +// assertProofInLocalArchive checks if the proof is already in the local proof +// archive. If it isn't, it is imported now. +func (c *Custodian) assertProofInLocalArchive(p *proof.AnnotatedProof) error { + ctxt, cancel := c.WithCtxQuit() + defer cancel() + + haveProof, err := c.cfg.ProofArchive.HasProof(ctxt, p.Locator) + if err != nil { + return fmt.Errorf("error checking if proof is available: %w", + err) + } + + // We don't have the proof yet, or not in all backends, so we + // need to import it now. + if !haveProof { + headerVerifier := GenHeaderVerifier(ctxt, c.cfg.ChainBridge) + err = c.cfg.ProofArchive.ImportProofs( + ctxt, headerVerifier, c.cfg.GroupVerifier, false, p, + ) + if err != nil { + log.Errorf("ERROOOORRR: %v", err) + return fmt.Errorf("error importing proof file into "+ + "main archive: %w", err) + } + } + + return nil +} + // setReceiveCompleted updates the address event in the database to mark it as // completed successfully and to link it to the proof we received. func (c *Custodian) setReceiveCompleted(event *address.Event, diff --git a/tapgarden/custodian_test.go b/tapgarden/custodian_test.go index 82c2a4e4e..590ee7d25 100644 --- a/tapgarden/custodian_test.go +++ b/tapgarden/custodian_test.go @@ -5,6 +5,7 @@ import ( "context" "database/sql" "fmt" + "io" "math/rand" "net/url" "testing" @@ -23,6 +24,7 @@ import ( "github.com/lightninglabs/taproot-assets/tapdb" "github.com/lightninglabs/taproot-assets/tapgarden" "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/lightninglabs/taproot-assets/universe" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest/wait" @@ -59,9 +61,46 @@ func newAddrBookForDB(db *tapdb.BaseDB, keyRing *tapgarden.MockKeyRing, return book, tapdbBook } +type mockVerifier struct { + t *testing.T +} + +func newMockVerifier(t *testing.T) *mockVerifier { + return &mockVerifier{ + t: t, + } +} + +func (m *mockVerifier) Verify(_ context.Context, r io.Reader, + headerVerifier proof.HeaderVerifier, + groupVerifier proof.GroupVerifier) (*proof.AssetSnapshot, error) { + + f := &proof.File{} + err := f.Decode(r) + require.NoError(m.t, err) + + lastProof, err := f.LastProof() + require.NoError(m.t, err) + + ac, err := commitment.NewAssetCommitment(&lastProof.Asset) + require.NoError(m.t, err) + tc, err := commitment.NewTapCommitment(ac) + require.NoError(m.t, err) + + return &proof.AssetSnapshot{ + Asset: &lastProof.Asset, + OutPoint: lastProof.OutPoint(), + OutputIndex: lastProof.InclusionProof.OutputIndex, + AnchorBlockHash: lastProof.BlockHeader.BlockHash(), + AnchorTx: &lastProof.AnchorTx, + InternalKey: lastProof.InclusionProof.InternalKey, + ScriptRoot: tc, + }, nil +} + // newProofArchive creates a new instance of the MultiArchiver. func newProofArchiveForDB(t *testing.T, db *tapdb.BaseDB) (*proof.MultiArchiver, - *tapdb.AssetStore) { + *tapdb.AssetStore, *tapdb.MultiverseStore) { txCreator := func(tx *sql.Tx) tapdb.ActiveAssetsStore { return db.WithTx(tx) @@ -78,7 +117,14 @@ func newProofArchiveForDB(t *testing.T, db *tapdb.BaseDB) (*proof.MultiArchiver, assetStore, ) - return proofArchive, assetStore + multiverseDB := tapdb.NewTransactionExecutor( + db, func(tx *sql.Tx) tapdb.BaseMultiverseStore { + return db.WithTx(tx) + }, + ) + multiverse := tapdb.NewMultiverseStore(multiverseDB) + + return proofArchive, assetStore, multiverse } type custodianHarness struct { @@ -93,6 +139,7 @@ type custodianHarness struct { addrBook *address.Book syncer *tapgarden.MockAssetSyncer assetDB *tapdb.AssetStore + multiverse *tapdb.MultiverseStore courier *proof.MockProofCourier } @@ -192,6 +239,48 @@ func (h *custodianHarness) assertAddrsRegistered( } } +// addProofFileToMultiverse adds the given proof to the multiverse store. +func (h *custodianHarness) addProofFileToMultiverse(p *proof.AnnotatedProof) { + f := &proof.File{} + err := f.Decode(bytes.NewReader(p.Blob)) + require.NoError(h.t, err) + + ctx := context.Background() + ctxt, cancel := context.WithTimeout(ctx, testTimeout) + defer cancel() + + for i := uint32(0); i < uint32(f.NumProofs()); i++ { + transition, err := f.ProofAt(i) + require.NoError(h.t, err) + + rawTransition, err := f.RawProofAt(i) + require.NoError(h.t, err) + + id := universe.NewUniIDFromAsset(transition.Asset) + key := universe.LeafKey{ + OutPoint: transition.OutPoint(), + ScriptKey: fn.Ptr(asset.NewScriptKey( + transition.Asset.ScriptKey.PubKey, + )), + } + leaf := &universe.Leaf{ + GenesisWithGroup: universe.GenesisWithGroup{ + Genesis: transition.Asset.Genesis, + GroupKey: transition.Asset.GroupKey, + }, + RawProof: rawTransition, + Asset: &transition.Asset, + Amt: transition.Asset.Amount, + } + h.t.Logf("Importing proof with script key %x and outpoint %v "+ + "into multiverse", + key.ScriptKey.PubKey.SerializeCompressed(), + key.OutPoint) + _, err = h.multiverse.UpsertProofLeaf(ctxt, id, key, leaf, nil) + require.NoError(h.t, err) + } +} + func newHarness(t *testing.T, initialAddrs []*address.AddrWithKeyInfo) *custodianHarness { @@ -201,7 +290,10 @@ func newHarness(t *testing.T, syncer := tapgarden.NewMockAssetSyncer() db := tapdb.NewTestDB(t) addrBook, tapdbBook := newAddrBookForDB(db.BaseDB, keyRing, syncer) - _, assetDB := newProofArchiveForDB(t, db.BaseDB) + + _, assetDB, multiverse := newProofArchiveForDB(t, db.BaseDB) + notifier := proof.NewMultiArchiveNotifier(assetDB, multiverse) + courier := proof.NewMockProofCourier() courierDispatch := &proof.MockProofCourierDispatcher{ Courier: courier, @@ -214,14 +306,18 @@ func newHarness(t *testing.T, require.NoError(t, err) } + archive := proof.NewMultiArchiver( + newMockVerifier(t), testTimeout, assetDB, + ) + errChan := make(chan error, 1) cfg := &tapgarden.CustodianConfig{ ChainParams: chainParams, ChainBridge: chainBridge, WalletAnchor: walletAnchor, AddrBook: addrBook, - ProofArchive: assetDB, - ProofNotifier: assetDB, + ProofArchive: archive, + ProofNotifier: notifier, ProofCourierDispatcher: courierDispatch, ProofWatcher: proofWatcher, ErrChan: errChan, @@ -238,6 +334,7 @@ func newHarness(t *testing.T, addrBook: addrBook, syncer: syncer, assetDB: assetDB, + multiverse: multiverse, courier: courier, } } @@ -315,6 +412,11 @@ func randProof(t *testing.T, outputIndex int, tx *wire.MsgTx, Genesis: *genesis, Amount: addr.Amount, ScriptKey: asset.NewScriptKey(&addr.ScriptKey), + PrevWitnesses: []asset.Witness{ + { + PrevID: &asset.PrevID{}, + }, + }, } if addr.GroupKey != nil { a.GroupKey = &asset.GroupKey{ @@ -653,6 +755,49 @@ func mustMakeAddr(t *testing.T, return addr } +// TestProofInMultiverseOnly tests that the custodian imports a proof correctly +// into the local archive if it's only present in the multiverse. +func TestProofInMultiverseOnly(t *testing.T) { + h := newHarness(t, nil) + + // Before we start the custodian, we create a random address and a + // corresponding wallet transaction. + ctx := context.Background() + + addr, genesis := randAddr(h) + err := h.tapdbBook.InsertAddrs(ctx, *addr) + require.NoError(t, err) + + // We now start the custodian and make sure it's started up correctly + // and the pending event is registered. + require.NoError(t, h.c.Start()) + h.assertStartup() + h.assertAddrsRegistered(addr) + + // Receiving a TX for it should create a pending event and cause the + // proof courier to attempt to fetch it. But the courier won't find it. + outputIdx, tx := randWalletTx(addr) + h.walletAnchor.SubscribeTx <- *tx + h.assertEventsPresent(1, address.StatusTransactionDetected) + + // We now stop the custodian again. + require.NoError(t, h.c.Stop()) + + // The proof is only in the multiverse, not in the local archive. And we + // add the proof to the multiverse before starting the custodian, so the + // notification for it doesn't trigger. + mockProof := randProof(t, outputIdx, tx.Tx, genesis, addr) + h.addProofFileToMultiverse(mockProof) + + // And a new start should import the proof into the local archive. + h.c = tapgarden.NewCustodian(h.cfg) + require.NoError(t, h.c.Start()) + t.Cleanup(func() { + require.NoError(t, h.c.Stop()) + }) + h.assertStartup() +} + // TestAddrMatchesAsset tests that the AddrMatchesAsset function works // correctly. func TestAddrMatchesAsset(t *testing.T) { From ca77ce5ca30cf341c10beebd97f828987f42a59d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 5 Feb 2024 16:53:38 -0800 Subject: [PATCH 19/19] tapgarden: remove stray log --- tapgarden/custodian.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tapgarden/custodian.go b/tapgarden/custodian.go index 4daea3a87..6f0e9d648 100644 --- a/tapgarden/custodian.go +++ b/tapgarden/custodian.go @@ -846,7 +846,6 @@ func (c *Custodian) assertProofInLocalArchive(p *proof.AnnotatedProof) error { ctxt, headerVerifier, c.cfg.GroupVerifier, false, p, ) if err != nil { - log.Errorf("ERROOOORRR: %v", err) return fmt.Errorf("error importing proof file into "+ "main archive: %w", err) }