From 9d92cdb85f090932c6cf062f7c05fe72deb735d0 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Tue, 20 Dec 2022 15:00:18 -0500 Subject: [PATCH 01/56] Rename expirationSequence -> expiration in JS (#2782) * Rename expirationSequence in JS -> expiration * Fix build errors --- ironfish-cli/src/commands/accounts/pay.ts | 8 ++++---- ironfish-cli/src/commands/accounts/repair.ts | 8 ++++---- .../src/commands/accounts/transactions.ts | 4 ++-- ironfish/src/consensus/verifier.ts | 6 +++--- ironfish/src/fileStores/config.ts | 6 +++--- ironfish/src/memPool/memPool.ts | 13 +++++-------- ironfish/src/mining/manager.ts | 2 +- .../src/primitives/rawTransaction.test.ts | 6 +++--- ironfish/src/primitives/rawTransaction.ts | 18 +++++++++--------- ironfish/src/primitives/transaction.ts | 12 ++++++++---- .../src/rpc/routes/chain/getTransaction.ts | 10 +++++----- .../transactions/sendTransaction.test.ts | 6 +++--- .../routes/transactions/sendTransaction.ts | 13 ++++++------- .../src/rpc/routes/wallet/getTransactions.ts | 12 ++++++------ ironfish/src/rpc/routes/wallet/types.ts | 4 ++-- ironfish/src/wallet/account.test.ts | 8 ++++---- ironfish/src/wallet/account.ts | 4 ++-- ironfish/src/wallet/wallet.test.slow.ts | 16 ++++++++-------- ironfish/src/wallet/wallet.ts | 19 +++++++++---------- ironfish/src/wallet/walletdb/walletdb.ts | 19 ++++++++----------- ironfish/src/workerPool/pool.ts | 4 ++-- .../src/workerPool/tasks/createTransaction.ts | 18 +++++++++--------- .../workerPool/tasks/postTransaction.test.ts | 2 +- 23 files changed, 107 insertions(+), 111 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/pay.ts b/ironfish-cli/src/commands/accounts/pay.ts index f2a184904b..15354493ba 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/accounts/pay.ts @@ -42,7 +42,7 @@ export class Pay extends IronfishCommand { default: false, description: 'Confirm without asking', }), - expirationSequence: Flags.integer({ + expiration: Flags.integer({ char: 'e', description: 'The block sequence after which the transaction will be removed from the mempool. Set to 0 for no expiration.', @@ -61,7 +61,7 @@ export class Pay extends IronfishCommand { let fee = null let to = flags.to?.trim() let from = flags.account?.trim() - const expirationSequence = flags.expirationSequence + const expiration = flags.expiration const memo = flags.memo || '' const client = await this.sdk.connectRpc(false, true) @@ -171,7 +171,7 @@ export class Pay extends IronfishCommand { this.error(`The minimum fee is ${CurrencyUtils.renderOre(1n, true)}`) } - if (expirationSequence !== undefined && expirationSequence < 0) { + if (expiration !== undefined && expiration < 0) { this.log('Expiration sequence must be non-negative') this.exit(1) } @@ -230,7 +230,7 @@ ${CurrencyUtils.renderIron(amount, true)} plus a transaction fee of ${CurrencyUt }, ], fee: CurrencyUtils.encode(fee), - expirationSequence, + expiration: expiration, }) stopProgressBar() diff --git a/ironfish-cli/src/commands/accounts/repair.ts b/ironfish-cli/src/commands/accounts/repair.ts index 90c951a088..420dfaa960 100644 --- a/ironfish-cli/src/commands/accounts/repair.ts +++ b/ironfish-cli/src/commands/accounts/repair.ts @@ -81,16 +81,16 @@ export default class Repair extends IronfishCommand { let unexpiredTransactions = 0 for await (const transactionValue of account.getTransactions()) { - const expirationSequence = transactionValue.transaction.expirationSequence() + const expiration = transactionValue.transaction.expiration() const transactionHash = transactionValue.transaction.hash() const isExpired = !transactionValue.sequence && - chain.verifier.isExpiredSequence(expirationSequence, chain.head.sequence) + chain.verifier.isExpiredSequence(expiration, chain.head.sequence) const pendingTransactionHash = await walletDb.pendingTransactionHashes.get([ account.prefix, - [expirationSequence, transactionHash], + [expiration, transactionHash], ]) if (isExpired && !pendingTransactionHash) { @@ -145,7 +145,7 @@ export default class Repair extends IronfishCommand { const isExpired = !transactionValue.sequence && chain.verifier.isExpiredSequence( - transactionValue.transaction.expirationSequence(), + transactionValue.transaction.expiration(), chain.head.sequence, ) diff --git a/ironfish-cli/src/commands/accounts/transactions.ts b/ironfish-cli/src/commands/accounts/transactions.ts index 4e3d734441..1a486a41a2 100644 --- a/ironfish-cli/src/commands/accounts/transactions.ts +++ b/ironfish-cli/src/commands/accounts/transactions.ts @@ -75,8 +75,8 @@ export class TransactionsCommand extends IronfishCommand { header: 'Spends', minWidth: 5, }, - expirationSequence: { - header: 'Expiration Sequence', + expiration: { + header: 'Expiration', }, }, { diff --git a/ironfish/src/consensus/verifier.ts b/ironfish/src/consensus/verifier.ts index e3c3c4ce79..d7be1ad785 100644 --- a/ironfish/src/consensus/verifier.ts +++ b/ironfish/src/consensus/verifier.ts @@ -65,7 +65,7 @@ export class Verifier { let transactionBatch = [] let runningNotesCount = 0 for (const [idx, tx] of block.transactions.entries()) { - if (this.isExpiredSequence(tx.expirationSequence(), block.header.sequence)) { + if (this.isExpiredSequence(tx.expiration(), block.header.sequence)) { return { valid: false, reason: VerificationResultReason.TRANSACTION_EXPIRED, @@ -289,8 +289,8 @@ export class Verifier { return validity } - isExpiredSequence(expirationSequence: number, sequence: number): boolean { - return expirationSequence !== 0 && expirationSequence <= sequence + isExpiredSequence(expiration: number, sequence: number): boolean { + return expiration !== 0 && expiration <= sequence } /** diff --git a/ironfish/src/fileStores/config.ts b/ironfish/src/fileStores/config.ts index 537b599611..4a7a249964 100644 --- a/ironfish/src/fileStores/config.ts +++ b/ironfish/src/fileStores/config.ts @@ -110,7 +110,7 @@ export type ConfigOptions = { * The default delta of block sequence for which to expire transactions from the * mempool. */ - defaultTransactionExpirationSequenceDelta: number + transactionExpirationDelta: number /** * The default number of blocks to request per message when syncing. @@ -277,7 +277,7 @@ export const ConfigOptionsSchema: yup.ObjectSchema> = yup targetPeers: yup.number().integer().min(1), telemetryApi: yup.string(), generateNewIdentity: yup.boolean(), - defaultTransactionExpirationSequenceDelta: YupUtils.isPositiveInteger, + transactionExpirationDelta: YupUtils.isPositiveInteger, blocksPerMessage: YupUtils.isPositiveInteger, minerBatchSize: YupUtils.isPositiveInteger, minimumBlockConfirmations: YupUtils.isPositiveInteger, @@ -328,7 +328,7 @@ export class Config extends KeyStore { return { bootstrapNodes: [], databaseMigrate: false, - defaultTransactionExpirationSequenceDelta: 15, + transactionExpirationDelta: 15, editor: '', enableListenP2P: true, enableLogFile: false, diff --git a/ironfish/src/memPool/memPool.ts b/ironfish/src/memPool/memPool.ts index e1718db0f3..eed004e154 100644 --- a/ironfish/src/memPool/memPool.ts +++ b/ironfish/src/memPool/memPool.ts @@ -19,7 +19,7 @@ interface MempoolEntry { } interface ExpirationMempoolEntry { - expirationSequence: number + expiration: number hash: TransactionHash } @@ -62,7 +62,7 @@ export class MemPool { ) this.expirationQueue = new PriorityQueue( - (t1, t2) => t1.expirationSequence < t2.expirationSequence, + (t1, t2) => t1.expiration < t2.expiration, (t) => t.hash.toString('hex'), ) @@ -131,7 +131,7 @@ export class MemPool { */ acceptTransaction(transaction: Transaction): boolean { const hash = transaction.hash().toString('hex') - const sequence = transaction.expirationSequence() + const sequence = transaction.expiration() if (this.exists(transaction.hash())) { return false } @@ -183,10 +183,7 @@ export class MemPool { let nextExpired = this.expirationQueue.peek() while ( nextExpired && - this.chain.verifier.isExpiredSequence( - nextExpired.expirationSequence, - this.chain.head.sequence, - ) + this.chain.verifier.isExpiredSequence(nextExpired.expiration, this.chain.head.sequence) ) { const transaction = this.get(nextExpired.hash) if (!transaction) { @@ -245,7 +242,7 @@ export class MemPool { } this.queue.add({ hash, feeRate: getFeeRate(transaction) }) - this.expirationQueue.add({ expirationSequence: transaction.expirationSequence(), hash }) + this.expirationQueue.add({ expiration: transaction.expiration(), hash }) this.metrics.memPoolSize.value = this.count() return true } diff --git a/ironfish/src/mining/manager.ts b/ironfish/src/mining/manager.ts index f06eaac22f..010a20326f 100644 --- a/ironfish/src/mining/manager.ts +++ b/ironfish/src/mining/manager.ts @@ -82,7 +82,7 @@ export class MiningManager { } const isExpired = this.chain.verifier.isExpiredSequence( - transaction.expirationSequence(), + transaction.expiration(), sequence, ) if (isExpired) { diff --git a/ironfish/src/primitives/rawTransaction.test.ts b/ironfish/src/primitives/rawTransaction.test.ts index 4668f45c3f..824326820d 100644 --- a/ironfish/src/primitives/rawTransaction.test.ts +++ b/ironfish/src/primitives/rawTransaction.test.ts @@ -58,7 +58,7 @@ describe('RawTransaction', () => { const posted = raw.post() expect(posted.takeReference().verify()).toBe(true) expect(posted.fee()).toEqual(5n) - expect(posted.expirationSequence()).toEqual(10) + expect(posted.expiration()).toEqual(10) expect(posted.notes.length).toEqual(3) expect(posted.spends.length).toEqual(1) expect(posted.mints.length).toEqual(1) @@ -112,7 +112,7 @@ describe('RawTransaction', () => { const raw = new RawTransaction() raw.spendingKey = account.spendingKey - raw.expirationSequence = 60 + raw.expiration = 60 raw.fee = 1337n raw.mints = [ @@ -142,7 +142,7 @@ describe('RawTransaction', () => { expect(deserialized).toMatchObject({ spendingKey: raw.spendingKey, - expirationSequence: raw.expirationSequence, + expiration: raw.expiration, fee: raw.fee, }) diff --git a/ironfish/src/primitives/rawTransaction.ts b/ironfish/src/primitives/rawTransaction.ts index 0ed587d621..6bb8056c83 100644 --- a/ironfish/src/primitives/rawTransaction.ts +++ b/ironfish/src/primitives/rawTransaction.ts @@ -19,7 +19,7 @@ const noteHasher = new NoteHasher() export class RawTransaction { spendingKey = '' - expirationSequence: number | null = null + expiration: number | null = null fee = 0n mints: MintDescription[] = [] burns: BurnDescription[] = [] @@ -56,8 +56,8 @@ export class RawTransaction { builder.burn(burn.assetIdentifier, burn.value) } - if (this.expirationSequence !== null) { - builder.setExpirationSequence(this.expirationSequence) + if (this.expiration !== null) { + builder.setExpirationSequence(this.expiration) } const serialized = builder.post(null, this.fee) @@ -111,9 +111,9 @@ export class RawTransactionSerde { bw.writeBigU64(burn.value) } - bw.writeU8(Number(raw.expirationSequence != null)) - if (raw.expirationSequence != null) { - bw.writeU64(raw.expirationSequence) + bw.writeU8(Number(raw.expiration != null)) + if (raw.expiration != null) { + bw.writeU64(raw.expiration) } return bw.render() @@ -167,7 +167,7 @@ export class RawTransactionSerde { const hasExpiration = reader.readU8() if (hasExpiration) { - raw.expirationSequence = reader.readU64() + raw.expiration = reader.readU64() } return raw @@ -210,8 +210,8 @@ export class RawTransactionSerde { } size += 1 // has expiration sequence - if (raw.expirationSequence != null) { - size += 8 // raw.expirationSequence + if (raw.expiration != null) { + size += 8 // raw.expiration } return size diff --git a/ironfish/src/primitives/transaction.ts b/ironfish/src/primitives/transaction.ts index 917e7dc272..8d4424bb8e 100644 --- a/ironfish/src/primitives/transaction.ts +++ b/ironfish/src/primitives/transaction.ts @@ -31,7 +31,7 @@ export class Transaction { private readonly _version: number private readonly _fee: bigint - private readonly _expirationSequence: number + private readonly _expiration: number private readonly _signature: Buffer private _hash?: TransactionHash private _unsignedHash?: TransactionHash @@ -50,7 +50,7 @@ export class Transaction { const _mintsLength = reader.readU64() // 8 const _burnsLength = reader.readU64() // 8 this._fee = BigInt(reader.readI64()) // 8 - this._expirationSequence = reader.readU32() // 4 + this._expiration = reader.readU32() // 4 // randomized public key of sender // to read the value of rpk reader.readBytes(PUBLIC_ADDRESS_LENGTH, true).toString('hex') reader.seek(32) @@ -225,7 +225,11 @@ export class Transaction { return this.transactionPostedSerialized.equals(other.transactionPostedSerialized) } - expirationSequence(): number { - return this._expirationSequence + /** + * @returns The expiration as block sequence of the transaction. + * The transaction cannot be added to a block of equal or greater sequence + */ + expiration(): number { + return this._expiration } } diff --git a/ironfish/src/rpc/routes/chain/getTransaction.ts b/ironfish/src/rpc/routes/chain/getTransaction.ts index dbf4232828..65ac95b06d 100644 --- a/ironfish/src/rpc/routes/chain/getTransaction.ts +++ b/ironfish/src/rpc/routes/chain/getTransaction.ts @@ -10,7 +10,7 @@ export type GetTransactionRequest = { blockHash: string; transactionHash: string export type GetTransactionResponse = { fee: string - expirationSequence: number + expiration: number notesCount: number spendsCount: number signature: string @@ -26,7 +26,7 @@ export const GetTransactionRequestSchema: yup.ObjectSchema = yup .object({ fee: yup.string().defined(), - expirationSequence: yup.number().defined(), + expiration: yup.number().defined(), notesCount: yup.number().defined(), spendsCount: yup.number().defined(), signature: yup.string().defined(), @@ -51,7 +51,7 @@ router.register( // Empty response used for case that transaction not found const rawTransaction: GetTransactionResponse = { fee: '0', - expirationSequence: 0, + expiration: 0, notesCount: 0, spendsCount: 0, signature: '', @@ -60,7 +60,7 @@ router.register( block.transactions.map((transaction) => { if (transaction.hash().toString('hex') === request.data.transactionHash) { const fee = transaction.fee().toString() - const expirationSequence = transaction.expirationSequence() + const expiration = transaction.expiration() const signature = transaction.transactionSignature() const notesEncrypted = [] @@ -69,7 +69,7 @@ router.register( } rawTransaction.fee = fee - rawTransaction.expirationSequence = expirationSequence + rawTransaction.expiration = expiration rawTransaction.notesCount = transaction.notes.length rawTransaction.spendsCount = transaction.spends.length rawTransaction.signature = signature.toString('hex') diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts b/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts index e7ea390156..1b451b6d37 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts @@ -216,14 +216,14 @@ describe('Transactions sendTransaction', () => { expect.anything(), expect.anything(), expect.anything(), - routeTest.node.config.get('defaultTransactionExpirationSequenceDelta'), + routeTest.node.config.get('transactionExpirationDelta'), undefined, ) await routeTest.client.sendTransaction({ ...TEST_PARAMS, - expirationSequence: 1234, - expirationSequenceDelta: 12345, + expiration: 1234, + expirationDelta: 12345, }) expect(paySpy).toHaveBeenCalledWith( diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.ts b/ironfish/src/rpc/routes/transactions/sendTransaction.ts index c3f9085ea1..4a0993f5cf 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.ts +++ b/ironfish/src/rpc/routes/transactions/sendTransaction.ts @@ -16,8 +16,8 @@ export type SendTransactionRequest = { memo: string }[] fee: string - expirationSequence?: number | null - expirationSequenceDelta?: number | null + expiration?: number | null + expirationDelta?: number | null } export type SendTransactionResponse = { @@ -45,8 +45,8 @@ export const SendTransactionRequestSchema: yup.ObjectSchema( account, receives, BigInt(transaction.fee), - transaction.expirationSequenceDelta ?? - node.config.get('defaultTransactionExpirationSequenceDelta'), - transaction.expirationSequence, + transaction.expirationDelta ?? node.config.get('transactionExpirationDelta'), + transaction.expiration, ) request.end({ diff --git a/ironfish/src/rpc/routes/wallet/getTransactions.ts b/ironfish/src/rpc/routes/wallet/getTransactions.ts index 16ac230022..7ae054586f 100644 --- a/ironfish/src/rpc/routes/wallet/getTransactions.ts +++ b/ironfish/src/rpc/routes/wallet/getTransactions.ts @@ -22,7 +22,7 @@ export type GetAccountTransactionsResponse = { fee: string notesCount: number spendsCount: number - expirationSequence: number + expiration: number } export const GetAccountTransactionsRequestSchema: yup.ObjectSchema = @@ -44,7 +44,7 @@ export const GetAccountTransactionsResponseSchema: yup.ObjectSchema { const pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeDefined() @@ -404,7 +404,7 @@ describe('Accounts', () => { const pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeUndefined() @@ -533,7 +533,7 @@ describe('Accounts', () => { let pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeUndefined() @@ -543,7 +543,7 @@ describe('Accounts', () => { pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeDefined() diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index f25a6d5170..0ea8d5d3b7 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -357,7 +357,7 @@ export class Account { await this.walletDb.savePendingTransactionHash( this, - transaction.expirationSequence(), + transaction.expiration(), transaction.hash(), tx, ) @@ -561,7 +561,7 @@ export class Account { await this.walletDb.deletePendingTransactionHash( this, - transaction.expirationSequence(), + transaction.expiration(), transactionHash, tx, ) diff --git a/ironfish/src/wallet/wallet.test.slow.ts b/ironfish/src/wallet/wallet.test.slow.ts index ee8cbd7864..d72b6aa720 100644 --- a/ironfish/src/wallet/wallet.test.slow.ts +++ b/ironfish/src/wallet/wallet.test.slow.ts @@ -129,7 +129,7 @@ describe('Accounts', () => { }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), 0, ) @@ -206,11 +206,11 @@ describe('Accounts', () => { }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), ) - expect(transaction.expirationSequence()).toBe( - node.chain.head.sequence + node.config.get('defaultTransactionExpirationSequenceDelta'), + expect(transaction.expiration()).toBe( + node.chain.head.sequence + node.config.get('transactionExpirationDelta'), ) // Create a block with a miner's fee @@ -297,11 +297,11 @@ describe('Accounts', () => { }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), ) - expect(transaction.expirationSequence()).toBe( - node.chain.head.sequence + node.config.get('defaultTransactionExpirationSequenceDelta'), + expect(transaction.expiration()).toBe( + node.chain.head.sequence + node.config.get('transactionExpirationDelta'), ) // Create a block with a miner's fee @@ -342,7 +342,7 @@ describe('Accounts', () => { }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), 1, ), ).rejects.toThrow(Error) diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index bee556164a..481eff7e7e 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -483,7 +483,7 @@ export class Wallet { if ( !('blockHash' in params) && this.chain.verifier.isExpiredSequence( - transaction.expirationSequence(), + transaction.expiration(), this.chainProcessor.sequence ?? 1, ) ) { @@ -710,18 +710,17 @@ export class Wallet { assetIdentifier: Buffer }[], transactionFee: bigint, - defaultTransactionExpirationSequenceDelta: number, - expirationSequence?: number | null, + transactionExpirationDelta: number, + expiration?: number | null, ): Promise { const heaviestHead = this.chain.head if (heaviestHead === null) { throw new Error('You must have a genesis block to create a transaction') } - expirationSequence = - expirationSequence ?? heaviestHead.sequence + defaultTransactionExpirationSequenceDelta + expiration = expiration ?? heaviestHead.sequence + transactionExpirationDelta - if (this.chain.verifier.isExpiredSequence(expirationSequence, this.chain.head.sequence)) { + if (this.chain.verifier.isExpiredSequence(expiration, this.chain.head.sequence)) { throw new Error('Invalid expiration sequence for transaction') } @@ -731,7 +730,7 @@ export class Wallet { [], [], transactionFee, - expirationSequence, + expiration, ) const transaction = await this.postTransaction(raw) @@ -760,7 +759,7 @@ export class Wallet { mints: MintDescription[], burns: BurnDescription[], fee: bigint, - expirationSequence: number, + expiration: number, ): Promise { const unlock = await this.createTransactionMutex.lock() @@ -773,7 +772,7 @@ export class Wallet { const raw = new RawTransaction() raw.spendingKey = sender.spendingKey - raw.expirationSequence = expirationSequence + raw.expiration = expiration raw.mints = mints raw.burns = burns raw.fee = fee @@ -1116,7 +1115,7 @@ export class Wallet { return isConfirmed ? TransactionStatus.CONFIRMED : TransactionStatus.UNCONFIRMED } else { const isExpired = this.chain.verifier.isExpiredSequence( - transaction.transaction.expirationSequence(), + transaction.transaction.expiration(), headSequence, ) diff --git a/ironfish/src/wallet/walletdb/walletdb.ts b/ironfish/src/wallet/walletdb/walletdb.ts index debc7c3d35..7e4da101d6 100644 --- a/ironfish/src/wallet/walletdb/walletdb.ts +++ b/ironfish/src/wallet/walletdb/walletdb.ts @@ -278,17 +278,17 @@ export class WalletDB { transactionValue: TransactionValue, tx?: IDatabaseTransaction, ): Promise { - const expirationSequence = transactionValue.transaction.expirationSequence() + const expiration = transactionValue.transaction.expiration() await this.db.withTransaction(tx, async (tx) => { if (transactionValue.blockHash) { await this.pendingTransactionHashes.del( - [account.prefix, [expirationSequence, transactionHash]], + [account.prefix, [expiration, transactionHash]], tx, ) } else { await this.pendingTransactionHashes.put( - [account.prefix, [expirationSequence, transactionHash]], + [account.prefix, [expiration, transactionHash]], null, tx, ) @@ -357,7 +357,7 @@ export class WalletDB { return false } - const expirationSequence = transactionValue.transaction.expirationSequence() + const expirationSequence = transactionValue.transaction.expiration() return this.pendingTransactionHashes.has( [account.prefix, [expirationSequence, transactionHash]], tx, @@ -693,12 +693,12 @@ export class WalletDB { async savePendingTransactionHash( account: Account, - expirationSequence: number, + expiration: number, transactionHash: TransactionHash, tx?: IDatabaseTransaction, ): Promise { await this.pendingTransactionHashes.put( - [account.prefix, [expirationSequence, transactionHash]], + [account.prefix, [expiration, transactionHash]], null, tx, ) @@ -706,14 +706,11 @@ export class WalletDB { async deletePendingTransactionHash( account: Account, - expirationSequence: number, + expiration: number, transactionHash: TransactionHash, tx?: IDatabaseTransaction, ): Promise { - await this.pendingTransactionHashes.del( - [account.prefix, [expirationSequence, transactionHash]], - tx, - ) + await this.pendingTransactionHashes.del([account.prefix, [expiration, transactionHash]], tx) } async clearPendingTransactionHashes( diff --git a/ironfish/src/workerPool/pool.ts b/ironfish/src/workerPool/pool.ts index 20ffe8b940..44b9ee5e74 100644 --- a/ironfish/src/workerPool/pool.ts +++ b/ironfish/src/workerPool/pool.ts @@ -163,7 +163,7 @@ export class WorkerPool { mints: MintDescription[], burns: BurnDescription[], transactionFee: bigint, - expirationSequence: number, + expiration: number, ): Promise { const spendsWithSerializedNotes = spends.map((s) => ({ ...s, @@ -172,7 +172,7 @@ export class WorkerPool { const request: CreateTransactionRequest = new CreateTransactionRequest( spendKey, transactionFee, - expirationSequence, + expiration, spendsWithSerializedNotes, receives, mints, diff --git a/ironfish/src/workerPool/tasks/createTransaction.ts b/ironfish/src/workerPool/tasks/createTransaction.ts index 79395e93f3..7e07c5f9bc 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.ts @@ -25,7 +25,7 @@ const noteHasher = new NoteHasher() export class CreateTransactionRequest extends WorkerMessage { readonly spendKey: string readonly transactionFee: bigint - readonly expirationSequence: number + readonly expiration: number readonly spends: { note: Buffer treeSize: number @@ -47,7 +47,7 @@ export class CreateTransactionRequest extends WorkerMessage { constructor( spendKey: string, transactionFee: bigint, - expirationSequence: number, + expiration: number, spends: { note: Buffer treeSize: number @@ -67,7 +67,7 @@ export class CreateTransactionRequest extends WorkerMessage { super(WorkerMessageType.CreateTransaction, jobId) this.spendKey = spendKey this.transactionFee = transactionFee - this.expirationSequence = expirationSequence + this.expiration = expiration this.spends = spends this.receives = receives this.mints = mints @@ -78,7 +78,7 @@ export class CreateTransactionRequest extends WorkerMessage { const bw = bufio.write(this.getSize()) bw.writeVarString(this.spendKey) bw.writeVarBytes(BigIntUtils.toBytesBE(this.transactionFee)) - bw.writeU64(this.expirationSequence) + bw.writeU64(this.expiration) bw.writeU64(this.spends.length) for (const spend of this.spends) { @@ -127,7 +127,7 @@ export class CreateTransactionRequest extends WorkerMessage { const reader = bufio.read(buffer, true) const spendKey = reader.readVarString() const transactionFee = BigIntUtils.fromBytes(reader.readVarBytes()) - const expirationSequence = reader.readU64() + const expiration = reader.readU64() const spendsLength = reader.readU64() const spends = [] @@ -176,7 +176,7 @@ export class CreateTransactionRequest extends WorkerMessage { return new CreateTransactionRequest( spendKey, transactionFee, - expirationSequence, + expiration, spends, receives, mints, @@ -225,7 +225,7 @@ export class CreateTransactionRequest extends WorkerMessage { return ( bufio.sizeVarString(this.spendKey) + bufio.sizeVarBytes(BigIntUtils.toBytesBE(this.transactionFee)) + - 8 + // expirationSequence + 8 + // expiration 8 + // spends length spendsSize + 8 + // receives length @@ -282,10 +282,10 @@ export class CreateTransactionTask extends WorkerTask { receives, mints, burns, - expirationSequence, + expiration, }: CreateTransactionRequest): CreateTransactionResponse { const transaction = new Transaction(spendKey) - transaction.setExpirationSequence(expirationSequence) + transaction.setExpirationSequence(expiration) for (const spend of spends) { const note = Note.deserialize(spend.note) diff --git a/ironfish/src/workerPool/tasks/postTransaction.test.ts b/ironfish/src/workerPool/tasks/postTransaction.test.ts index d8a60c39a9..f9765384de 100644 --- a/ironfish/src/workerPool/tasks/postTransaction.test.ts +++ b/ironfish/src/workerPool/tasks/postTransaction.test.ts @@ -86,6 +86,6 @@ describe('PostTransactionTask', () => { const response = task.execute(request) expect(response.transaction.fee()).toEqual(5n) - expect(response.transaction.expirationSequence()).toEqual(9) + expect(response.transaction.expiration()).toEqual(9) }) }) From e2a1c54235e5a8f8baedfe8fde927bf5dc946e9f Mon Sep 17 00:00:00 2001 From: mat-if <97762857+mat-if@users.noreply.github.com> Date: Tue, 20 Dec 2022 13:21:34 -0700 Subject: [PATCH 02/56] feat(ci): Fetch cargo-tarpaulin binary from github instead of using flaky github action (#2784) --- .github/workflows/rust_ci.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/rust_ci.yml b/.github/workflows/rust_ci.yml index 75530cb61a..b2ca167ced 100644 --- a/.github/workflows/rust_ci.yml +++ b/.github/workflows/rust_ci.yml @@ -31,6 +31,7 @@ jobs: - name: Cache Rust uses: Swatinem/rust-cache@v2 with: + save-if: false shared-key: base - name: Check that cargo lockfile is up to date @@ -74,12 +75,13 @@ jobs: with: shared-key: base - # Build & Run test & Collect Code coverage + # Run tests to collect code coverage - name: Run cargo-tarpaulin on ironfish-rust - uses: actions-rs/tarpaulin@v0.1 - with: - version: "0.22.0" - args: --avoid-cfg-tarpaulin --manifest-path ironfish-rust/Cargo.toml --release -- --test-threads 1 + run: | + wget -O tarpaulin.tar.gz https://github.com/xd009642/tarpaulin/releases/download/0.22.0/cargo-tarpaulin-0.22.0-travis.tar.gz + tar -xzf tarpaulin.tar.gz + mv cargo-tarpaulin ~/.cargo/bin/ + cargo tarpaulin -p ironfish_rust --release --out Xml --avoid-cfg-tarpaulin --skip-clean -- --test-threads 1 # Upload code coverage to Codecov - name: Upload to codecov.io @@ -102,12 +104,13 @@ jobs: with: shared-key: zkp - # Build & Run test & Collect Code coverage + # Run tests to collect code coverage - name: Run cargo-tarpaulin on ironfish-zkp - uses: actions-rs/tarpaulin@v0.1 - with: - version: "0.22.0" - args: --avoid-cfg-tarpaulin --manifest-path ironfish-zkp/Cargo.toml --release -- --test-threads 1 + run: | + wget -O tarpaulin.tar.gz https://github.com/xd009642/tarpaulin/releases/download/0.22.0/cargo-tarpaulin-0.22.0-travis.tar.gz + tar -xzf tarpaulin.tar.gz + mv cargo-tarpaulin ~/.cargo/bin/ + cargo tarpaulin -p ironfish_zkp --release --out Xml --avoid-cfg-tarpaulin --skip-clean -- --test-threads 1 # Upload code coverage to Codecov - name: Upload to codecov.io From 0e7d9af775b0d3a8468ba3798909227a56a7ee9e Mon Sep 17 00:00:00 2001 From: mat-if <97762857+mat-if@users.noreply.github.com> Date: Tue, 20 Dec 2022 15:15:12 -0700 Subject: [PATCH 03/56] fix(napi): Update changes to autogenerated files (#2787) --- ironfish-rust-nodejs/index.d.ts | 6 ------ ironfish-rust-nodejs/index.js | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ironfish-rust-nodejs/index.d.ts b/ironfish-rust-nodejs/index.d.ts index e0bb7f1589..5e92762132 100644 --- a/ironfish-rust-nodejs/index.d.ts +++ b/ironfish-rust-nodejs/index.d.ts @@ -3,12 +3,6 @@ /* auto-generated by NAPI-RS */ -export class ExternalObject { - readonly '': { - readonly '': unique symbol - [K: symbol]: T - } -} export const KEY_LENGTH: number export const NONCE_LENGTH: number export function randomBytes(bytesLength: number): Uint8Array diff --git a/ironfish-rust-nodejs/index.js b/ironfish-rust-nodejs/index.js index 1228b0a7e3..55075bd020 100644 --- a/ironfish-rust-nodejs/index.js +++ b/ironfish-rust-nodejs/index.js @@ -11,7 +11,8 @@ function isMusl() { // For Node 10 if (!process.report || typeof process.report.getReport !== 'function') { try { - return readFileSync('/usr/bin/ldd', 'utf8').includes('musl') + const lddPath = require('child_process').execSync('which ldd').toString().trim(); + return readFileSync(lddPath, 'utf8').includes('musl') } catch (e) { return true } From 0b37da4afbb1bdabbe2090089a7fe03c7813060b Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Tue, 20 Dec 2022 17:56:31 -0500 Subject: [PATCH 04/56] Rename expirationSequence -> expiration in RS (#2785) * Rename expirationSequence -> expiration in RS * Fix lint --- ironfish-rust-nodejs/index.d.ts | 4 +-- .../src/structs/transaction.rs | 9 +++-- ironfish-rust-nodejs/tests/demo.test.slow.ts | 4 +-- ironfish-rust/src/transaction/mod.rs | 34 ++++++++----------- ironfish-rust/src/transaction/tests.rs | 6 ++-- ironfish/src/primitives/rawTransaction.ts | 2 +- ironfish/src/wallet/walletdb/walletdb.ts | 4 +-- .../src/workerPool/tasks/createTransaction.ts | 2 +- 8 files changed, 30 insertions(+), 35 deletions(-) diff --git a/ironfish-rust-nodejs/index.d.ts b/ironfish-rust-nodejs/index.d.ts index 5e92762132..6ea4d1bed3 100644 --- a/ironfish-rust-nodejs/index.d.ts +++ b/ironfish-rust-nodejs/index.d.ts @@ -126,7 +126,7 @@ export class TransactionPosted { fee(): bigint transactionSignature(): Buffer hash(): Buffer - expirationSequence(): number + expiration(): number } export type NativeTransaction = Transaction export class Transaction { @@ -162,7 +162,7 @@ export class Transaction { * aka: self.value_balance - intended_transaction_fee - change = 0 */ post(changeGoesTo: string | undefined | null, intendedTransactionFee: bigint): Buffer - setExpirationSequence(expirationSequence: number): void + setExpiration(sequence: number): void } export class FoundBlockResult { randomness: string diff --git a/ironfish-rust-nodejs/src/structs/transaction.rs b/ironfish-rust-nodejs/src/structs/transaction.rs index 387fb82641..63f26ca611 100644 --- a/ironfish-rust-nodejs/src/structs/transaction.rs +++ b/ironfish-rust-nodejs/src/structs/transaction.rs @@ -147,8 +147,8 @@ impl NativeTransactionPosted { } #[napi] - pub fn expiration_sequence(&self) -> u32 { - self.transaction.expiration_sequence() + pub fn expiration(&self) -> u32 { + self.transaction.expiration() } } @@ -260,9 +260,8 @@ impl NativeTransaction { } #[napi] - pub fn set_expiration_sequence(&mut self, expiration_sequence: u32) -> Undefined { - self.transaction - .set_expiration_sequence(expiration_sequence); + pub fn set_expiration(&mut self, sequence: u32) -> Undefined { + self.transaction.set_expiration(sequence); } } diff --git a/ironfish-rust-nodejs/tests/demo.test.slow.ts b/ironfish-rust-nodejs/tests/demo.test.slow.ts index fd3927ad43..cb3fac9903 100644 --- a/ironfish-rust-nodejs/tests/demo.test.slow.ts +++ b/ironfish-rust-nodejs/tests/demo.test.slow.ts @@ -84,7 +84,7 @@ describe('Demonstrate the Sapling API', () => { const postedMinersFeeTransaction = new TransactionPosted(minersFeeTransaction.post_miners_fee()) const transaction = new Transaction(key.spending_key) - transaction.setExpirationSequence(10) + transaction.setExpiration(10) const encryptedNote = new NoteEncrypted(postedMinersFeeTransaction.getNote(0)) const decryptedNote = Note.deserialize(encryptedNote.decryptNoteForOwner(key.incoming_view_key)!) const newNote = new Note(recipientKey.public_address, BigInt(15), 'receive', Asset.nativeIdentifier(), minersFeeNote.owner()) @@ -112,7 +112,7 @@ describe('Demonstrate the Sapling API', () => { const postedTransaction = new TransactionPosted(transaction.post(key.public_address, BigInt(5))) - expect(postedTransaction.expirationSequence()).toEqual(10) + expect(postedTransaction.expiration()).toEqual(10) expect(postedTransaction.fee()).toEqual(BigInt(5)) expect(postedTransaction.notesLength()).toEqual(1) expect(postedTransaction.spendsLength()).toEqual(1) diff --git a/ironfish-rust/src/transaction/mod.rs b/ironfish-rust/src/transaction/mod.rs index 5779662767..c453a317f0 100644 --- a/ironfish-rust/src/transaction/mod.rs +++ b/ironfish-rust/src/transaction/mod.rs @@ -96,7 +96,7 @@ pub struct ProposedTransaction { /// This is the sequence in the chain the transaction will expire at and be /// removed from the mempool. A value of 0 indicates the transaction will /// not expire. - expiration_sequence: u32, + expiration: u32, /// The key used to sign the transaction and any descriptions that need /// signed. @@ -120,7 +120,7 @@ impl ProposedTransaction { mints: vec![], burns: vec![], value_balances: ValueBalances::new(), - expiration_sequence: 0, + expiration: 0, spender_key, public_key_randomness: jubjub::Fr::random(thread_rng()), } @@ -234,13 +234,13 @@ impl ProposedTransaction { } /// Get the expiration sequence for this transaction - pub fn expiration_sequence(&self) -> u32 { - self.expiration_sequence + pub fn expiration(&self) -> u32 { + self.expiration } /// Set the sequence to expire the transaction from the mempool. - pub fn set_expiration_sequence(&mut self, expiration_sequence: u32) { - self.expiration_sequence = expiration_sequence; + pub fn set_expiration(&mut self, sequence: u32) { + self.expiration = sequence; } // Post transaction without much validation. @@ -318,7 +318,7 @@ impl ProposedTransaction { Ok(Transaction { version: self.version, - expiration_sequence: self.expiration_sequence, + expiration: self.expiration, fee: *self.value_balances.fee(), spends: spend_descriptions, outputs: output_descriptions, @@ -348,9 +348,7 @@ impl ProposedTransaction { hasher.update(TRANSACTION_SIGNATURE_VERSION); hasher.write_u8(self.version).unwrap(); - hasher - .write_u32::(self.expiration_sequence) - .unwrap(); + hasher.write_u32::(self.expiration).unwrap(); hasher .write_i64::(*self.value_balances.fee()) .unwrap(); @@ -486,7 +484,7 @@ pub struct Transaction { /// This is the sequence in the chain the transaction will expire at and be /// removed from the mempool. A value of 0 indicates the transaction will /// not expire. - expiration_sequence: u32, + expiration: u32, /// Randomized public key of the sender of the Transaction /// currently this value is the same for all spends[].owner and outputs[].sender @@ -508,7 +506,7 @@ impl Transaction { let num_mints = reader.read_u64::()?; let num_burns = reader.read_u64::()?; let fee = reader.read_i64::()?; - let expiration_sequence = reader.read_u32::()?; + let expiration = reader.read_u32::()?; let randomized_public_key = redjubjub::PublicKey::read(&mut reader)?; let mut spends = Vec::with_capacity(num_spends as usize); @@ -541,7 +539,7 @@ impl Transaction { mints, burns, binding_signature, - expiration_sequence, + expiration, randomized_public_key, }) } @@ -555,7 +553,7 @@ impl Transaction { writer.write_u64::(self.mints.len() as u64)?; writer.write_u64::(self.burns.len() as u64)?; writer.write_i64::(self.fee)?; - writer.write_u32::(self.expiration_sequence)?; + writer.write_u32::(self.expiration)?; writer.write_all(&self.randomized_public_key.0.to_bytes())?; for spend in self.spends.iter() { @@ -624,8 +622,8 @@ impl Transaction { } /// Get the expiration sequence for this transaction - pub fn expiration_sequence(&self) -> u32 { - self.expiration_sequence + pub fn expiration(&self) -> u32 { + self.expiration } /// Get the expiration sequence for this transaction @@ -643,9 +641,7 @@ impl Transaction { .to_state(); hasher.update(TRANSACTION_SIGNATURE_VERSION); hasher.write_u8(self.version).unwrap(); - hasher - .write_u32::(self.expiration_sequence) - .unwrap(); + hasher.write_u32::(self.expiration).unwrap(); hasher.write_i64::(self.fee).unwrap(); hasher .write_all(&self.randomized_public_key.0.to_bytes()) diff --git a/ironfish-rust/src/transaction/tests.rs b/ironfish-rust/src/transaction/tests.rs index e6a6dd630e..49428d0a2c 100644 --- a/ironfish-rust/src/transaction/tests.rs +++ b/ironfish-rust/src/transaction/tests.rs @@ -121,8 +121,8 @@ fn test_transaction() { read_back_transaction.burns.len() ); assert_eq!( - public_transaction.expiration_sequence, - read_back_transaction.expiration_sequence + public_transaction.expiration, + read_back_transaction.expiration ); let mut serialized_again = vec![]; read_back_transaction @@ -238,7 +238,7 @@ fn test_transaction_signature() { transaction.add_output(out_note); - transaction.set_expiration_sequence(1337); + transaction.set_expiration(1337); let public_transaction = transaction .post(None, 0) diff --git a/ironfish/src/primitives/rawTransaction.ts b/ironfish/src/primitives/rawTransaction.ts index 6bb8056c83..cda251a1a4 100644 --- a/ironfish/src/primitives/rawTransaction.ts +++ b/ironfish/src/primitives/rawTransaction.ts @@ -57,7 +57,7 @@ export class RawTransaction { } if (this.expiration !== null) { - builder.setExpirationSequence(this.expiration) + builder.setExpiration(this.expiration) } const serialized = builder.post(null, this.fee) diff --git a/ironfish/src/wallet/walletdb/walletdb.ts b/ironfish/src/wallet/walletdb/walletdb.ts index 7e4da101d6..a74e25dd34 100644 --- a/ironfish/src/wallet/walletdb/walletdb.ts +++ b/ironfish/src/wallet/walletdb/walletdb.ts @@ -357,9 +357,9 @@ export class WalletDB { return false } - const expirationSequence = transactionValue.transaction.expiration() + const expiration = transactionValue.transaction.expiration() return this.pendingTransactionHashes.has( - [account.prefix, [expirationSequence, transactionHash]], + [account.prefix, [expiration, transactionHash]], tx, ) } diff --git a/ironfish/src/workerPool/tasks/createTransaction.ts b/ironfish/src/workerPool/tasks/createTransaction.ts index 7e07c5f9bc..3d550b7c68 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.ts @@ -285,7 +285,7 @@ export class CreateTransactionTask extends WorkerTask { expiration, }: CreateTransactionRequest): CreateTransactionResponse { const transaction = new Transaction(spendKey) - transaction.setExpirationSequence(expiration) + transaction.setExpiration(expiration) for (const spend of spends) { const note = Note.deserialize(spend.note) From b6f90f1bb70e6df96d14379fd827dca998a23f85 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Tue, 20 Dec 2022 17:59:38 -0500 Subject: [PATCH 05/56] feat(cli,ironfish): Update balance CLI command to include `assetIdentifier` (#2762) * feat(cli,ironfish): Update balance CLI command to include `assetIdentifier` * feat(cli,ironfish): Make assetIdentifier in balance render optional * fix(cli): Revert balance argument * fix(ironfish): Revert renderOre * feat(cli,ironfish): Use assetIdentifier in response --- ironfish-cli/src/commands/accounts/balance.ts | 35 ++++++++++++++----- ironfish/src/rpc/routes/wallet/getBalance.ts | 3 ++ ironfish/src/utils/asset.ts | 8 +++++ ironfish/src/utils/currency.ts | 29 +++++++++++---- 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 ironfish/src/utils/asset.ts diff --git a/ironfish-cli/src/commands/accounts/balance.ts b/ironfish-cli/src/commands/accounts/balance.ts index 9e7d295ba2..a7f9ee135a 100644 --- a/ironfish-cli/src/commands/accounts/balance.ts +++ b/ironfish-cli/src/commands/accounts/balance.ts @@ -27,6 +27,10 @@ export class BalanceCommand extends IronfishCommand { required: false, description: 'Minimum number of blocks confirmations for a note', }), + assetIdentifier: Flags.string({ + required: false, + description: 'Asset identifier to check the balance for', + }), } static args = [ @@ -46,26 +50,42 @@ export class BalanceCommand extends IronfishCommand { const response = await client.getAccountBalance({ account, + assetIdentifier: flags.assetIdentifier, minimumBlockConfirmations: flags.confirmations, }) + const assetIdentifier = response.content.assetIdentifier if (flags.explain) { - this.explainBalance(response.content) + this.explainBalance(response.content, assetIdentifier) return } if (flags.all) { this.log(`Account: ${response.content.account}`) - this.log(`Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true)}`) - this.log(`Unconfirmed: ${CurrencyUtils.renderIron(response.content.unconfirmed, true)}`) + this.log( + `Balance: ${CurrencyUtils.renderIron( + response.content.confirmed, + true, + assetIdentifier, + )}`, + ) + this.log( + `Unconfirmed: ${CurrencyUtils.renderIron( + response.content.unconfirmed, + true, + assetIdentifier, + )}`, + ) return } this.log(`Account: ${response.content.account}`) - this.log(`Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true)}`) + this.log( + `Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetIdentifier)}`, + ) } - explainBalance(response: GetBalanceResponse): void { + explainBalance(response: GetBalanceResponse, assetIdentifier: string): void { const unconfirmed = CurrencyUtils.decode(response.unconfirmed) const confirmed = CurrencyUtils.decode(response.confirmed) @@ -75,15 +95,14 @@ export class BalanceCommand extends IronfishCommand { this.log('') this.log(`Your balance is made of notes on the chain that are safe to spend`) - this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true)}`) + this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true, assetIdentifier)}`) this.log('') this.log( `${response.unconfirmedCount} notes worth ${CurrencyUtils.renderIron( unconfirmedDelta, - true, )} are on the chain within ${response.minimumBlockConfirmations.toString()} blocks of the head`, ) - this.log(`Unconfirmed: ${CurrencyUtils.renderIron(unconfirmed, true)}`) + this.log(`Unconfirmed: ${CurrencyUtils.renderIron(unconfirmed, true, assetIdentifier)}`) } } diff --git a/ironfish/src/rpc/routes/wallet/getBalance.ts b/ironfish/src/rpc/routes/wallet/getBalance.ts index 2d0a819db0..ccf2fc4b4d 100644 --- a/ironfish/src/rpc/routes/wallet/getBalance.ts +++ b/ironfish/src/rpc/routes/wallet/getBalance.ts @@ -14,6 +14,7 @@ export type GetBalanceRequest = { export type GetBalanceResponse = { account: string + assetIdentifier: string confirmed: string unconfirmed: string unconfirmedCount: number @@ -30,6 +31,7 @@ export const GetBalanceRequestSchema: yup.ObjectSchema = yup export const GetBalanceResponseSchema: yup.ObjectSchema = yup .object({ account: yup.string().defined(), + assetIdentifier: yup.string().defined(), unconfirmed: yup.string().defined(), unconfirmedCount: yup.number().defined(), confirmed: yup.string().defined(), @@ -59,6 +61,7 @@ router.register( request.end({ account: account.name, + assetIdentifier: assetIdentifier.toString('hex'), confirmed: balance.confirmed.toString(), unconfirmed: balance.unconfirmed.toString(), unconfirmedCount: balance.unconfirmedCount, diff --git a/ironfish/src/utils/asset.ts b/ironfish/src/utils/asset.ts new file mode 100644 index 0000000000..92e6ff5ea6 --- /dev/null +++ b/ironfish/src/utils/asset.ts @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' + +export function isNativeIdentifier(assetIdentifier: string): boolean { + return Buffer.from(assetIdentifier, 'hex').equals(Asset.nativeIdentifier()) +} diff --git a/ironfish/src/utils/currency.ts b/ironfish/src/utils/currency.ts index 3bb288a525..36d5ea12f5 100644 --- a/ironfish/src/utils/currency.ts +++ b/ironfish/src/utils/currency.ts @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { formatFixed, parseFixed } from '@ethersproject/bignumber' +import { isNativeIdentifier } from './asset' import { FixedNumberUtils } from './fixedNumber' export class CurrencyUtils { @@ -39,15 +40,23 @@ export class CurrencyUtils { /* * Renders ore as iron for human-readable purposes */ - static renderIron(amount: bigint | string, ticker = false): string { + static renderIron( + amount: bigint | string, + includeTicker = false, + assetIdentifier?: string, + ): string { if (typeof amount === 'string') { amount = this.decode(amount) } const iron = FixedNumberUtils.render(amount, 8) - if (ticker) { - return `$IRON ${iron}` + if (includeTicker) { + let ticker = '$IRON' + if (assetIdentifier && !isNativeIdentifier(assetIdentifier)) { + ticker = assetIdentifier + } + return `${ticker} ${iron}` } return iron @@ -56,15 +65,23 @@ export class CurrencyUtils { /* * Renders ore for human-readable purposes */ - static renderOre(amount: bigint | string, ticker = false): string { + static renderOre( + amount: bigint | string, + includeTicker = false, + assetIdentifier?: string, + ): string { if (typeof amount === 'string') { amount = this.decode(amount) } const ore = amount.toString() - if (ticker) { - return `$ORE ${ore}` + if (includeTicker) { + let ticker = '$ORE' + if (assetIdentifier && !isNativeIdentifier(assetIdentifier)) { + ticker = assetIdentifier + } + return `${ticker} ${ore}` } return ore From c88216e877d5f3c1ee1e949c1da08b1bf7883b63 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Tue, 20 Dec 2022 18:15:36 -0500 Subject: [PATCH 06/56] feat(ironfish): Add RPC route for minting asset (#2786) --- ironfish/src/rpc/clients/client.ts | 5 + .../assets/__fixtures__/mint.test.ts.fixture | 16 ++++ ironfish/src/rpc/routes/assets/index.ts | 4 + ironfish/src/rpc/routes/assets/mint.test.ts | 92 +++++++++++++++++++ ironfish/src/rpc/routes/assets/mint.ts | 75 +++++++++++++++ ironfish/src/rpc/routes/index.ts | 1 + ironfish/src/rpc/routes/router.ts | 1 + ironfish/src/wallet/wallet.ts | 31 +++++++ 8 files changed, 225 insertions(+) create mode 100644 ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture create mode 100644 ironfish/src/rpc/routes/assets/index.ts create mode 100644 ironfish/src/rpc/routes/assets/mint.test.ts create mode 100644 ironfish/src/rpc/routes/assets/mint.ts diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index 47fb27edf8..f884f8ccb8 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -60,6 +60,7 @@ import { UseAccountRequest, UseAccountResponse, } from '../routes' +import { MintAssetRequest, MintAssetResponse } from '../routes/assets/mint' import { ExportChainStreamRequest, ExportChainStreamResponse, @@ -327,6 +328,10 @@ export abstract class RpcClient { return this.request(`${ApiNamespace.event}/onGossip`, params) } + async mintAsset(params: MintAssetRequest): Promise> { + return this.request(`${ApiNamespace.asset}/mint`, params).waitForEnd() + } + async sendTransaction( params: SendTransactionRequest, ): Promise> { diff --git a/ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture b/ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture new file mode 100644 index 0000000000..01713fe71e --- /dev/null +++ b/ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture @@ -0,0 +1,16 @@ +{ + "mint with valid parameters returns the asset identifier and transaction hash": [ + { + "id": "da3955e2-b169-4f7d-9325-13d8b25fc99c", + "name": "test", + "spendingKey": "7556c0c0ed420113010787de8824a0919747fe9b1d2b3a4d7da0b85fb25ae99d", + "incomingViewKey": "564bbaaeec2bc7f5a56168dc2a335ad515eb4aaeffce9fdb363698692559f904", + "outgoingViewKey": "554dfd60469e187aca075ba6a1800fa99659e10910b8198d336c29eb859881ed", + "publicAddress": "c49c82e645f54e7e50bb298b61948c8b1a47693bf3db5d1be09e1fbd9a0ffd85" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApGE3L7OfqPUiXP5DkHjuvtUrduHWhs0roo0+0nhhAAuAovfYfn2XAQk7niBMP+OHwKVfja2t8dkPH6UWxYdNunRpWyjZPDycs70DCYxFUQ2LI31t/DE2wr5kclLkvZlf40OeG9Hjth7u2hPdU0o2bnKeXuKKK9HionOBiCpcBj8GI8j1LDJ5ujWayCs28QVgtUKfhfXmTn7wqlPHgUFRs9JmJxA2Lu6CgS8KKJhzd2KZt1j4QQhg8bX0pZRn69bfHq2FLWrQWoSp2UxUvZ8PDltecCBTUk8G+5pDevLILPmg1PeI2j3iKLk8FSREwIdyIC5AdNc3BQ+tSfdzsCnZ4A4+vvYIyy8sHunoo2aK9RfQdTYopkIgjrZJCdLgQ9wI9jVbCN1w9sIsOW7zuel85d95Wx80KLhlCkz4BXu1Xr2IuONQibw8r4H9PjjOP6ICBXH2zVwey9CQ2wA3yPfnTauyNdxS03RFf5jjYIVJlUs4RIxlWt2cw7Dt7f6DBVLwDI8V38v2RKEL3bUGm6eaS3gtQrPB1mnYWqz5jaXgCmxxqn90BDIeGRqtfBx5hzzikd5Om7ADCR6PO2tOC0wLHMSWm8diBrXl9Pf31vzbEbxF+0HDKMkCjXzvjCMZuQZbayVXcVYs0ywPX7jwE8jtZHO+p45x1KNKlQLxAGroFiy7ZmOA94vV2RQ0o1HZzRy0oLBLbd0+8z4vcZpKZ2GTq6xw6fJzVt8IsKRdLTpcmhRhkHP7cVkWNowLKgS+49QXiKJm1a8N2JGBFVZlm9YQW0FKQvjDSotQtYfFSmXhjlKvuMWbHO4pWUzdx4WBVrbK/SZVnJ0Nb78z7Uzze0cxVLdU/K9FtYfGEYLNelp+MA8Rb+KJFlBz6yZiu7Y6jiVkjXcX4uhwqxZfwJHjOZ2r4N0A4GeeTVXnmGeFI9CTL7Sf12c6apD/MVBHSL9UWfSB4Q5gYS4Hky8gE82Hm+QIG9UQEypO8To5xJyC5kX1Tn5QuymLYZSMixpHaTvz210b4J4fvZoP/YVtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAAADfzKVcfTyAtJtNen+p9ZWKwumRz5/bumn8YGn8QM5URFDz0DOEFG8fHQRuckmwsr6nhJy17HnPBTOO6i3r/DuTs5AIkpNoxAaKyymaZzdIjlM/aOhr3Oqb8GiMz2DdwrQN2AQVXInfdBg+rAJASCNmIZ0+Qi1LLH81cfxNMEjveSHkIi/PaRKn5eIFAOKBqTfEAzp06aA79ID4fxEd0QG" + } + ] +} \ No newline at end of file diff --git a/ironfish/src/rpc/routes/assets/index.ts b/ironfish/src/rpc/routes/assets/index.ts new file mode 100644 index 0000000000..b16a573275 --- /dev/null +++ b/ironfish/src/rpc/routes/assets/index.ts @@ -0,0 +1,4 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +export * from './mint' diff --git a/ironfish/src/rpc/routes/assets/mint.test.ts b/ironfish/src/rpc/routes/assets/mint.test.ts new file mode 100644 index 0000000000..b2999ff113 --- /dev/null +++ b/ironfish/src/rpc/routes/assets/mint.test.ts @@ -0,0 +1,92 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' +import { useAccountFixture, useTxFixture } from '../../../testUtilities' +import { createRouteTest } from '../../../testUtilities/routeTest' + +describe('mint', () => { + const routeTest = createRouteTest(true) + + beforeAll(async () => { + await routeTest.node.wallet.createAccount('account', true) + }) + + describe('with no default account', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.mintAsset({ + account: 'fake-account', + fee: '1', + metadata: '{ url: hello }', + name: 'fake-coin', + value: '1', + }), + ).rejects.toThrow('No account found with name fake-account') + }) + }) + + describe('with an invalid fee', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.mintAsset({ + account: 'account', + fee: '0', + metadata: '{ url: hello }', + name: 'fake-coin', + value: '100', + }), + ).rejects.toThrow('Invalid transaction fee') + }) + }) + + describe('with an invalid value', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.mintAsset({ + account: 'account', + fee: '1', + metadata: '{ url: hello }', + name: 'fake-coin', + value: '-1', + }), + ).rejects.toThrow('Invalid mint amount') + }) + }) + + describe('with valid parameters', () => { + it('returns the asset identifier and transaction hash', async () => { + const node = routeTest.node + const wallet = node.wallet + const account = await useAccountFixture(wallet) + + const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') + const value = BigInt(10) + const mintTransaction = await useTxFixture(wallet, account, account, async () => { + const raw = await wallet.createTransaction( + account, + [], + [{ asset, value }], + [], + BigInt(0), + 0, + ) + return wallet.postTransaction(raw) + }) + + jest.spyOn(wallet, 'mint').mockResolvedValueOnce(mintTransaction) + + const response = await routeTest.client.mintAsset({ + account: account.name, + fee: '1', + metadata: asset.metadata().toString('hex'), + name: asset.name().toString('hex'), + value: value.toString(), + }) + expect(response.content).toEqual({ + assetIdentifier: asset.identifier().toString('hex'), + hash: mintTransaction.hash().toString('hex'), + }) + }) + }) +}) diff --git a/ironfish/src/rpc/routes/assets/mint.ts b/ironfish/src/rpc/routes/assets/mint.ts new file mode 100644 index 0000000000..6f074693c6 --- /dev/null +++ b/ironfish/src/rpc/routes/assets/mint.ts @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import * as yup from 'yup' +import { Assert } from '../../../assert' +import { CurrencyUtils } from '../../../utils' +import { ValidationError } from '../../adapters' +import { ApiNamespace, router } from '../router' + +export interface MintAssetRequest { + account: string + fee: string + metadata: string + name: string + value: string +} + +export interface MintAssetResponse { + assetIdentifier: string + hash: string +} + +export const MintAssetRequestSchema: yup.ObjectSchema = yup + .object({ + account: yup.string().required(), + fee: yup.string().required(), + metadata: yup.string().required(), + name: yup.string().required(), + value: yup.string().required(), + }) + .defined() + +export const MintAssetResponseSchema: yup.ObjectSchema = yup + .object({ + assetIdentifier: yup.string().required(), + hash: yup.string().required(), + }) + .defined() + +router.register( + `${ApiNamespace.asset}/mint`, + MintAssetRequestSchema, + async (request, node): Promise => { + const account = node.wallet.getAccountByName(request.data.account) + if (!account) { + throw new ValidationError(`No account found with name ${request.data.account}`) + } + + const fee = CurrencyUtils.decode(request.data.fee) + if (fee < 1n) { + throw new ValidationError(`Invalid transaction fee, ${fee}`) + } + + const value = CurrencyUtils.decodeIron(request.data.value) + if (value <= 0) { + throw new ValidationError('Invalid mint amount') + } + + const transaction = await node.wallet.mint( + node.memPool, + account, + request.data.name, + request.data.metadata, + value, + fee, + ) + Assert.isEqual(transaction.mints.length, 1) + const mint = transaction.mints[0] + + request.end({ + assetIdentifier: mint.asset.identifier().toString('hex'), + hash: transaction.hash().toString('hex'), + }) + }, +) diff --git a/ironfish/src/rpc/routes/index.ts b/ironfish/src/rpc/routes/index.ts index 817f44388a..9ce0b2a81b 100644 --- a/ironfish/src/rpc/routes/index.ts +++ b/ironfish/src/rpc/routes/index.ts @@ -1,6 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +export * from './assets' export * from './wallet' export * from './config' export * from './chain' diff --git a/ironfish/src/rpc/routes/router.ts b/ironfish/src/rpc/routes/router.ts index bd1d2c2351..36cef7d0d2 100644 --- a/ironfish/src/rpc/routes/router.ts +++ b/ironfish/src/rpc/routes/router.ts @@ -11,6 +11,7 @@ import { RpcRequest } from '../request' import { RpcServer } from '../server' export enum ApiNamespace { + asset = 'asset', chain = 'chain', config = 'config', event = 'event', diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 481eff7e7e..2380cb893b 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -748,6 +748,37 @@ export class Wallet { return transaction } + async mint( + memPool: MemPool, + account: Account, + name: string, + metadata: string, + value: bigint, + fee: bigint, + ): Promise { + const heaviestHead = this.chain.head + if (heaviestHead === null) { + throw new Error('You must have a genesis block to create a transaction') + } + + const asset = new Asset(account.spendingKey, name, metadata) + const raw = await this.createTransaction(account, [], [{ asset, value }], [], fee, 0) + + const transaction = await this.postTransaction(raw) + + const verify = this.chain.verifier.verifyCreatedTransaction(transaction) + if (!verify.valid) { + throw new Error(`Invalid transaction, reason: ${String(verify.reason)}`) + } + + await this.addPendingTransaction(transaction) + memPool.acceptTransaction(transaction) + this.broadcastTransaction(transaction) + this.onTransactionCreated.emit(transaction) + + return transaction + } + async createTransaction( sender: Account, receives: { From 43141f3394734f2ab82b703fb0b7de35086e32a7 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:08:48 -0500 Subject: [PATCH 07/56] feat(ironfish): Pass `assetIdentifier` in `transaction/sendTransaction` (#2760) * feat(ironfish): Pass `assetIdentifier` in `transaction/sendTransaction` * fix(cli): Pass asset identifier in faucet and pay * test(ironfish): Pass asset identifier * fix(ironfish): Init amount as fee * feat(cli): Add `assetIdentifier` to pay command (#2770) * feat(cli): Add `assetIdentifier` to pay command * feat(cli,ironfish): Make identifier optional in CLI * refactor(ironfish): Remove identifier in error --- ironfish-cli/src/commands/accounts/pay.ts | 15 ++++--- ironfish-cli/src/commands/service/faucet.ts | 2 + ironfish/src/mining/poolShares.ts | 2 + .../transactions/sendTransaction.test.ts | 11 +++-- .../routes/transactions/sendTransaction.ts | 42 ++++++++++++------- 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/pay.ts b/ironfish-cli/src/commands/accounts/pay.ts index 15354493ba..5d346be640 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/accounts/pay.ts @@ -53,6 +53,10 @@ export class Pay extends IronfishCommand { description: 'The priority level for transaction fee estimation.', options: ['low', 'medium', 'high'], }), + assetIdentifier: Flags.string({ + char: 'i', + description: 'The identifier for the asset to use when paying', + }), } async start(): Promise { @@ -78,13 +82,13 @@ export class Pay extends IronfishCommand { amount = CurrencyUtils.decodeIron(flags.amount) } + const assetIdentifier = flags.assetIdentifier + if (amount === null) { - const response = await client.getAccountBalance({ account: from }) + const response = await client.getAccountBalance({ account: from, assetIdentifier }) const input = (await CliUx.ux.prompt( - `Enter the amount in $IRON (balance: ${CurrencyUtils.renderIron( - response.content.confirmed, - )})`, + `Enter the amount (balance: ${CurrencyUtils.renderIron(response.content.confirmed)})`, { required: true, }, @@ -226,7 +230,8 @@ ${CurrencyUtils.renderIron(amount, true)} plus a transaction fee of ${CurrencyUt { publicAddress: to, amount: CurrencyUtils.encode(amount), - memo: memo, + memo, + assetIdentifier, }, ], fee: CurrencyUtils.encode(fee), diff --git a/ironfish-cli/src/commands/service/faucet.ts b/ironfish-cli/src/commands/service/faucet.ts index 374ce5c13c..e91979ad74 100644 --- a/ironfish-cli/src/commands/service/faucet.ts +++ b/ironfish-cli/src/commands/service/faucet.ts @@ -1,6 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' import { Meter, PromiseUtils, RpcConnectionError, RpcSocketClient, WebApi } from '@ironfish/sdk' import { Flags } from '@oclif/core' import { IronfishCommand } from '../../command' @@ -176,6 +177,7 @@ export default class Faucet extends IronfishCommand { publicAddress: ft.public_key, amount: BigInt(FAUCET_AMOUNT).toString(), memo: `Faucet for ${ft.id}`, + assetIdentifier: Asset.nativeIdentifier().toString('hex'), } }) diff --git a/ironfish/src/mining/poolShares.ts b/ironfish/src/mining/poolShares.ts index b2399f4f87..f1b4d8bba3 100644 --- a/ironfish/src/mining/poolShares.ts +++ b/ironfish/src/mining/poolShares.ts @@ -1,6 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' import { Config } from '../fileStores/config' import { Logger } from '../logger' import { RpcSocketClient } from '../rpc/clients/socketClient' @@ -152,6 +153,7 @@ export class MiningPoolShares { publicAddress, amount: amt.toString(), memo: `${this.poolName} payout ${shareCutoff.toUTCString()}`, + assetIdentifier: Asset.nativeIdentifier().toString('hex'), } }, ) diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts b/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts index 1b451b6d37..bd44fee166 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts @@ -15,6 +15,7 @@ const TEST_PARAMS = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', + assetIdentifier: Asset.nativeIdentifier().toString('hex'), }, ], fee: BigInt(1).toString(), @@ -27,11 +28,13 @@ const TEST_PARAMS_MULTI = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', + assetIdentifier: Asset.nativeIdentifier().toString('hex'), }, { publicAddress: 'test3', amount: BigInt(10).toString(), memo: '', + assetIdentifier: Asset.nativeIdentifier().toString('hex'), }, ], fee: BigInt(1).toString(), @@ -77,7 +80,7 @@ describe('Transactions sendTransaction', () => { await expect(routeTest.client.sendTransaction(TEST_PARAMS)).rejects.toThrow( expect.objectContaining({ message: expect.stringContaining( - 'Your balance is too low. Add funds to your account first', + `Your balance is too low. Add funds to your account first`, ), status: 400, code: ERROR_CODES.INSUFFICIENT_BALANCE, @@ -87,7 +90,7 @@ describe('Transactions sendTransaction', () => { await expect(routeTest.client.sendTransaction(TEST_PARAMS_MULTI)).rejects.toThrow( expect.objectContaining({ message: expect.stringContaining( - 'Your balance is too low. Add funds to your account first', + `Your balance is too low. Add funds to your account first`, ), status: 400, code: ERROR_CODES.INSUFFICIENT_BALANCE, @@ -108,7 +111,7 @@ describe('Transactions sendTransaction', () => { await expect(routeTest.client.sendTransaction(TEST_PARAMS)).rejects.toThrow( expect.objectContaining({ message: expect.stringContaining( - 'Your balance is too low. Add funds to your account first', + `Your balance is too low. Add funds to your account first`, ), status: 400, code: ERROR_CODES.INSUFFICIENT_BALANCE, @@ -124,7 +127,7 @@ describe('Transactions sendTransaction', () => { await expect(routeTest.client.sendTransaction(TEST_PARAMS_MULTI)).rejects.toThrow( expect.objectContaining({ message: expect.stringContaining( - 'Your balance is too low. Add funds to your account first', + `Your balance is too low. Add funds to your account first`, ), status: 400, code: ERROR_CODES.INSUFFICIENT_BALANCE, diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.ts b/ironfish/src/rpc/routes/transactions/sendTransaction.ts index 4a0993f5cf..59dfb88a29 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.ts +++ b/ironfish/src/rpc/routes/transactions/sendTransaction.ts @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Asset } from '@ironfish/rust-nodejs' +import { BufferMap } from 'buffer-map' import * as yup from 'yup' import { CurrencyUtils } from '../../../utils' import { NotEnoughFundsError } from '../../../wallet/errors' @@ -14,6 +15,7 @@ export type SendTransactionRequest = { publicAddress: string amount: string memo: string + assetIdentifier?: string }[] fee: string expiration?: number | null @@ -25,6 +27,7 @@ export type SendTransactionResponse = { publicAddress: string amount: string memo: string + assetIdentifier?: string }[] fromAccountName: string hash: string @@ -40,6 +43,7 @@ export const SendTransactionRequestSchema: yup.ObjectSchema( } const receives = transaction.receives.map((receive) => { + let assetIdentifier = Asset.nativeIdentifier() + if (receive.assetIdentifier) { + assetIdentifier = Buffer.from(receive.assetIdentifier, 'hex') + } + return { publicAddress: receive.publicAddress, amount: CurrencyUtils.decode(receive.amount), memo: receive.memo, - assetIdentifier: Asset.nativeIdentifier(), + assetIdentifier, } }) const fee = CurrencyUtils.decode(transaction.fee) - const sum = receives.reduce((m, c) => m + c.amount, fee) - if (fee < 1n) { throw new ValidationError(`Invalid transaction fee, ${transaction.fee}`) } - for (const receive of receives) { - if (receive.amount < 0) { - throw new ValidationError(`Invalid transaction amount, ${receive.amount}`) + const totalByAssetIdentifier = new BufferMap() + totalByAssetIdentifier.set(Asset.nativeIdentifier(), fee) + for (const { assetIdentifier, amount } of receives) { + if (amount < 0) { + throw new ValidationError(`Invalid transaction amount ${amount}.`) } + + const sum = totalByAssetIdentifier.get(assetIdentifier) ?? BigInt(0) + totalByAssetIdentifier.set(assetIdentifier, sum + amount) } // Check that the node account is updated - // TODO(mgeist,rohanjadvani): Pass through asset identifier - const balance = await node.wallet.getBalance(account, Asset.nativeIdentifier()) + for (const [assetIdentifier, sum] of totalByAssetIdentifier) { + const balance = await node.wallet.getBalance(account, assetIdentifier) - if (balance.confirmed < sum) { - throw new ValidationError( - 'Your balance is too low. Add funds to your account first', - undefined, - ERROR_CODES.INSUFFICIENT_BALANCE, - ) + if (balance.confirmed < sum) { + throw new ValidationError( + `Your balance is too low. Add funds to your account first`, + undefined, + ERROR_CODES.INSUFFICIENT_BALANCE, + ) + } } try { From 900bb303b0ab3384f43aa11c128ecf7b23b77091 Mon Sep 17 00:00:00 2001 From: Mira Yadav <40811052+mirayadav@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:12:52 -0500 Subject: [PATCH 08/56] Fix submittedSequence for transaction in connectTransaction (#2791) --- ironfish/src/wallet/account.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index 0ea8d5d3b7..600f6e33d9 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -182,8 +182,14 @@ export class Account { tx?: IDatabaseTransaction, ): Promise { const balanceDeltas = new AssetBalanceDeltas() + let submittedSequence: number | null = null await this.walletDb.db.withTransaction(tx, async (tx) => { + const transactionValue = await this.getTransaction(transaction.hash(), tx) + if (transactionValue) { + submittedSequence = transactionValue.submittedSequence + } + for (const decryptedNote of decryptedNotes) { if (decryptedNote.forSpender) { continue @@ -230,7 +236,7 @@ export class Account { transaction, blockHash: blockHeader.hash, sequence: blockHeader.sequence, - submittedSequence: blockHeader.sequence, + submittedSequence, }, tx, ) From cfa9529ba160e5954fc0a431af0e450700a59f1a Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:30:27 -0500 Subject: [PATCH 09/56] feat(cli): Introduce `assets:mint` CLI command (#2788) --- ironfish-cli/src/commands/wallet/mint.ts | 121 +++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 ironfish-cli/src/commands/wallet/mint.ts diff --git a/ironfish-cli/src/commands/wallet/mint.ts b/ironfish-cli/src/commands/wallet/mint.ts new file mode 100644 index 0000000000..24ccc9c569 --- /dev/null +++ b/ironfish-cli/src/commands/wallet/mint.ts @@ -0,0 +1,121 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { CurrencyUtils } from '@ironfish/sdk' +import { CliUx, Flags } from '@oclif/core' +import { IronfishCommand } from '../../command' +import { RemoteFlags } from '../../flags' +import { ProgressBar } from '../../types' + +export class Mint extends IronfishCommand { + static description = 'Mint tokens and increase supply for a given asset' + + static examples = [ + '$ ironfish wallet:mint -m "see more here" -n mycoin -a 1000 -f myaccount -o 1', + ] + + static flags = { + ...RemoteFlags, + account: Flags.string({ + char: 'f', + description: 'The account to mint from', + required: true, + }), + fee: Flags.string({ + char: 'o', + description: 'The fee amount in IRON', + required: true, + }), + amount: Flags.string({ + char: 'a', + description: 'Amount of coins to mint', + required: true, + }), + metadata: Flags.string({ + char: 'm', + description: 'Metadata for the asset', + required: true, + }), + name: Flags.string({ + char: 'n', + description: 'Name for the asset', + required: true, + }), + } + + async start(): Promise { + const { flags } = await this.parse(Mint) + // TODO(mgeist,rohanjadvani): + // These fields will be required for now. They will be made optional when + // this CLI command is refactored to also accept an asset identifier + const account = flags.account + const fee = flags.fee + const metadata = flags.metadata + const name = flags.name + const amount = flags.amount + const client = await this.sdk.connectRpc(false, true) + + const status = await client.getNodeStatus() + if (!status.content.blockchain.synced) { + this.log( + `Your node must be synced with the Iron Fish network to send a transaction. Please try again later`, + ) + this.exit(1) + } + + const bar = CliUx.ux.progress({ + barCompleteChar: '\u2588', + barIncompleteChar: '\u2591', + format: 'Creating the transaction: [{bar}] {percentage}% | ETA: {eta}s', + }) as ProgressBar + + bar.start() + + let value = 0 + const timer = setInterval(() => { + value++ + bar.update(value) + if (value >= bar.getTotal()) { + bar.stop() + } + }, 1000) + + const stopProgressBar = () => { + clearInterval(timer) + bar.update(100) + bar.stop() + } + + try { + const result = await client.mintAsset({ + account, + fee, + metadata, + name, + value: amount, + }) + + stopProgressBar() + + const response = result.content + this.log(` + Minted asset ${name} from ${account} + Asset Identifier: ${response.assetIdentifier} + Value: ${amount} + + Transaction Hash: ${response.hash} + Transaction fee: ${CurrencyUtils.renderIron(fee, true)} + + Find the transaction on https://explorer.ironfish.network/transaction/${ + response.hash + } (it can take a few minutes before the transaction appears in the Explorer)`) + } catch (error: unknown) { + stopProgressBar() + this.log(`An error occurred while minting the asset.`) + if (error instanceof Error) { + this.error(error.message) + } + this.exit(2) + } + } +} From f47462b63a109265b3c446ed49df609fbf9c8f84 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Wed, 21 Dec 2022 10:42:02 -0800 Subject: [PATCH 10/56] removes unused wallet code for syncing transactions (#2783) * removes unused wallet code for syncing transactions removes syncTransaction from wallet and account. removes SyncTransactionParams. removes bulkUpdateDecryptedNotes and processTransactionSpends which were only called from syncTransaction. removes updateDecryptedNote and replaces remaining uses with calls to saveDecryptedNote. removes updateTransaction and replaces remaining uses with calls to saveTransaction. removes unnecessary join with transactions in getUnspentNotes; uses decryptedNote.sequence for block confirmations. * removes fixtures for removed tests * fixes expirationSequence from bad rebase * fixes lint --- ironfish/src/testUtilities/mocks.ts | 1 - .../__fixtures__/wallet.test.ts.fixture | 204 ------------------ ironfish/src/wallet/account.ts | 156 +------------- ironfish/src/wallet/wallet.test.ts | 118 +--------- ironfish/src/wallet/wallet.ts | 66 +----- 5 files changed, 8 insertions(+), 537 deletions(-) diff --git a/ironfish/src/testUtilities/mocks.ts b/ironfish/src/testUtilities/mocks.ts index fa4e131179..72146712a8 100644 --- a/ironfish/src/testUtilities/mocks.ts +++ b/ironfish/src/testUtilities/mocks.ts @@ -25,7 +25,6 @@ export function mockEvent(): any { export function mockWallet(): any { return { onBroadcastTransaction: mockEvent(), - syncTransaction: jest.fn(), } } diff --git a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture index aa8f49e7c2..3419d23716 100644 --- a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture +++ b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture @@ -1829,210 +1829,6 @@ ] } ], - "Accounts syncTransaction should not re-sync expired transactions": [ - { - "id": "cd50a62f-aac2-4e94-93ff-a76e2cac05b5", - "name": "a", - "spendingKey": "487a4ebad16142cd8665118fcd0c0bceb4f59680e73c7cab1224af059031317f", - "incomingViewKey": "204a8302844e45354d36ceee97657424365f7648f36d5a4158ffda73671c0304", - "outgoingViewKey": "7c5c342f43f3d5dbbc269b6e4e55ba88f6a9314ba8506bb6222f106226ced765", - "publicAddress": "9db7bc8bef5c9c861c0b4f6d8b9ea37ac1b39236b06e72c631a38bf24e89796d" - }, - { - "id": "fb30904f-3d87-43e2-a62b-4681d05b88fb", - "name": "b", - "spendingKey": "99e27770c1a93ceddf1ea92e7ac6f47bd0f55182a8b410ab842e3d6b4e20ae4d", - "incomingViewKey": "65bbe30c7ca978b3f8b1e05f5727744c6c5fc641fc135168fc2d06f662c80f01", - "outgoingViewKey": "6dd0a948cf75dfce6c12efa7559a0477d9cd69d98cf6640f624de85f64479453", - "publicAddress": "ab72a641500f5b97df3127de466ada641d7d5bd11742a1080c3dc58d9bd1f841" - }, - { - "header": { - "sequence": 2, - "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", - "noteCommitment": { - "type": "Buffer", - "data": "base64:9fC8t43TBK6/9msz/zFMp0AjaNHs9vtAEKVr4cpf2Tg=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:XCWjjCCbbx8Y7N8NqAQhFnzyEu7Q46QEBZ2kfiC2gnA=" - }, - "target": "883423532389192164791648750371459257913741948437809479060803100646309888", - "randomness": "0", - "timestamp": 1671522106720, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 4, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAFKhEplPb5avY5AdS4cfNq3aq+ykrl3bZ/sJ4569HK7mk1lf/lNIJUi1Uv2DI8dYxorEPz8wkiC+QlZ/08QytmgIebQ3PEI+uLRf0tvv1CJK54JC0t3ELGjnBuDCb5N5gaMy40khFvJIkNOTu98iSbZ9TTHshSx46JfYwlls+7XcWExsf01fBGZXPPlIWNlMIiSLpubBMMOn1eIWjP3jB9ypwtcn9MeixjdLiIR8m/pOKFngYYSz/rHdZW8O4gBgva+x8qOQ8xI2CQUoar3OZy0/wgkDE83YlcvApQif2B0F0glfOeDe5Y3xZZQlPK4GhdS37RKGgMt3kA/k/C2VhtZm9vq8KM118Ox3igssoOnQgIMt5exh799sCEqB81kEq9cB49XaC/t6/FpnvICvynv/iAx3TLFP0CZe5TocrcjEw35nSOtm5n8LAX+D7Uu82tcQWY2EaFytyJQcxIyQTIaAFJVStUHUbSdebYqhInFJ/CgsgZDfZMBxWnV8gYHUJu1zrixJ/0s1OohyM2Nsav1bnWJpDJT+q4yUNp0MzrIFZUyHuvTH8ocLHoaL9/hYgJntzUxMHzf02i3zJHlNXtl1Ml093gfi/l2aik44Yeuyt93AKZkvQ3Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwr42zUPXfe3atZZpIM4su/YhV/eVQerE/dr2ngPU2XqlvY/WZlhRvKZjqURBar2ZYJvUB2f1oJqiVv/hY+xMtAw==" - } - ] - }, - { - "type": "Buffer", - "data": "base64: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" - }, - { - "header": { - "sequence": 3, - "previousBlockHash": "29165EAD74A3933A959371BFEE5053B354996C4B740E2CF2444B14F07DB8C3F0", - "noteCommitment": { - "type": "Buffer", - "data": "base64:0+vPuCB/Pl/GcPbxDVg0NrIsQJl4GLrfrcNQTfxgxRc=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:/wi7EsMOfiThb97EEQNEB8/b3HZTUB/Q4t9fqEcgw28=" - }, - "target": "880842937844725196442695540779332307793253899902937591585455087694081134", - "randomness": "0", - "timestamp": 1671522108555, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 5, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAe0NVlbu/QcsmYMA/iEkCP6DyoBblXDHqlpeJt++iZ7ONqoKhkoQDcxagRECd44Dg+9Lm9q+YtMmgf8/hdCZvx7/Si9JpzH7/ZGMuvOjWY2i1hCQmzrblfWJMFm9Drz4LLomHnskSCrzkfuffiMw3+gV3zQ3VdBKI3xZhBOGQt2sNs3IDux0NZcokU3X4/CBfSOaTkYMB8qBpGU0vfBdz2mXdo9HMvah34GmGzU7YdM6LbigFKmHrgVrwLaxQV3Z/h8BKqzO2sURzf180ByV8gvJ8S54ffnOVytkdqFhM6CeXvgbCw0qZ3EMEMX7+pFnAMZAWreOnop/nwA3XRJ2RYGKNfaMHDEC/QzZIsuuC9qTvnJsI7bbTOoK3LFxYPbdpZxXV99pX7ZwETSYSYE6X0hdb3UBxCAyIE0idlM+59tdB35LXok7ip/c7YGpz8WjFGT09l3s5LU2lqQKBzfqCYXLGnw4tqPzcCVrR+YvKUcUYnNHxaOPoXT+ZwI+DAKHhGyohKfM6S6BeSeGhBLQG6sD20NcFz1TPZi46j+BPpAOR7GAasNu8++MKm+9xhXKDxQ9irR0FP/JT/1+z8AIUMjpZAnzpKpc3CYql9br8FAOI7+1kIv/q60lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAO53oDoDYQztIWuB7tHUrLhERC/Q5tLMvcOgnX1p5S6wG/PWClqSvusRSqWPYAvXGe/8snpw7BIpYS0Xsio5Dg==" - } - ] - } - ], - "Accounts syncTransaction should re-sync expired transactions if they were added on blocks": [ - { - "id": "84aaabe1-cc10-44fd-bb9a-34adf2e36d54", - "name": "a", - "spendingKey": "2cf4c7b55a1f2c591eeb6423337718bb773f8d430e969726e220cf4432a54d5b", - "incomingViewKey": "69e03dcee37baeaa9f7dffb3babcf6dbb5c1f3acb145e9edadd0dde633185803", - "outgoingViewKey": "4867ee829865bca48840e769560d28e82e07401b20919e081dd4cb1f82846a07", - "publicAddress": "1d44e82d6737f75ac517c886831c973e8e5aceb7e05b6d21e4dcd4f6063dea91" - }, - { - "id": "e2d6af57-a4b6-42bf-bfb5-7fa72ed502f0", - "name": "b", - "spendingKey": "ada35ecfa761c0cb18ce4d51c1b1f4805106e0a905b106b8c2a016a9e04db381", - "incomingViewKey": "dc01ba60c689c344ab3b3ad36eb3fc95adbe626a3ed9182c84664e3a04540501", - "outgoingViewKey": "54c6113d668b554370d2c5829ad1da0a16e8205989c1f357c5a4b1a7c7d90f98", - "publicAddress": "63cc2d18b60bdfe670708bb4e265f280554c3bc1aa85a0a18fce0171264d68bd" - }, - { - "header": { - "sequence": 2, - "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", - "noteCommitment": { - "type": "Buffer", - "data": "base64:NJNipEuywHnNAhelHkEVZaPraUgprKSoFW4dB282U2Q=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:EWneKY1N9smwnleCmQHnEI6zNcJV9RjBETgf/nq9Q/Q=" - }, - "target": "883423532389192164791648750371459257913741948437809479060803100646309888", - "randomness": "0", - "timestamp": 1671522108995, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 4, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAUTRscuyPeJGmlz+epBhvhZ3cUAZD7zfEjyPbdlwS5F+Oj74iYnvMU5JxTvH7bsHflLCruU00hMFgvEkhKAZNWcRG/RgvF2KVYU4diyIO2oy1OA0h/yoLYhl7n3bDI6sSFRw94NrWnlw9u7SU5DA1WXjq6ZjQf2Q9el9qpwVKTWcM5sSjSeJzGo5CY0f/AFeDWaNg7/x9u5uD3pvbOQfOcLRhJFzZGXWivyMPo6FP1uum5pAylqSoNUvLBF+50YaPFcjSRwoQniH/dLBZf7GRqdLoZ7laMvyaGCRHg0AUyFinVqylxFmlesxQ+utU11eypNOhoPQdjpX2lFSHaUsccMnyewXLMDJqx1bYek/Z2RW+eP2LTeEVPmoYacWrNVlMZ9Z9kNgnG65BhMcAtcyfJqx13CYa1oD/bgKcF91AJMBM9Bvp5sJA4nN2oUcVVlZu9KyTRqIb7c+xAbByts6aOidHBNKt05m2RWGOST68L/RXbGUlkEwc3bAWhgSlPSWsQjwH4FKbBZMOpev3VAxmZ7TIy52BNrvm/alrTPYD7wSVlSKKigo3tUn9xwQ9gh1i+lFKGzo153SLl8/yWTta4BZKvNL75NTehQnXmJvcpolJ4IotqeATQklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwVd5lVDwFntdaWtQSLbQ8uBjlHtNvjAybdpb/w7w5Bd41jbKv4YN3c8TSrlSDdvJCQHHIWcfXTAE9z95MOYeYCA==" - } - ] - }, - { - "type": "Buffer", - "data": "base64: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" - }, - { - "header": { - "sequence": 3, - "previousBlockHash": "24E0CF2FC24BD3AB8B1C563CDED737FAD8AAFD2B0A85F0E1DD5C768734D6184A", - "noteCommitment": { - "type": "Buffer", - "data": "base64:LH1xhUCn4BbeA/y7I91FLEVQW+TFlPv/Q4VbDBhLxj8=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:BOFZM+Wv2GGwlNF75CGTPwMtDcuaKNSww6QPKZDV1UQ=" - }, - "target": "880842937844725196442695540779332307793253899902937591585455087694081134", - "randomness": "0", - "timestamp": 1671522110888, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 5, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAymdi28grc5Y2Wgr6mnFrE+YlaE2bLYbZ55G280e/fpyPszOtwcC3V5eUQOw1fh4yCb7B69YZuMqQHEeJ2mvL6Ab6s9501R/irXqVUwnbSqqMPeZdLaaVjpwQlvAtlV61Tjyb7rizGmC69Q4OAHyN1CvMZdF/8WfZENCFZ4B3640Up2kbogJEg70MVhRO3hA7xX/ZjafiocBHwFqb0EexL63oT9QdkC5eANRSK1iTxxaMUcmei6C5nOYw5ixqB1b3qCAIl8bDBITGaalokr+Vvf+7JkzJ3xU0gzSR9Pry3BoFKaU7FeCwl8fkr70f8JEHwoZ2yTeVuY6rqggj4tZhVuuqtjKb8qWX5+fE0nYLB1RTna2VeRcNJL4VicKHTxY6sHRmYfb4psS3B8TolEi4Xh58sfEViX68NQg3CFMSvLuDwv2j0GPJl46JwXj8rONchSyPGaKEtrA8db3ff/eBN3W3K9P0wMq2QcESRSJwU08U1LgBgmHXoEISDMEWpIu/0XgZLMUgorvNo2BLxNbjTwmcS00lwgNo/tz2b2iOc+N1RzTg8J1xm0OJo/2cJBiOi6nsYOUCdgDz/xtH6UO1ItTXHF2F0htJjPboyhEIVtEBdy3E2mj+aElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwjZplYBs3IA6JLHCP+osIIG8LUtIUFx6enOIxy0uOahiEB0+bybGDMQHQKs4siCmd/0/8mW3LVv3uvZx/4NWgDQ==" - } - ] - }, - { - "header": { - "sequence": 3, - "previousBlockHash": "24E0CF2FC24BD3AB8B1C563CDED737FAD8AAFD2B0A85F0E1DD5C768734D6184A", - "noteCommitment": { - "type": "Buffer", - "data": "base64:7P+sry+rPqYmbKcrCXiPPvWHiST22yz1INvlGyvt3S8=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:cAIss3j4SDbDt12K6DaDeRbBH9y1uq1/rQ459Bvnu30=" - }, - "target": "880842937844725196442695540779332307793253899902937591585455087694081134", - "randomness": "0", - "timestamp": 1671522111231, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 7, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAiLe9j3XZF98f14llmM44nw0bk39RQrkluQtSVi0HAYSYL2LgKqnp5s7Yng19GYvJFsVqbzNeEV0mrq4LGZhJ5Gv7bO2DAVxf+ALtp3rP59mtL+rPGM17RPj+jy158Psez3DSMLV+a4omRNbTLtEnGMPOoefo8Y6sYvJTd3PHiQUBggh7JAVXQJlb5jKPtr9+kw2ucKl2rd5NxB40v/6KQHfIwu1tJJiPB7bY4hZJ0lu0a7P4VLqwW7ZvdTYUc050pjy8SQU+WIzinMMd9sisMkgJRc9hy9e/q7lRELrx2PuQdjQSBg+bP8h6Np/VqJPbv0+j2HVgrPJutN+Am4Sw4/wBCa9GpqY34GDvpVMbxYXmcWqoiYObeEWCFcFylWxonWZnuozySCzJPxBXBJDq9W7rDGgXAEy/bk1taNXJ1bBZjyYqTUSqIL8DzPbXHgpieMRta1sSUrsFjP3QY+ClHPE6j8r/L7fzIE0gDzezC8MlzJYqJY7X27fzFIStMwcbCaa/vgOcUuIF4i7weRSFdzxIOL6AheDZBJoaRKghcIfj6ZCwmGwsevO7PM078b1Prt+sBTM1I2k+B3fcwrKhSedv9AntYcFDZOXouCOJn/CTSi6UhSO/b0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwFBHqQJyCJz2UXKYN2C9cOMQrXW/FNVAg1NHc2rON2zFNF1ROWx1ffa4jxxiCFELCklkdj/sqRIQnxvJyT3s8AQ==" - }, - { - "type": "Buffer", - "data": "base64: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" - } - ] - }, - { - "header": { - "sequence": 4, - "previousBlockHash": "3F1D34416300B995AFBA6D506448BEF367BE6665A1FB2F165EAB8F13325C7C04", - "noteCommitment": { - "type": "Buffer", - "data": "base64:uAvEtf3xY7fKF5P38o426gktzlBo7R3rNDiuBAN2qj4=" - }, - "transactionCommitment": { - "type": "Buffer", - "data": "base64:+82vh1m7M5QRDzmcVFTLNjqCJXlQy30703jPwp+/nZU=" - }, - "target": "878277375889837647326843029495509009809390053592540685978895509768758568", - "randomness": "0", - "timestamp": 1671522111567, - "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 8, - "work": "0" - }, - "transactions": [ - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAIPXjp7OLqoVzP4oZ4JwXjR9N71W72IIa8ZH/rorMjxayp3xV/nfgprBovBeoKzn33Affsz9RCyQEQAFTStesHDOsT+uEfvzsTs1Rxj+al0qzRbUVQGZpn7QIZfsqgr5+3kMf1X4cs3D/v5we+iiOoFWEYjo9qTLX6rB04R4/P9gJ81geGfoFq9SgG36nP1g7QiGNFTF4yv912l7OjEHhnBcYFwSBeerhioXR8gk40eCgTUsVxJgY5kmzRm+71+mv3ha1HbKDwZwGsP25oEfdGlvHUozH0gWY0C/dtmgVlh41WaLK6qwp+eP+baJeGUdMGOHuQkA9Tv477ErsoXgmQTeT/cU0Ls9kXE7ve1esAknvR0oNL3xo7l5K7GFXAYJUH8QD6K9YqXQQDlxPEScVHjaSUM0U/b8otELNS5xgoxnFVYdJGsfMbBT1vRcFRWoxE21BjGyAS1XGjV3YIoHxYs20IBLiswGT30yMgzNzdZ24NxHenfMpWNu6qg3mMIBlzHmGLqLzKwow13b8JOeQeO+ndk3+DqEUXrBy71WXLgFiV5VxKe/x8Fcl2dCV9DBOqPWwMXjXca9furHWOD7mwGZkK7MLi2QKo/C3JFOAWtaW1im0sv2u7Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmE06nRfw9C6GHHQSOmMl327tTrUJAVrV1kcHxbWkKdsowQ6+DvuTuUCTwkVE+UqwVLDD8MvlK4F2HO0/RR8sBQ==" - } - ] - } - ], "Accounts createSpendsForAsset returns spendable notes for a provided asset identifier": [ { "id": "4a9c61df-276c-46ad-8429-09211f274afc", diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index 600f6e33d9..ab392049e8 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -9,9 +9,7 @@ import { GENESIS_BLOCK_SEQUENCE } from '../primitives/block' import { Note } from '../primitives/note' import { DatabaseKeyRange, IDatabaseTransaction } from '../storage' import { StorageUtils } from '../storage/database/utils' -import { BufferUtils } from '../utils' import { DecryptedNote } from '../workerPool/tasks/decryptNotes' -import { SyncTransactionParams } from './wallet' import { AccountValue } from './walletdb/accountValue' import { DecryptedNoteValue } from './walletdb/decryptedNoteValue' import { TransactionValue } from './walletdb/transactionValue' @@ -118,63 +116,6 @@ export class Account { return await this.walletDb.loadDecryptedNote(this, hash, tx) } - async updateDecryptedNote( - noteHash: Buffer, - note: Readonly, - tx?: IDatabaseTransaction, - ): Promise { - await this.walletDb.db.withTransaction(tx, async (tx) => { - const existingNote = await this.getDecryptedNote(noteHash, tx) - - if (existingNote && existingNote.nullifier !== null && note.nullifier == null) { - await this.walletDb.deleteNullifier(this, existingNote.nullifier, tx) - } - - await this.walletDb.saveDecryptedNote(this, noteHash, note, tx) - }) - } - - async syncTransaction( - transaction: Transaction, - decryptedNotes: Array, - params: SyncTransactionParams, - tx?: IDatabaseTransaction, - ): Promise { - const transactionHash = transaction.hash() - const blockHash = 'blockHash' in params ? params.blockHash : null - const sequence = 'sequence' in params ? params.sequence : null - let submittedSequence = 'submittedSequence' in params ? params.submittedSequence : null - - await this.walletDb.db.withTransaction(tx, async (tx) => { - const record = await this.getTransaction(transactionHash, tx) - if (record) { - submittedSequence = record.submittedSequence - } - - const shouldUpdateTransaction = - !record || - !record.transaction.equals(transaction) || - !BufferUtils.equalsNullable(record.blockHash, blockHash) - - if (shouldUpdateTransaction) { - await this.updateTransaction( - transactionHash, - { transaction, blockHash, sequence, submittedSequence }, - tx, - ) - } - - await this.bulkUpdateDecryptedNotes( - transactionHash, - decryptedNotes, - blockHash, - sequence, - tx, - ) - await this.processTransactionSpends(transaction, tx) - }) - } - async connectTransaction( blockHeader: BlockHeader, transaction: Transaction, @@ -379,100 +320,6 @@ export class Account { }) } - async updateTransaction( - hash: Buffer, - transactionValue: TransactionValue, - tx?: IDatabaseTransaction, - ): Promise { - await this.walletDb.db.withTransaction(tx, async (tx) => { - await this.walletDb.saveTransaction(this, hash, transactionValue, tx) - }) - } - - // TODO(hughy): this method is now only called when blocks are removed from the chain - // this method now updates the balance when blocks are removed but will be removed once disconnect is implemented - private async bulkUpdateDecryptedNotes( - transactionHash: Buffer, - decryptedNotes: Array, - blockHash: Buffer | null, - sequence: number | null, - tx?: IDatabaseTransaction, - ) { - await this.walletDb.db.withTransaction(tx, async (tx) => { - const balanceDeltas = new AssetBalanceDeltas() - for (const decryptedNote of decryptedNotes) { - if (decryptedNote.forSpender) { - continue - } - - if (decryptedNote.nullifier !== null) { - await this.walletDb.saveNullifierNoteHash( - this, - decryptedNote.nullifier, - decryptedNote.hash, - tx, - ) - } - - const note = new Note(decryptedNote.serializedNote) - balanceDeltas.increment(note.assetIdentifier(), -note.value()) - - await this.updateDecryptedNote( - decryptedNote.hash, - { - accountId: this.id, - nullifier: decryptedNote.nullifier, - index: decryptedNote.index, - note, - spent: false, - transactionHash, - blockHash, - sequence, - }, - tx, - ) - } - - await this.updateUnconfirmedBalances(balanceDeltas, tx) - }) - } - - // TODO(hughy): this method is now only called when a block is disconnected - // this method now updates the balance when blocks are removed but will be removed once disconnect is implemented - private async processTransactionSpends( - transaction: Transaction, - tx?: IDatabaseTransaction, - ): Promise { - const balanceDeltas = new AssetBalanceDeltas() - for (const spend of transaction.spends) { - const noteHash = await this.getNoteHash(spend.nullifier, tx) - - if (noteHash) { - const decryptedNote = await this.getDecryptedNote(noteHash, tx) - Assert.isNotUndefined( - decryptedNote, - 'nullifierToNote mappings must have a corresponding decryptedNote', - ) - - await this.updateDecryptedNote( - noteHash, - { - ...decryptedNote, - spent: true, - }, - tx, - ) - - balanceDeltas.increment( - decryptedNote.note.assetIdentifier(), - -decryptedNote.note.value(), - ) - } - } - - await this.updateUnconfirmedBalances(balanceDeltas, tx) - } - private async deleteDecryptedNote( noteHash: Buffer, transactionHash: Buffer, @@ -554,7 +401,8 @@ export class Account { 'nullifierToNote mappings must have a corresponding decryptedNote', ) - await this.updateDecryptedNote( + await this.walletDb.saveDecryptedNote( + this, noteHash, { ...decryptedNote, diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index aa415fe358..29eaa69801 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -684,7 +684,7 @@ describe('Accounts', () => { const account = await useAccountFixture(node.wallet) const tx = await useMinersTxFixture(node.wallet, account) - await node.wallet.syncTransaction(tx, {}) + await node.wallet.addPendingTransaction(tx) await expect( node.wallet.walletDb.loadTransaction(account, tx.hash()), @@ -933,122 +933,6 @@ describe('Accounts', () => { }) }) - describe('syncTransaction', () => { - it('should not re-sync expired transactions', async () => { - const { node: nodeA } = await nodeTest.createSetup() - - const accountA = await useAccountFixture(nodeA.wallet, 'a') - const accountB = await useAccountFixture(nodeA.wallet, 'b') - - const blockA2 = await useMinerBlockFixture(nodeA.chain, 2, accountA, nodeA.wallet) - await expect(nodeA.chain).toAddBlock(blockA2) - await nodeA.wallet.updateHead() - - // Create a transaction that will expire - const tx = await useTxFixture(nodeA.wallet, accountA, accountB, undefined, undefined, 3) - await expect(accountA.hasPendingTransaction(tx.hash())).resolves.toBeTruthy() - - // Mine a new block at sequence 3, expiring transaction - const blockA3 = await useMinerBlockFixture(nodeA.chain, 3, accountB, nodeA.wallet) - await expect(nodeA.chain).toAddBlock(blockA3) - expect(nodeA.chain.head.hash.equals(blockA3.header.hash)).toBe(true) - - await nodeA.wallet.updateHead() - - await accountA.expireTransaction(tx) - - // none of the transaction's notes are in accountA's wallet - for (const note of tx.notes) { - await expect(accountA.getDecryptedNote(note.merkleHash())).resolves.toBeUndefined() - } - - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - unconfirmed: BigInt(2000000000), // minersFee from blockA1 - }) - - // re-sync expired transaction - await nodeA.wallet.syncTransaction(tx, {}) - - // none of the expired transaction's notes should be in accountA's wallet - for (const note of tx.notes) { - await expect(accountA.getDecryptedNote(note.merkleHash())).resolves.toBeUndefined() - } - - // balance should not have changed - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - unconfirmed: BigInt(2000000000), // minersFee from blockA1 - }) - }) - - it('should re-sync expired transactions if they were added on blocks', async () => { - const { node: nodeA } = await nodeTest.createSetup() - const { node: nodeB } = await nodeTest.createSetup() - - const accountA = await useAccountFixture(nodeA.wallet, 'a') - const accountB = await useAccountFixture(nodeA.wallet, 'b') - - const blockA2 = await useMinerBlockFixture(nodeA.chain, 2, accountA, nodeA.wallet) - await expect(nodeA.chain).toAddBlock(blockA2) - await expect(nodeB.chain).toAddBlock(blockA2) - await nodeA.wallet.updateHead() - - // Create a transaction that will expire - const tx = await useTxFixture(nodeA.wallet, accountA, accountB, undefined, undefined, 4) - - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - confirmed: BigInt(2000000000), - unconfirmed: BigInt(2000000000), - }) - - // Mine a new block at sequence 3, expiring transaction - const blockA3 = await useMinerBlockFixture(nodeA.chain, 3, accountB, nodeA.wallet) - await expect(nodeA.chain).toAddBlock(blockA3) - expect(nodeA.chain.head.hash.equals(blockA3.header.hash)).toBe(true) - - await nodeA.wallet.updateHead() - - await accountA.expireTransaction(tx) - - // none of the transaction's notes are in accountA's wallet - for (const note of tx.notes) { - await expect(accountA.getDecryptedNote(note.merkleHash())).resolves.toBeUndefined() - } - - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - confirmed: BigInt(2000000000), - unconfirmed: BigInt(2000000000), // minersFee from blockA1 - }) - - // mine the transaction on a fork - const blockB3 = await useMinerBlockFixture(nodeB.chain, 3, undefined, undefined, [tx]) - await expect(nodeB.chain).toAddBlock(blockB3) - const blockB4 = await useMinerBlockFixture(nodeB.chain, 4) - await expect(nodeB.chain).toAddBlock(blockB4) - - // re-org nodeA to the fork, and re-sync the transaction - await expect(nodeA.chain).toAddBlock(blockB3) - await expect(nodeA.chain).toAddBlock(blockB4) - expect(nodeA.chain.head.hash.equals(blockB4.header.hash)).toBe(true) - - await nodeA.wallet.updateHead() - - // balance should include the transaction - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - unconfirmed: BigInt(1999999999), // change from transaction - }) - }) - }) - describe('createSpendsForAsset', () => { it('returns spendable notes for a provided asset identifier', async () => { const { node } = await nodeTest.createSetup() diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 2380cb893b..48ea42f14f 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -48,14 +48,6 @@ export enum TransactionStatus { UNKNOWN = 'unknown', } -export type SyncTransactionParams = - // Used when receiving a transaction from a block with notes - // that have been added to the trees - | { blockHash: Buffer; initialNoteIndex: number; sequence: number } - // Used if the transaction is not yet part of the chain - | { submittedSequence: number } - | Record - export class Wallet { readonly onAccountImported = new Event<[account: Account]>() readonly onAccountRemoved = new Event<[account: Account]>() @@ -471,43 +463,6 @@ export class Wallet { } } - /** - * Called: - * - Called for transactions on disconnected blocks - */ - async syncTransaction( - transaction: Transaction, - params: SyncTransactionParams, - accounts?: Array, - ): Promise { - if ( - !('blockHash' in params) && - this.chain.verifier.isExpiredSequence( - transaction.expiration(), - this.chainProcessor.sequence ?? 1, - ) - ) { - return - } - - const initialNoteIndex = 'initialNoteIndex' in params ? params.initialNoteIndex : null - - const decryptedNotesByAccountId = await this.decryptNotes( - transaction, - initialNoteIndex, - accounts, - ) - - for (const [accountId, decryptedNotes] of decryptedNotesByAccountId) { - const account = this.accounts.get(accountId) - - if (!account) { - continue - } - await account.syncTransaction(transaction, decryptedNotes, params) - } - } - async scanTransactions(fromHash?: Buffer): Promise { if (!this.isOpen) { throw new Error('Cannot start a scan if accounts are not loaded') @@ -676,20 +631,11 @@ export class Wallet { for await (const decryptedNote of account.getUnspentNotes(assetIdentifier)) { if (minimumBlockConfirmations > 0) { - const transaction = await account.getTransaction(decryptedNote.transactionHash) - - Assert.isNotUndefined( - transaction, - `Transaction '${decryptedNote.transactionHash.toString( - 'hex', - )}' missing for account '${account.id}'`, - ) - - if (!transaction.sequence) { + if (!decryptedNote.sequence) { continue } - const confirmations = headSequence - transaction.sequence + const confirmations = headSequence - decryptedNote.sequence if (confirmations < minimumBlockConfirmations) { continue @@ -988,7 +934,7 @@ export class Wallet { if (noteMapValue) { this.logger.debug(`Unspent note has index ${String(noteMapValue.index)}`) - await sender.updateDecryptedNote(unspentNote.hash, { + await this.walletDb.saveDecryptedNote(sender, unspentNote.hash, { ...noteMapValue, spent: true, }) @@ -1038,9 +984,6 @@ export class Wallet { continue } - // TODO: Submitted sequence is only set from transactions generated by this node and we don't rebroadcast - // transactions to us, or from us and generated from another node, but we should do this later. It - // will require us to set submittedSequence in syncTransaction to the current head if it's null if (!submittedSequence) { continue } @@ -1060,7 +1003,8 @@ export class Wallet { // We still update this even if it's not valid to prevent constantly // reprocessing valid transaction every block. Give them a few blocks to // try to become valid. - await account.updateTransaction( + await this.walletDb.saveTransaction( + account, transactionHash, { ...transactionInfo, From 4ccbc0a3c094de3c838b9d110106cef09ad96964 Mon Sep 17 00:00:00 2001 From: Mira Yadav <40811052+mirayadav@users.noreply.github.com> Date: Wed, 21 Dec 2022 15:32:46 -0500 Subject: [PATCH 11/56] Add DatabaseIteratorOptions and merge with DatabaseKeyRange to pass into levelup createReadStream (#2798) --- ironfish/src/storage/database/database.ts | 11 +++++++++-- ironfish/src/storage/database/types.ts | 5 +++++ ironfish/src/storage/levelup/database.ts | 9 ++++++--- ironfish/src/storage/levelup/store.ts | 4 +++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ironfish/src/storage/database/database.ts b/ironfish/src/storage/database/database.ts index 2ec2970f3a..e94ebaa393 100644 --- a/ironfish/src/storage/database/database.ts +++ b/ironfish/src/storage/database/database.ts @@ -6,6 +6,7 @@ import { BatchOperation, IDatabaseBatch } from './batch' import { IDatabaseStore, IDatabaseStoreOptions } from './store' import { IDatabaseTransaction } from './transaction' import { + DatabaseIteratorOptions, DatabaseKeyRange, DatabaseOptions, DatabaseSchema, @@ -158,7 +159,10 @@ export interface IDatabase { put(key: Readonly, value: Buffer): Promise /* Get an [[`AsyncGenerator`]] that yields all of the key/value pairs in the IDatabase */ - getAllIter(range?: DatabaseKeyRange): AsyncGenerator<[Buffer, Buffer]> + getAllIter( + range?: DatabaseKeyRange, + options?: DatabaseIteratorOptions, + ): AsyncGenerator<[Buffer, Buffer]> } export abstract class Database implements IDatabase { @@ -193,7 +197,10 @@ export abstract class Database implements IDatabase { abstract put(key: Readonly, value: Buffer): Promise - abstract getAllIter(range?: DatabaseKeyRange): AsyncGenerator<[Buffer, Buffer]> + abstract getAllIter( + range?: DatabaseKeyRange, + options?: DatabaseIteratorOptions, + ): AsyncGenerator<[Buffer, Buffer]> protected abstract _createStore( options: IDatabaseStoreOptions, diff --git a/ironfish/src/storage/database/types.ts b/ironfish/src/storage/database/types.ts index e453cf47e1..275a7b1f48 100644 --- a/ironfish/src/storage/database/types.ts +++ b/ironfish/src/storage/database/types.ts @@ -11,6 +11,11 @@ export interface DatabaseKeyRange { lte?: Buffer } +export interface DatabaseIteratorOptions { + reverse?: boolean + limit?: number +} + export type DatabaseKey = | bigint | number diff --git a/ironfish/src/storage/levelup/database.ts b/ironfish/src/storage/levelup/database.ts index fe79f7b85b..71c79d8d5d 100644 --- a/ironfish/src/storage/levelup/database.ts +++ b/ironfish/src/storage/levelup/database.ts @@ -27,7 +27,7 @@ import { DatabaseIsOpenError, DatabaseVersionError, } from '../database/errors' -import { DatabaseKeyRange } from '../database/types' +import { DatabaseIteratorOptions, DatabaseKeyRange } from '../database/types' import { LevelupBatch } from './batch' import { LevelupStore } from './store' import { LevelupTransaction } from './transaction' @@ -213,8 +213,11 @@ export class LevelupDatabase extends Database { await this.levelup.put(key, value) } - async *getAllIter(range?: DatabaseKeyRange): AsyncGenerator<[Buffer, Buffer]> { - const stream = this.levelup.createReadStream(range) + async *getAllIter( + range?: DatabaseKeyRange, + options?: DatabaseIteratorOptions, + ): AsyncGenerator<[Buffer, Buffer]> { + const stream = this.levelup.createReadStream({ ...range, ...options }) // The return type for createReadStream is wrong const iter = stream as unknown as AsyncIterable<{ diff --git a/ironfish/src/storage/levelup/store.ts b/ironfish/src/storage/levelup/store.ts index 6154539af2..e4f9a8a240 100644 --- a/ironfish/src/storage/levelup/store.ts +++ b/ironfish/src/storage/levelup/store.ts @@ -7,6 +7,7 @@ import MurmurHash3 from 'imurmurhash' import { Assert } from '../../assert' import { AsyncUtils } from '../../utils/async' import { + DatabaseIteratorOptions, DatabaseKeyRange, DatabaseSchema, DatabaseStore, @@ -74,6 +75,7 @@ export class LevelupStore extends DatabaseStore, SchemaValue]> { if (keyRange) { keyRange = StorageUtils.addPrefixToRange(keyRange, this.prefixBuffer) @@ -108,7 +110,7 @@ export class LevelupStore extends DatabaseStore Date: Wed, 21 Dec 2022 17:36:31 -0500 Subject: [PATCH 12/56] Add support for iterating database entries by key order (#2799) --- ironfish/src/storage/database.test.ts | 36 ++++++++++++++++++ ironfish/src/storage/database/store.ts | 9 +++++ ironfish/src/storage/database/types.ts | 1 + ironfish/src/storage/levelup/store.ts | 52 +++++++++++++++++++++----- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/ironfish/src/storage/database.test.ts b/ironfish/src/storage/database.test.ts index a49959868e..4da8396fbf 100644 --- a/ironfish/src/storage/database.test.ts +++ b/ironfish/src/storage/database.test.ts @@ -746,6 +746,42 @@ describe('Database', () => { // No keys should exist expect(await keyStore.getAllKeys()).toHaveLength(0) }) + + it('should order entries by key if ordered option specified', async () => { + await db.open() + + await db.metaStore.clear() + await db.metaStore.put('e', 1000) + await db.metaStore.put('a', 1001) + await db.metaStore.put('d', 1002) + await db.metaStore.put('b', 1003) + + await db.transaction(async (tx) => { + await expect( + db.metaStore.getAllKeys(tx, undefined, { ordered: true }), + ).resolves.toMatchObject(['a', 'b', 'd', 'e']) + await expect( + db.metaStore.getAllValues(tx, undefined, { ordered: true }), + ).resolves.toMatchObject([1001, 1003, 1002, 1000]) + + await db.metaStore.put('a', 1004, tx) + await db.metaStore.put('c', 999, tx) + + await expect( + db.metaStore.getAllKeys(tx, undefined, { ordered: true }), + ).resolves.toMatchObject(['a', 'b', 'c', 'd', 'e']) + await expect( + db.metaStore.getAllValues(tx, undefined, { ordered: true }), + ).resolves.toMatchObject([1004, 1003, 999, 1002, 1000]) + + await expect( + db.metaStore.getAllKeys(tx, undefined, { ordered: true, reverse: true }), + ).resolves.toMatchObject(['e', 'd', 'c', 'b', 'a']) + await expect( + db.metaStore.getAllValues(tx, undefined, { ordered: true, reverse: true }), + ).resolves.toMatchObject([1000, 1002, 999, 1003, 1004]) + }) + }) }) }) diff --git a/ironfish/src/storage/database/store.ts b/ironfish/src/storage/database/store.ts index eb3631e768..6b271806f1 100644 --- a/ironfish/src/storage/database/store.ts +++ b/ironfish/src/storage/database/store.ts @@ -5,6 +5,7 @@ import { UnwrapPromise } from '../../utils/types' import { IDatabaseTransaction } from './transaction' import { + DatabaseIteratorOptions, DatabaseKeyRange, DatabaseSchema, IDatabaseEncoding, @@ -51,35 +52,41 @@ export interface IDatabaseStore { getAll( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): Promise, SchemaValue]>> /* Get an [[`AsyncGenerator`]] that yields all of the key/value pairs in the IDatastore */ getAllIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator<[SchemaKey, SchemaValue]> /* Get an [[`AsyncGenerator`]] that yields all of the values in the IDatastore */ getAllValuesIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator> /* Get all of the values in the IDatastore */ getAllValues( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): Promise>> /* Get an [[`AsyncGenerator`]] that yields all of the keys in the IDatastore */ getAllKeysIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator> /* Get all of the keys in the IDatastore */ getAllKeys( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): Promise>> /** @@ -183,11 +190,13 @@ export abstract class DatabaseStore abstract getAllIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator<[SchemaKey, SchemaValue]> abstract getAll( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): Promise, SchemaValue]>> abstract getAllValuesIter( diff --git a/ironfish/src/storage/database/types.ts b/ironfish/src/storage/database/types.ts index 275a7b1f48..fe24949e95 100644 --- a/ironfish/src/storage/database/types.ts +++ b/ironfish/src/storage/database/types.ts @@ -14,6 +14,7 @@ export interface DatabaseKeyRange { export interface DatabaseIteratorOptions { reverse?: boolean limit?: number + ordered?: boolean } export type DatabaseKey = diff --git a/ironfish/src/storage/levelup/store.ts b/ironfish/src/storage/levelup/store.ts index e4f9a8a240..5857c50590 100644 --- a/ironfish/src/storage/levelup/store.ts +++ b/ironfish/src/storage/levelup/store.ts @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { LevelupDatabase } from './database' import { BufferSet } from 'buffer-map' +import FastPriorityQueue from 'fastpriorityqueue' import MurmurHash3 from 'imurmurhash' import { Assert } from '../../assert' import { AsyncUtils } from '../../utils/async' @@ -75,7 +76,7 @@ export class LevelupStore extends DatabaseStore, SchemaValue]> { if (keyRange) { keyRange = StorageUtils.addPrefixToRange(keyRange, this.prefixBuffer) @@ -84,6 +85,10 @@ export class LevelupStore extends DatabaseStore }>( + ({ key: a }, { key: b }) => + iteratorOptions?.reverse ? b.compare(a) < 0 : a.compare(b) < 0, + ) if (ENABLE_TRANSACTIONS && transaction) { Assert.isInstanceOf(transaction, LevelupTransaction) @@ -106,31 +111,57 @@ export class LevelupStore extends DatabaseStore] + if (iteratorOptions?.ordered) { + cacheElements.add({ key: key, value: value as SchemaValue }) + } else { + yield [this.decodeKey(key), value as SchemaValue] + } } } - for await (const [key, value] of this.db.getAllIter(keyRange, iterationOptions)) { + let nextCacheElement = cacheElements.peek() + + for await (const [key, value] of this.db.getAllIter(keyRange, iteratorOptions)) { + while ( + nextCacheElement && + (iteratorOptions?.reverse + ? key.compare(nextCacheElement.key) <= 0 + : key.compare(nextCacheElement.key) >= 0) + ) { + const element = cacheElements.poll() + Assert.isNotUndefined(element) + yield [this.decodeKey(element.key), element.value] + nextCacheElement = cacheElements.peek() + } + if (seen.has(key)) { continue + } else { + yield [this.decodeKey(key), this.valueEncoding.deserialize(value)] } + } - yield [this.decodeKey(key), this.valueEncoding.deserialize(value)] + while (!cacheElements.isEmpty()) { + const element = cacheElements.poll() + Assert.isNotUndefined(element) + yield [this.decodeKey(element.key), element.value] } } async getAll( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): Promise, SchemaValue]>> { - return AsyncUtils.materialize(this.getAllIter(transaction, keyRange)) + return AsyncUtils.materialize(this.getAllIter(transaction, keyRange, iteratorOptions)) } async *getAllValuesIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator> { - for await (const [, value] of this.getAllIter(transaction, keyRange)) { + for await (const [, value] of this.getAllIter(transaction, keyRange, iteratorOptions)) { yield value } } @@ -138,15 +169,17 @@ export class LevelupStore extends DatabaseStore>> { - return AsyncUtils.materialize(this.getAllValuesIter(transaction, keyRange)) + return AsyncUtils.materialize(this.getAllValuesIter(transaction, keyRange, iteratorOptions)) } async *getAllKeysIter( transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange, + iteratorOptions?: DatabaseIteratorOptions, ): AsyncGenerator> { - for await (const [key] of this.getAllIter(transaction, keyRange)) { + for await (const [key] of this.getAllIter(transaction, keyRange, iteratorOptions)) { yield key } } @@ -154,8 +187,9 @@ export class LevelupStore extends DatabaseStore>> { - return AsyncUtils.materialize(this.getAllKeysIter(transaction, keyRange)) + return AsyncUtils.materialize(this.getAllKeysIter(transaction, keyRange, iteratorOptions)) } async clear(transaction?: IDatabaseTransaction, keyRange?: DatabaseKeyRange): Promise { From caf0e5f05e7e0df63ab3c1a2a541571983ccb49b Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Wed, 21 Dec 2022 19:10:59 -0500 Subject: [PATCH 13/56] feat(cli): Show asset identifier for amount being paid instead of $IRON (#2800) --- ironfish-cli/src/commands/accounts/pay.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/pay.ts b/ironfish-cli/src/commands/accounts/pay.ts index 5d346be640..a7668b63b8 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/accounts/pay.ts @@ -183,7 +183,11 @@ export class Pay extends IronfishCommand { if (!flags.confirm) { this.log(` You are about to send: -${CurrencyUtils.renderIron(amount, true)} plus a transaction fee of ${CurrencyUtils.renderIron( +${CurrencyUtils.renderIron( + amount, + true, + assetIdentifier, +)} plus a transaction fee of ${CurrencyUtils.renderIron( fee, true, )} to ${to} from the account ${from} @@ -243,7 +247,7 @@ ${CurrencyUtils.renderIron(amount, true)} plus a transaction fee of ${CurrencyUt const transaction = result.content const recipients = transaction.receives.map((receive) => receive.publicAddress).join(', ') this.log(` -Sending ${CurrencyUtils.renderIron(amount, true)} to ${recipients} from ${ +Sending ${CurrencyUtils.renderIron(amount, true, assetIdentifier)} to ${recipients} from ${ transaction.fromAccountName } Transaction Hash: ${transaction.hash} From efa450713e62e6255592e4a66c4e60200cbbb994 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:47:39 -0800 Subject: [PATCH 14/56] removes balance repair from accounts:repair (#2802) now that an account's stored balance only reflects transactions on chain it is not feasible to recompute the balance only from an account's decrypted notes. we should not include spent notes in the balance, but we don't currently have an efficient way to determine if the note was spent in a transaction that is on the chain or in a transaction that is pending. we can still make some repairs to the spent attribute stored on the note, so the old implementation of `repairBalance` processes notes without updating balance and is renamed `repairNotes`. future changes to better support recomputing the balance: - add sequence and block hash to balance store to allow incremental updates to balance - add balance delta to transactions to avoid iterating over all notes and spends - add an index from sequence to transaction hash to support efficiently iterating over transactions in order - add an index from nullifier to transaction hash to support identifying whether a note was spent in an on-chain transaction --- ironfish-cli/src/commands/accounts/repair.ts | 44 ++------------------ 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/repair.ts b/ironfish-cli/src/commands/accounts/repair.ts index 420dfaa960..dc8fa2c022 100644 --- a/ironfish-cli/src/commands/accounts/repair.ts +++ b/ironfish-cli/src/commands/accounts/repair.ts @@ -1,16 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { - Account, - Assert, - Blockchain, - CurrencyUtils, - NodeUtils, - Wallet, - WalletDB, -} from '@ironfish/sdk' -import { BufferMap } from 'buffer-map' +import { Account, Assert, Blockchain, NodeUtils, Wallet, WalletDB } from '@ironfish/sdk' import { IronfishCommand } from '../../command' import { LocalFlags } from '../../flags' @@ -49,8 +40,8 @@ export default class Repair extends IronfishCommand { this.log('Repairing expired transactions') await this.repairTransactions(account, node.wallet.walletDb, node.chain) - this.log('Repairing balance') - await this.repairBalance(account, node.wallet.walletDb, node.chain) + this.log('Repairing notes') + await this.repairNotes(account, node.wallet.walletDb, node.chain) this.log('Repairing sequenceToNoteHash') await this.repairSequenceToNoteHash(account, node.wallet.walletDb) @@ -105,13 +96,11 @@ export default class Repair extends IronfishCommand { ) } - private async repairBalance( + private async repairNotes( account: Account, walletDb: WalletDB, chain: Blockchain, ): Promise { - const unconfirmedBalances = new BufferMap() - let noteUnspentMismatches = 0 for await (const decryptedNoteValue of account.getNotes()) { @@ -142,40 +131,15 @@ export default class Repair extends IronfishCommand { spent: true, }) } else if (!spent) { - const isExpired = - !transactionValue.sequence && - chain.verifier.isExpiredSequence( - transactionValue.transaction.expiration(), - chain.head.sequence, - ) - if (decryptedNoteValue.spent) { await walletDb.saveDecryptedNote(account, decryptedNoteValue.hash, { ...decryptedNoteValue, spent: false, }) } - - if (!isExpired) { - const assetIdentifier = decryptedNoteValue.note.assetIdentifier() - const unconfirmedBalance = unconfirmedBalances.get(assetIdentifier) ?? BigInt(0) - unconfirmedBalances.set( - assetIdentifier, - unconfirmedBalance + decryptedNoteValue.note.value(), - ) - } } } - for (const [assetIdentifier, unconfirmedBalance] of unconfirmedBalances.entries()) { - this.log( - `\tSaving new unconfirmed balance for ${assetIdentifier.toString( - 'hex', - )}: ${CurrencyUtils.renderIron(unconfirmedBalance)}`, - ) - await walletDb.saveUnconfirmedBalance(account, assetIdentifier, unconfirmedBalance) - } - this.log( `\tRepaired ${noteUnspentMismatches} decrypted notes incorrectly marked as unspent`, ) From 51e1dc589bc0a6dd4700021c5e935edb15647b10 Mon Sep 17 00:00:00 2001 From: ygao76 <4500784+ygao76@users.noreply.github.com> Date: Thu, 22 Dec 2022 11:03:06 -0800 Subject: [PATCH 15/56] Display Mints and Burns for accounts:transactions (#2803) --- ironfish-cli/src/commands/accounts/transactions.ts | 8 ++++++++ ironfish/src/rpc/routes/wallet/getTransactions.ts | 4 ++++ ironfish/src/rpc/routes/wallet/types.ts | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/ironfish-cli/src/commands/accounts/transactions.ts b/ironfish-cli/src/commands/accounts/transactions.ts index 1a486a41a2..2ff70f9487 100644 --- a/ironfish-cli/src/commands/accounts/transactions.ts +++ b/ironfish-cli/src/commands/accounts/transactions.ts @@ -75,6 +75,14 @@ export class TransactionsCommand extends IronfishCommand { header: 'Spends', minWidth: 5, }, + mintsCount: { + header: 'Mints', + minWidth: 5, + }, + burnsCount: { + header: 'Burns', + minWidth: 5, + }, expiration: { header: 'Expiration', }, diff --git a/ironfish/src/rpc/routes/wallet/getTransactions.ts b/ironfish/src/rpc/routes/wallet/getTransactions.ts index 7ae054586f..b5e7cb8013 100644 --- a/ironfish/src/rpc/routes/wallet/getTransactions.ts +++ b/ironfish/src/rpc/routes/wallet/getTransactions.ts @@ -22,6 +22,8 @@ export type GetAccountTransactionsResponse = { fee: string notesCount: number spendsCount: number + mintsCount: number + burnsCount: number expiration: number } @@ -44,6 +46,8 @@ export const GetAccountTransactionsResponseSchema: yup.ObjectSchema Date: Thu, 22 Dec 2022 15:37:31 -0500 Subject: [PATCH 16/56] Extend status column to 12 (#2805) --- ironfish-cli/src/commands/accounts/transactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ironfish-cli/src/commands/accounts/transactions.ts b/ironfish-cli/src/commands/accounts/transactions.ts index 2ff70f9487..6fcfa53ea3 100644 --- a/ironfish-cli/src/commands/accounts/transactions.ts +++ b/ironfish-cli/src/commands/accounts/transactions.ts @@ -49,7 +49,7 @@ export class TransactionsCommand extends IronfishCommand { { status: { header: 'Status', - minWidth: 11, + minWidth: 12, }, creator: { header: 'Creator', From 66d6505c00c9a8135c45048fa2bffcb7aebe0e3e Mon Sep 17 00:00:00 2001 From: Mira Yadav <40811052+mirayadav@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:13:40 -0500 Subject: [PATCH 17/56] Transaction Ordering By Timestamp (#2790) * Add support for ordered iteration in db and add timestamp index for transactions * Correct timestamp behavior for new connectTransaction and addPendingTransaction functions and reverse transaction order so most recent listed first * Replace sorted with ordered in function names * Rename get/loadOrderedTransactions to get/loadTransactionsByTime and use priority queue for cache elements during ordered iteration * Change U64 encoding to BE so keys encoded with it are iterated in sorting order * Fix merge conflict * Merge conflict fixes pt 2 * Fix lint --- .../src/commands/accounts/transactions.ts | 4 ++ ironfish/src/blockchain/blockchain.ts | 2 + .../src/rpc/routes/wallet/getTransactions.ts | 6 ++- ironfish/src/rpc/routes/wallet/types.ts | 2 + ironfish/src/storage/database/encoding.ts | 14 +++++++ ironfish/src/wallet/account.ts | 8 ++++ .../wallet/walletdb/transactionValue.test.ts | 4 ++ .../src/wallet/walletdb/transactionValue.ts | 8 +++- ironfish/src/wallet/walletdb/walletdb.ts | 42 +++++++++++++++++++ 9 files changed, 86 insertions(+), 4 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/transactions.ts b/ironfish-cli/src/commands/accounts/transactions.ts index 6fcfa53ea3..db63793588 100644 --- a/ironfish-cli/src/commands/accounts/transactions.ts +++ b/ironfish-cli/src/commands/accounts/transactions.ts @@ -47,6 +47,10 @@ export class TransactionsCommand extends IronfishCommand { CliUx.ux.table( [transaction], { + timestamp: { + header: 'Timestamp', + get: (transaction) => new Date(transaction.timestamp).toLocaleString(), + }, status: { header: 'Status', minWidth: 12, diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 5e4910a67e..51c50c1c28 100644 --- a/ironfish/src/blockchain/blockchain.ts +++ b/ironfish/src/blockchain/blockchain.ts @@ -1177,6 +1177,7 @@ export class Blockchain { sequence: number blockHash: Buffer previousBlockHash: Buffer + timestamp: Date }, void, unknown @@ -1202,6 +1203,7 @@ export class Blockchain { blockHash: header.hash, sequence: header.sequence, previousBlockHash: header.previousBlockHash, + timestamp: header.timestamp, } } } diff --git a/ironfish/src/rpc/routes/wallet/getTransactions.ts b/ironfish/src/rpc/routes/wallet/getTransactions.ts index b5e7cb8013..283ad91386 100644 --- a/ironfish/src/rpc/routes/wallet/getTransactions.ts +++ b/ironfish/src/rpc/routes/wallet/getTransactions.ts @@ -25,6 +25,7 @@ export type GetAccountTransactionsResponse = { mintsCount: number burnsCount: number expiration: number + timestamp: number } export const GetAccountTransactionsRequestSchema: yup.ObjectSchema = @@ -49,6 +50,7 @@ export const GetAccountTransactionsResponseSchema: yup.ObjectSchema => { - for await (const transaction of account.getTransactions()) { + for await (const transaction of account.getTransactionsByTime()) { if (request.closed) { break } diff --git a/ironfish/src/rpc/routes/wallet/types.ts b/ironfish/src/rpc/routes/wallet/types.ts index 4f7f24e96b..61dfcf05d3 100644 --- a/ironfish/src/rpc/routes/wallet/types.ts +++ b/ironfish/src/rpc/routes/wallet/types.ts @@ -14,6 +14,7 @@ export type RpcAccountTransaction = { mintsCount: number burnsCount: number expiration: number + timestamp: number } export type RpcAccountDecryptedNote = { @@ -38,5 +39,6 @@ export function serializeRpcAccountTransaction( mintsCount: transaction.transaction.mints.length, burnsCount: transaction.transaction.burns.length, expiration: transaction.transaction.expiration(), + timestamp: transaction.timestamp.getTime(), } } diff --git a/ironfish/src/storage/database/encoding.ts b/ironfish/src/storage/database/encoding.ts index b852a41828..99a79dbed9 100644 --- a/ironfish/src/storage/database/encoding.ts +++ b/ironfish/src/storage/database/encoding.ts @@ -175,7 +175,21 @@ export class BigIntLEEncoding implements IDatabaseEncoding { } } +export class U64Encoding implements IDatabaseEncoding { + serialize(value: number): Buffer { + const buffer = bufio.write(8) + buffer.writeBigU64BE(BigInt(value)) + return buffer.render() + } + + deserialize(buffer: Buffer): number { + const reader = bufio.read(buffer, true) + return Number(reader.readBigU64BE()) + } +} + export const BUFFER_TO_STRING_ENCODING = new BufferToStringEncoding() export const BUFFER_ENCODING = new BufferEncoding() export const U32_ENCODING = new U32Encoding() export const NULL_ENCODING = new NullEncoding() +export const U64_ENCODING = new U64Encoding() diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index ab392049e8..ee5950693e 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -124,11 +124,13 @@ export class Account { ): Promise { const balanceDeltas = new AssetBalanceDeltas() let submittedSequence: number | null = null + let timestamp = new Date() await this.walletDb.db.withTransaction(tx, async (tx) => { const transactionValue = await this.getTransaction(transaction.hash(), tx) if (transactionValue) { submittedSequence = transactionValue.submittedSequence + timestamp = transactionValue.timestamp } for (const decryptedNote of decryptedNotes) { @@ -178,6 +180,7 @@ export class Account { blockHash: blockHeader.hash, sequence: blockHeader.sequence, submittedSequence, + timestamp, }, tx, ) @@ -238,6 +241,7 @@ export class Account { blockHash: null, sequence: null, submittedSequence, + timestamp: new Date(), }, tx, ) @@ -360,6 +364,10 @@ export class Account { return this.walletDb.loadTransactions(this, tx) } + getTransactionsByTime(tx?: IDatabaseTransaction): AsyncGenerator> { + return this.walletDb.loadTransactionsByTime(this, tx) + } + getPendingTransactions( headSequence: number, tx?: IDatabaseTransaction, diff --git a/ironfish/src/wallet/walletdb/transactionValue.test.ts b/ironfish/src/wallet/walletdb/transactionValue.test.ts index f7e8ed375a..40277bcdd2 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.test.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.test.ts @@ -21,6 +21,7 @@ describe('TransactionValueEncoding', () => { const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: null, sequence: null, submittedSequence: null, @@ -39,6 +40,7 @@ describe('TransactionValueEncoding', () => { const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: null, sequence: null, submittedSequence: 123, @@ -57,6 +59,7 @@ describe('TransactionValueEncoding', () => { const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, submittedSequence: null, @@ -75,6 +78,7 @@ describe('TransactionValueEncoding', () => { const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, submittedSequence: 123, diff --git a/ironfish/src/wallet/walletdb/transactionValue.ts b/ironfish/src/wallet/walletdb/transactionValue.ts index 82f27b5b65..7edcbdc03c 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.ts @@ -7,6 +7,7 @@ import { Transaction } from '../../primitives' export interface TransactionValue { transaction: Transaction + timestamp: Date // These fields are populated once the transaction is on the main chain blockHash: Buffer | null sequence: number | null @@ -18,10 +19,11 @@ export interface TransactionValue { export class TransactionValueEncoding implements IDatabaseEncoding { serialize(value: TransactionValue): Buffer { - const { transaction, blockHash, sequence, submittedSequence } = value + const { transaction, blockHash, sequence, submittedSequence, timestamp } = value const bw = bufio.write(this.getSize(value)) bw.writeVarBytes(transaction.serialize()) + bw.writeU64(timestamp.getTime()) let flags = 0 flags |= Number(!!blockHash) << 0 @@ -45,6 +47,7 @@ export class TransactionValueEncoding implements IDatabaseEncoding + timestampToTransactionHash: IDatabaseStore<{ + key: [Account['prefix'], number] + value: TransactionHash + }> + constructor({ files, location, @@ -185,6 +191,12 @@ export class WalletDB { keyEncoding: new StringEncoding(), valueEncoding: NULL_ENCODING, }) + + this.timestampToTransactionHash = this.db.addStore({ + name: 'T', + keyEncoding: new PrefixEncoding(new BufferEncoding(), U64_ENCODING, 4), + valueEncoding: new BufferEncoding(), + }) } async open(): Promise { @@ -295,6 +307,11 @@ export class WalletDB { } await this.transactions.put([account.prefix, transactionHash], transactionValue, tx) + await this.timestampToTransactionHash.put( + [account.prefix, transactionValue.timestamp.getTime()], + transactionHash, + tx, + ) }) } @@ -303,11 +320,19 @@ export class WalletDB { transactionHash: Buffer, tx?: IDatabaseTransaction, ): Promise { + const transaction = await this.loadTransaction(account, transactionHash, tx) + Assert.isNotUndefined(transaction) + + await this.timestampToTransactionHash.del( + [account.prefix, transaction.timestamp.getTime()], + tx, + ) await this.transactions.del([account.prefix, transactionHash], tx) } async clearTransactions(account: Account, tx?: IDatabaseTransaction): Promise { await this.transactions.clear(tx, account.prefixRange) + await this.timestampToTransactionHash.clear(tx, account.prefixRange) } async clearSequenceToNoteHash(account: Account, tx?: IDatabaseTransaction): Promise { @@ -733,6 +758,7 @@ export class WalletDB { this.nullifierToNoteHash, this.pendingTransactionHashes, this.decryptedNotes, + this.timestampToTransactionHash, ] for (const [accountId] of await this.accountIdsToCleanup.getAll()) { @@ -753,4 +779,20 @@ export class WalletDB { await this.accountIdsToCleanup.del(accountId) } } + + async *loadTransactionsByTime( + account: Account, + tx?: IDatabaseTransaction, + ): AsyncGenerator { + for await (const transactionHash of this.timestampToTransactionHash.getAllValuesIter( + tx, + account.prefixRange, + { ordered: true, reverse: true }, + )) { + const transaction = await this.loadTransaction(account, transactionHash, tx) + Assert.isNotUndefined(transaction) + + yield transaction + } + } } From 7e50b05a0d3b8aa6314e2a5870f0cbe3e21a39da Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Sat, 24 Dec 2022 15:10:05 -0500 Subject: [PATCH 18/56] Change RPC note.amount to be value (#2806) * Change RPC note.amount to be value This renamed a field on the note incorrectly * Fixed lint --- ironfish-cli/src/commands/accounts/notes.ts | 4 ++-- ironfish/src/rpc/routes/wallet/getNotes.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/notes.ts b/ironfish-cli/src/commands/accounts/notes.ts index c822183705..2b633ba52d 100644 --- a/ironfish-cli/src/commands/accounts/notes.ts +++ b/ironfish-cli/src/commands/accounts/notes.ts @@ -36,9 +36,9 @@ export class NotesCommand extends IronfishCommand { CliUx.ux.table( [note], { - amount: { + value: { header: 'Amount ($IRON)', - get: (row) => CurrencyUtils.renderIron(row.amount), + get: (row) => CurrencyUtils.renderIron(row.value), }, memo: { header: 'Memo', diff --git a/ironfish/src/rpc/routes/wallet/getNotes.ts b/ironfish/src/rpc/routes/wallet/getNotes.ts index 383eee7bd2..22b48ec5f4 100644 --- a/ironfish/src/rpc/routes/wallet/getNotes.ts +++ b/ironfish/src/rpc/routes/wallet/getNotes.ts @@ -9,7 +9,7 @@ import { getAccount } from './utils' export type GetAccountNotesStreamRequest = { account?: string } export type GetAccountNotesStreamResponse = { - amount: string + value: string memo: string sender: string transactionHash: string @@ -26,7 +26,7 @@ export const GetAccountNotesStreamRequestSchema: yup.ObjectSchema = yup .object({ - amount: yup.string().defined(), + value: yup.string().defined(), memo: yup.string().trim().defined(), sender: yup.string().defined(), transactionHash: yup.string().defined(), @@ -49,7 +49,7 @@ router.register Date: Tue, 3 Jan 2023 12:06:00 -0500 Subject: [PATCH 19/56] Replace hex-array library with native (de)serialization (#2794) --- ironfish/package.json | 1 - ironfish/src/serde/BufferSerde.ts | 24 ++++--- ironfish/src/serde/Uint8ArraySerde.test.ts | 69 ------------------- ironfish/src/serde/Uint8ArraySerde.ts | 44 ------------ .../Uint8ArraySerde.test.ts.snap | 44 ------------ ironfish/src/serde/index.ts | 1 - ironfish/src/storage/database/encoding.ts | 28 +++----- ironfish/src/storage/levelup/store.ts | 4 +- ironfish/src/storage/levelup/transaction.ts | 10 +-- ironfish/src/typedefs/hex-array.d.ts | 11 --- yarn.lock | 5 -- 11 files changed, 33 insertions(+), 208 deletions(-) delete mode 100644 ironfish/src/serde/Uint8ArraySerde.test.ts delete mode 100644 ironfish/src/serde/Uint8ArraySerde.ts delete mode 100644 ironfish/src/serde/__snapshots__/Uint8ArraySerde.test.ts.snap delete mode 100644 ironfish/src/typedefs/hex-array.d.ts diff --git a/ironfish/package.json b/ironfish/package.json index 07030c4837..64eccd5660 100644 --- a/ironfish/package.json +++ b/ironfish/package.json @@ -30,7 +30,6 @@ "consola": "2.15.0", "date-fns": "2.16.1", "fastpriorityqueue": "0.7.1", - "hex-array": "1.0.0", "imurmurhash": "0.1.4", "level-errors": "2.0.1", "leveldown": "5.6.0", diff --git a/ironfish/src/serde/BufferSerde.ts b/ironfish/src/serde/BufferSerde.ts index 75f101a82d..52b669a6ff 100644 --- a/ironfish/src/serde/BufferSerde.ts +++ b/ironfish/src/serde/BufferSerde.ts @@ -2,28 +2,34 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Assert } from '../assert' import { Serde } from './Serde' -import Uint8ArraySerde from './Uint8ArraySerde' /** * A buffer serializer and equality checker */ export class BufferSerde implements Serde { - serde: Uint8ArraySerde - - constructor(readonly size: number) { - this.serde = new Uint8ArraySerde(size) - } + constructor(readonly size: number) {} equals(element1: Buffer, element2: Buffer): boolean { - return this.serde.equals(element1, element2) + return element1.equals(element2) } serialize(element: Buffer): string { - return this.serde.serialize(element) + Assert.isEqual( + element.length, + this.size, + `Attempting to serialize array with ${element.length} bytes, expected ${this.size}`, + ) + return element.toString('hex').toUpperCase() } deserialize(data: string): Buffer { - return Buffer.from(this.serde.deserialize(data)) + Assert.isEqual( + data.length, + this.size * 2, + `${JSON.stringify(data)} is not a ${this.size * 2}-character hex string`, + ) + return Buffer.from(data, 'hex') } } diff --git a/ironfish/src/serde/Uint8ArraySerde.test.ts b/ironfish/src/serde/Uint8ArraySerde.test.ts deleted file mode 100644 index 96793975c4..0000000000 --- a/ironfish/src/serde/Uint8ArraySerde.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -import Uint8ArraySerde from './Uint8ArraySerde' - -describe('Uint8ArraySerde', () => { - it('constructs a Uint8ArraySerde', () => { - expect(new Uint8ArraySerde(32)).toMatchSnapshot() - }) - it('compares two arrays as equal', () => { - const nullifier1 = new Uint8Array(32) - const nullifier2 = new Uint8Array(32) - nullifier1[0] = 1 - nullifier2[0] = 1 - expect(new Uint8ArraySerde(32).equals(nullifier1, nullifier2)).toBe(true) - }) - - it('compares two different arrays as not equal', () => { - const nullifier1 = new Uint8Array(32) - const nullifier2 = new Uint8Array(32) - nullifier2[0] = 1 - expect(new Uint8ArraySerde(32).equals(nullifier1, nullifier2)).toBe(false) - }) - it('throws error when passed incorrectly sized array', () => { - const nullifier1 = new Uint8Array(32) - const nullifier2 = new Uint8Array(32) - expect(() => - new Uint8ArraySerde(64).equals(nullifier1, nullifier2), - ).toThrowErrorMatchingInlineSnapshot(`"Attempting to compare inappropriately sized array"`) - }) - - it('serializes and deserializes an equal array', () => { - const serde = new Uint8ArraySerde(32) - const nullifier = new Uint8Array(32) - nullifier.set([8, 18, 24, 199, 255, 1, 0, 127]) - const serialized = serde.serialize(nullifier) - expect(serialized).toMatchInlineSnapshot( - `"081218C7FF01007F000000000000000000000000000000000000000000000000"`, - ) - const deserialized = serde.deserialize(serialized) - expect(deserialized).toMatchSnapshot() - expect(serde.equals(nullifier, deserialized)).toBe(true) - expect(serde.serialize(deserialized)).toEqual(serialized) - }) - - it('throws an error when trying to serialize an inappropriate array', () => { - expect(() => - new Uint8ArraySerde(32).serialize(new Uint8Array(10)), - ).toThrowErrorMatchingInlineSnapshot( - `"Attempting to serialize array with 10 bytes, expected 32"`, - ) - }) - - it('throws an error when trying to deserialize an inappropriate value', () => { - expect(() => new Uint8ArraySerde(32).deserialize('ABC')).toThrowErrorMatchingInlineSnapshot( - `""ABC" is not a 64-character hex string"`, - ) - expect(() => - // @ts-expect-error Argument of type '{ bad: string; }' is not assignable to parameter of type 'string'. - new Uint8ArraySerde(32).deserialize({ bad: 'object' }), - ).toThrowErrorMatchingInlineSnapshot(`"{"bad":"object"} is not a 64-character hex string"`) - expect(() => - new Uint8ArraySerde(32).deserialize( - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag', - ), - ).toThrowErrorMatchingInlineSnapshot(`"unexpected character"`) - }) -}) diff --git a/ironfish/src/serde/Uint8ArraySerde.ts b/ironfish/src/serde/Uint8ArraySerde.ts deleted file mode 100644 index 49e92e4ed8..0000000000 --- a/ironfish/src/serde/Uint8ArraySerde.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -import hexarray from 'hex-array' -import { zip } from 'lodash' -import { Serde } from './Serde' - -/** - * General-purpose uint8array serializer and equality checker - */ -export default class Uint8ArraySerde implements Serde { - constructor(readonly size: number) {} - equals(element1: Uint8Array, element2: Uint8Array): boolean { - if (element1.length !== this.size) { - throw new Error('Attempting to compare inappropriately sized array') - } - if (element1.length !== element2.length) { - return false - } - for (const [first, second] of zip(element1, element2)) { - if (first !== second) { - return false - } - } - return true - } - - serialize(element: Uint8Array): string { - if (element.length !== this.size) { - throw new Error( - `Attempting to serialize array with ${element.length} bytes, expected ${this.size}`, - ) - } - return hexarray.toString(element) - } - - deserialize(data: string): Uint8Array { - if (typeof data !== 'string' || data.length !== this.size * 2) { - throw new Error(`${JSON.stringify(data)} is not a ${this.size * 2}-character hex string`) - } - return hexarray.fromString(data) - } -} diff --git a/ironfish/src/serde/__snapshots__/Uint8ArraySerde.test.ts.snap b/ironfish/src/serde/__snapshots__/Uint8ArraySerde.test.ts.snap deleted file mode 100644 index e182645342..0000000000 --- a/ironfish/src/serde/__snapshots__/Uint8ArraySerde.test.ts.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Uint8ArraySerde constructs a Uint8ArraySerde 1`] = ` -Uint8ArraySerde { - "size": 32, -} -`; - -exports[`Uint8ArraySerde serializes and deserializes an equal array 2`] = ` -Uint8Array [ - 8, - 18, - 24, - 199, - 255, - 1, - 0, - 127, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -] -`; diff --git a/ironfish/src/serde/index.ts b/ironfish/src/serde/index.ts index c8491df20b..1ec5df0ad1 100644 --- a/ironfish/src/serde/index.ts +++ b/ironfish/src/serde/index.ts @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ export { default as StringSerde } from './StringSerde' -export { default as Uint8ArraySerde } from './Uint8ArraySerde' export * from './BlockTemplateSerde' export * from './BufferSerde' export * from './serdeInstances' diff --git a/ironfish/src/storage/database/encoding.ts b/ironfish/src/storage/database/encoding.ts index 99a79dbed9..cee8d11031 100644 --- a/ironfish/src/storage/database/encoding.ts +++ b/ironfish/src/storage/database/encoding.ts @@ -3,8 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import bufio from 'bufio' -import hexArray from 'hex-array' -import { IJSON, IJsonSerializable, Serde } from '../../serde' +import { IJSON, IJsonSerializable } from '../../serde' import { BigIntUtils } from '../../utils' import { IDatabaseEncoding } from './types' @@ -151,20 +150,6 @@ export class NullableStringEncoding implements IDatabaseEncoding export class ArrayEncoding extends JsonEncoding {} -export default class BufferToStringEncoding implements Serde { - serialize(element: Buffer): string { - return hexArray.toString(element) - } - - deserialize(data: string): Buffer { - return Buffer.from(hexArray.fromString(data)) - } - - equals(): boolean { - throw new Error('You should never use this') - } -} - export class BigIntLEEncoding implements IDatabaseEncoding { serialize(value: bigint): Buffer { return BigIntUtils.toBytesLE(value) @@ -188,7 +173,16 @@ export class U64Encoding implements IDatabaseEncoding { } } -export const BUFFER_TO_STRING_ENCODING = new BufferToStringEncoding() +export class BufferToStringEncoding { + static serialize(element: Buffer): string { + return element.toString('hex') + } + + static deserialize(data: string): Buffer { + return Buffer.from(data, 'hex') + } +} + export const BUFFER_ENCODING = new BufferEncoding() export const U32_ENCODING = new U32Encoding() export const NULL_ENCODING = new NullEncoding() diff --git a/ironfish/src/storage/levelup/store.ts b/ironfish/src/storage/levelup/store.ts index 5857c50590..d1cc7b2459 100644 --- a/ironfish/src/storage/levelup/store.ts +++ b/ironfish/src/storage/levelup/store.ts @@ -18,7 +18,7 @@ import { SchemaKey, SchemaValue, } from '../database' -import { BUFFER_TO_STRING_ENCODING } from '../database/encoding' +import { BufferToStringEncoding } from '../database/encoding' import { StorageUtils } from '../database/utils' import { LevelupTransaction } from './transaction' @@ -95,7 +95,7 @@ export class LevelupStore extends DatabaseStore Date: Tue, 3 Jan 2023 13:44:14 -0500 Subject: [PATCH 20/56] Replace all fixed sized BigInt serialization and deserialization with bufio (#2781) --- ironfish/src/blockchain/database/headers.ts | 4 +-- ironfish/src/mining/pool.ts | 8 +++-- ironfish/src/mining/soloMiner.ts | 2 +- ironfish/src/network/utils/serializers.ts | 4 +-- ironfish/src/primitives/blockheader.ts | 2 +- ironfish/src/primitives/target.ts | 4 ++- ironfish/src/serde/BlockTemplateSerde.ts | 10 +++--- ironfish/src/serde/PartialHeaderSerde.ts | 4 +-- ironfish/src/utils/bigint.test.ts | 8 ++--- ironfish/src/utils/bigint.ts | 36 ++++++++----------- .../src/workerPool/tasks/createMinersFee.ts | 6 ++-- .../src/workerPool/tasks/createTransaction.ts | 8 ++--- 12 files changed, 47 insertions(+), 49 deletions(-) diff --git a/ironfish/src/blockchain/database/headers.ts b/ironfish/src/blockchain/database/headers.ts index 199de022d5..d94c615edf 100644 --- a/ironfish/src/blockchain/database/headers.ts +++ b/ironfish/src/blockchain/database/headers.ts @@ -27,7 +27,7 @@ export class HeaderEncoding implements IDatabaseEncoding { bw.writeHash(value.header.noteCommitment) bw.writeU32(value.header.noteSize) bw.writeHash(value.header.transactionCommitment) - bw.writeBigU256(value.header.target.asBigInt()) + bw.writeBigU256BE(value.header.target.asBigInt()) bw.writeBigU64(value.header.randomness) bw.writeU64(value.header.timestamp.getTime()) @@ -46,7 +46,7 @@ export class HeaderEncoding implements IDatabaseEncoding { const noteCommitment = reader.readHash() const noteSize = reader.readU32() const transactionCommitment = reader.readHash() - const target = new Target(reader.readBigU256()) + const target = new Target(reader.readBigU256BE()) const randomness = reader.readBigU64() const timestamp = reader.readU64() const graffiti = reader.readBytes(32) diff --git a/ironfish/src/mining/pool.ts b/ironfish/src/mining/pool.ts index 4389ecedad..4834dac104 100644 --- a/ironfish/src/mining/pool.ts +++ b/ironfish/src/mining/pool.ts @@ -86,7 +86,7 @@ export class MiningPool { this.difficulty = BigInt(this.config.get('poolDifficulty')) const basePoolTarget = Target.fromDifficulty(this.difficulty).asBigInt() - this.target = BigIntUtils.toBytesBE(basePoolTarget, 32) + this.target = BigIntUtils.writeBigU256BE(basePoolTarget) this.connectTimeout = null this.connectWarned = false @@ -365,7 +365,9 @@ export class MiningPool { // Target might be the same if there is a slight timing issue or if the block is at max target. // In this case, it is detrimental to send out new work as it will needlessly reset miner's search // space, resulting in duplicated work. - const existingTarget = BigIntUtils.fromBytes(Buffer.from(latestBlock.header.target, 'hex')) + const existingTarget = BigIntUtils.fromBytesBE( + Buffer.from(latestBlock.header.target, 'hex'), + ) if (newTarget.asBigInt() === existingTarget) { this.logger.debug( `New target ${newTarget.asBigInt()} is the same as the existing target, no need to send out new work.`, @@ -373,7 +375,7 @@ export class MiningPool { return } - latestBlock.header.target = BigIntUtils.toBytesBE(newTarget.asBigInt(), 32).toString('hex') + latestBlock.header.target = BigIntUtils.writeBigU256BE(newTarget.asBigInt()).toString('hex') latestBlock.header.timestamp = newTime.getTime() this.distributeNewBlock(latestBlock) diff --git a/ironfish/src/mining/soloMiner.ts b/ironfish/src/mining/soloMiner.ts index f434d76a27..504e989b8b 100644 --- a/ironfish/src/mining/soloMiner.ts +++ b/ironfish/src/mining/soloMiner.ts @@ -282,7 +282,7 @@ export class MiningSoloMiner { ), ) - latestBlock.header.target = BigIntUtils.toBytesBE(newTarget.asBigInt(), 32).toString('hex') + latestBlock.header.target = BigIntUtils.writeBigU256BE(newTarget.asBigInt()).toString('hex') latestBlock.header.timestamp = newTime.getTime() this.startNewWork(latestBlock) diff --git a/ironfish/src/network/utils/serializers.ts b/ironfish/src/network/utils/serializers.ts index 1130512ece..d95564e094 100644 --- a/ironfish/src/network/utils/serializers.ts +++ b/ironfish/src/network/utils/serializers.ts @@ -25,7 +25,7 @@ export function writeBlockHeader( bw.writeHash(header.previousBlockHash) bw.writeHash(header.noteCommitment) bw.writeHash(header.transactionCommitment) - bw.writeBigU256(header.target.targetValue) + bw.writeBigU256BE(header.target.targetValue) bw.writeBigU64(header.randomness) bw.writeU64(header.timestamp.getTime()) @@ -39,7 +39,7 @@ export function readBlockHeader(reader: bufio.BufferReader): BlockHeader { const previousBlockHash = reader.readHash() const noteCommitment = reader.readHash() const transactionCommitment = reader.readHash() - const target = reader.readBigU256() + const target = reader.readBigU256BE() const randomness = reader.readBigU64() const timestamp = reader.readU64() const graffiti = reader.readBytes(GRAFFITI_SIZE) diff --git a/ironfish/src/primitives/blockheader.ts b/ironfish/src/primitives/blockheader.ts index a46b822041..912b519333 100644 --- a/ironfish/src/primitives/blockheader.ts +++ b/ironfish/src/primitives/blockheader.ts @@ -220,7 +220,7 @@ export class BlockHeader { const partialHeader = this.serializePartial() const headerBytes = Buffer.alloc(partialHeader.byteLength + 8) - headerBytes.set(BigIntUtils.toBytesBE(this.randomness, 8)) + headerBytes.set(BigIntUtils.writeBigU64BE(this.randomness)) headerBytes.set(partialHeader, 8) const hash = hashBlockHeader(headerBytes) diff --git a/ironfish/src/primitives/target.ts b/ironfish/src/primitives/target.ts index 0a6e031bf6..9bd325452f 100644 --- a/ironfish/src/primitives/target.ts +++ b/ironfish/src/primitives/target.ts @@ -31,7 +31,9 @@ export class Target { this.targetValue = BigInt(0) } else { const candidate = - targetValue instanceof Buffer ? BigIntUtils.fromBytes(targetValue) : BigInt(targetValue) + targetValue instanceof Buffer + ? BigIntUtils.fromBytesBE(targetValue) + : BigInt(targetValue) if (candidate > MAX_256_BIT_NUM) { throw new Error('Target value exceeds max target') diff --git a/ironfish/src/serde/BlockTemplateSerde.ts b/ironfish/src/serde/BlockTemplateSerde.ts index 6e67d9395f..231ee1ab24 100644 --- a/ironfish/src/serde/BlockTemplateSerde.ts +++ b/ironfish/src/serde/BlockTemplateSerde.ts @@ -34,13 +34,15 @@ export class BlockTemplateSerde { previousBlockHash: block.header.previousBlockHash.toString('hex'), noteCommitment: block.header.noteCommitment.toString('hex'), transactionCommitment: block.header.transactionCommitment.toString('hex'), - target: BigIntUtils.toBytesBE(block.header.target.asBigInt(), 32).toString('hex'), - randomness: BigIntUtils.toBytesBE(block.header.randomness, 8).toString('hex'), + target: BigIntUtils.writeBigU256BE(block.header.target.asBigInt()).toString('hex'), + randomness: BigIntUtils.writeBigU64BE(block.header.randomness).toString('hex'), timestamp: block.header.timestamp.getTime(), graffiti: block.header.graffiti.toString('hex'), } const previousBlockInfo = { - target: BigIntUtils.toBytesBE(previousBlock.header.target.asBigInt(), 32).toString('hex'), + target: BigIntUtils.writeBigU256BE(previousBlock.header.target.asBigInt()).toString( + 'hex', + ), timestamp: previousBlock.header.timestamp.getTime(), } @@ -60,7 +62,7 @@ export class BlockTemplateSerde { noteHasher.deserialize(Buffer.from(blockTemplate.header.noteCommitment, 'hex')), Buffer.from(blockTemplate.header.transactionCommitment, 'hex'), new Target(Buffer.from(blockTemplate.header.target, 'hex')), - BigIntUtils.fromBytes(Buffer.from(blockTemplate.header.randomness, 'hex')), + BigIntUtils.fromBytesBE(Buffer.from(blockTemplate.header.randomness, 'hex')), new Date(blockTemplate.header.timestamp), Buffer.from(blockTemplate.header.graffiti, 'hex'), ) diff --git a/ironfish/src/serde/PartialHeaderSerde.ts b/ironfish/src/serde/PartialHeaderSerde.ts index 71a5e7a76c..12f1679804 100644 --- a/ironfish/src/serde/PartialHeaderSerde.ts +++ b/ironfish/src/serde/PartialHeaderSerde.ts @@ -5,7 +5,6 @@ import bufio from 'bufio' import { NoteEncryptedHash } from '../primitives/noteEncrypted' import { Target } from '../primitives/target' -import { BigIntUtils } from '../utils' export default class PartialBlockHeaderSerde { static serialize(header: PartialBlockHeader): Buffer { @@ -14,8 +13,7 @@ export default class PartialBlockHeaderSerde { bw.writeHash(header.previousBlockHash) bw.writeHash(header.noteCommitment) bw.writeHash(header.transactionCommitment) - // TODO: Change to little-endian for consistency, since other non-bigint numbers are serialized as little-endian. - bw.writeBytes(BigIntUtils.toBytesBE(header.target.asBigInt(), 32)) + bw.writeBigU256BE(header.target.asBigInt()) bw.writeU64(header.timestamp.getTime()) bw.writeBytes(header.graffiti) return bw.render() diff --git a/ironfish/src/utils/bigint.test.ts b/ironfish/src/utils/bigint.test.ts index 57a5d88d8f..ce2312bb95 100644 --- a/ironfish/src/utils/bigint.test.ts +++ b/ironfish/src/utils/bigint.test.ts @@ -17,8 +17,8 @@ describe('BigIntUtils', () => { ] for (const candidate of bigints) { - const bytes = BigIntUtils.toBytes(candidate) - const back = BigIntUtils.fromBytes(bytes) + const bytes = BigIntUtils.toBytesBE(candidate) + const back = BigIntUtils.fromBytesBE(bytes) expect(back).toEqual(candidate) } }) @@ -26,7 +26,7 @@ describe('BigIntUtils', () => { it('can convert to a little-endian representation', () => { const bigint = BigInt(258) - const bigintBuffer = BigIntUtils.toBytesLE(bigint, 2) + const bigintBuffer = BigIntUtils.toBytesLE(bigint) const buffer = Buffer.alloc(2) buffer.writeUInt16LE(Number(bigint)) @@ -38,7 +38,7 @@ describe('BigIntUtils', () => { }) it('converts empty array to 0', () => { - expect(BigIntUtils.fromBytes(Buffer.from([]))).toEqual(BigInt(0)) + expect(BigIntUtils.fromBytesBE(Buffer.from([]))).toEqual(BigInt(0)) }) it('divides bigint', () => { diff --git a/ironfish/src/utils/bigint.ts b/ironfish/src/utils/bigint.ts index 831e3b95c6..390c77bdaf 100644 --- a/ironfish/src/utils/bigint.ts +++ b/ironfish/src/utils/bigint.ts @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import bufio from 'bufio' + /** * Accept two bigints and return the larger of the two, * in the case of equality, b is returned @@ -40,7 +42,7 @@ function min(a: bigint, b: bigint): bigint { * * Sorry. */ -function fromBytes(bytes: Buffer): bigint { +function fromBytesBE(bytes: Buffer): bigint { if (bytes.length === 0) { return BigInt(0) } @@ -59,7 +61,7 @@ function fromBytes(bytes: Buffer): bigint { } function fromBytesLE(bytes: Buffer): bigint { - return fromBytes(bytes.reverse()) + return fromBytesBE(bytes.reverse()) } /** @@ -69,7 +71,7 @@ function fromBytesLE(bytes: Buffer): bigint { * incoming bigint is non-negative, and fix the places where we're calling * it with a negative number (at least one place is miners fee serialization) */ -function toBytes(value: bigint): Buffer { +function toBytesBE(value: bigint): Buffer { let hex = value.toString(16) if (hex.length % 2) { hex = '0' + hex @@ -94,25 +96,16 @@ function toBytes(value: bigint): Buffer { * incoming bigint is non-negative, and fix the places where we're calling * it with a negative number (at least one place is miners fee serialization) */ -function toBytesLE(value: bigint, size?: number): Buffer { - return toBytesBE(value, size).reverse() +function toBytesLE(value: bigint): Buffer { + return toBytesBE(value).reverse() } -/** - * TODO: Handle negative numbers, or add an assertion that the - * incoming bigint is non-negative, and fix the places where we're calling - * it with a negative number (at least one place is miners fee serialization) - */ -function toBytesBE(value: bigint, size?: number): Buffer { - const bytes = toBytes(value) - - if (size) { - const result = Buffer.alloc(size) - result.set(bytes, size - bytes.length) - return result - } +function writeBigU64BE(value: bigint): Buffer { + return bufio.write(8).writeBigU64BE(value).render() +} - return bytes +function writeBigU256BE(value: bigint): Buffer { + return bufio.write(32).writeBigU256BE(value).render() } /** @@ -136,8 +129,7 @@ function tryParse(value: string): [bigint, null] | [null, Error] { } export const BigIntUtils = { - toBytes, - fromBytes, + fromBytesBE, fromBytesLE, toBytesBE, toBytesLE, @@ -145,4 +137,6 @@ export const BigIntUtils = { min, divide, tryParse, + writeBigU64BE, + writeBigU256BE, } diff --git a/ironfish/src/workerPool/tasks/createMinersFee.ts b/ironfish/src/workerPool/tasks/createMinersFee.ts index 984721ec45..7d5d4e0e6b 100644 --- a/ironfish/src/workerPool/tasks/createMinersFee.ts +++ b/ironfish/src/workerPool/tasks/createMinersFee.ts @@ -21,7 +21,7 @@ export class CreateMinersFeeRequest extends WorkerMessage { serialize(): Buffer { const bw = bufio.write(this.getSize()) - bw.writeVarBytes(BigIntUtils.toBytes(this.amount)) + bw.writeVarBytes(BigIntUtils.toBytesBE(this.amount)) bw.writeVarString(this.memo, 'utf8') bw.writeVarString(this.spendKey, 'utf8') return bw.render() @@ -29,7 +29,7 @@ export class CreateMinersFeeRequest extends WorkerMessage { static deserialize(jobId: number, buffer: Buffer): CreateMinersFeeRequest { const reader = bufio.read(buffer, true) - const amount = BigIntUtils.fromBytes(reader.readVarBytes()) + const amount = BigIntUtils.fromBytesBE(reader.readVarBytes()) const memo = reader.readVarString('utf8') const spendKey = reader.readVarString('utf8') return new CreateMinersFeeRequest(amount, memo, spendKey, jobId) @@ -37,7 +37,7 @@ export class CreateMinersFeeRequest extends WorkerMessage { getSize(): number { return ( - bufio.sizeVarBytes(BigIntUtils.toBytes(this.amount)) + + bufio.sizeVarBytes(BigIntUtils.toBytesBE(this.amount)) + bufio.sizeVarString(this.memo, 'utf8') + bufio.sizeVarString(this.spendKey, 'utf8') ) diff --git a/ironfish/src/workerPool/tasks/createTransaction.ts b/ironfish/src/workerPool/tasks/createTransaction.ts index 3d550b7c68..3ad21d86d0 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.ts @@ -126,7 +126,7 @@ export class CreateTransactionRequest extends WorkerMessage { static deserialize(jobId: number, buffer: Buffer): CreateTransactionRequest { const reader = bufio.read(buffer, true) const spendKey = reader.readVarString() - const transactionFee = BigIntUtils.fromBytes(reader.readVarBytes()) + const transactionFee = BigIntUtils.fromBytesBE(reader.readVarBytes()) const expiration = reader.readU64() const spendsLength = reader.readU64() @@ -151,7 +151,7 @@ export class CreateTransactionRequest extends WorkerMessage { const receives = [] for (let i = 0; i < receivesLength; i++) { const publicAddress = reader.readVarString() - const amount = BigIntUtils.fromBytes(reader.readVarBytes()) + const amount = BigIntUtils.fromBytesBE(reader.readVarBytes()) const memo = reader.readVarString('utf8') const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) receives.push({ publicAddress, amount, memo, assetIdentifier }) @@ -161,7 +161,7 @@ export class CreateTransactionRequest extends WorkerMessage { const mints = [] for (let i = 0; i < mintsLength; i++) { const asset = Asset.deserialize(reader.readBytes(ASSET_LENGTH)) - const value = BigIntUtils.fromBytes(reader.readVarBytes()) + const value = BigIntUtils.fromBytesBE(reader.readVarBytes()) mints.push({ asset, value }) } @@ -169,7 +169,7 @@ export class CreateTransactionRequest extends WorkerMessage { const burns = [] for (let i = 0; i < burnsLength; i++) { const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) - const value = BigIntUtils.fromBytes(reader.readVarBytes()) + const value = BigIntUtils.fromBytesBE(reader.readVarBytes()) burns.push({ assetIdentifier, value }) } From c3e4b8843dcbfb49f3db1cdfb1ebd8b2fba6d3b9 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Tue, 3 Jan 2023 13:46:14 -0500 Subject: [PATCH 21/56] Remove buildRawTransaction() in blockchain.test (#2801) * Remove buildRawTransaction() in blockchain.test * Optimize test fixture * REmove fixture --- .../__fixtures__/blockchain.test.ts.fixture | 94 +++++++++++++------ ironfish/src/blockchain/blockchain.test.ts | 88 +++++++++-------- 2 files changed, 110 insertions(+), 72 deletions(-) diff --git a/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture b/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture index aed0464a78..842ef24df3 100644 --- a/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture +++ b/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture @@ -2013,14 +2013,14 @@ ] } ], - "Blockchain asset updates when spending and burning the same note in a block throws an exception": [ + "Blockchain asset updates when spending and burning the same note in a block fails validation as double spend when spend and burn the same note": [ { - "id": "1e2a5afe-1104-4056-8f81-8a1e2e3cacae", + "id": "98e57449-b702-4b9c-af09-b723d18a2ed3", "name": "test", - "spendingKey": "da9cb52ae61f08bdeb7859ac794ce85a213ae1607f6028dd2f61f4ce8891fd60", - "incomingViewKey": "1bae8d41797b3efe01408f19399499139555fc6fea0fead6203d30fa56d68601", - "outgoingViewKey": "835da9b208d71500fe640c531e085fc9e289055b38c72c33c0ec59fd91ac6c27", - "publicAddress": "4be864d2e03585153eb8a32719fa107b38b88b474e0f0507fcc86e40c188a997" + "spendingKey": "e8b4ba8c402644bf740ec1fabf289e10664ac3ee6993fb212c72da99ade9b864", + "incomingViewKey": "4fadf1d75b4b9840bb74d4325fc2087c19f47e67d4dd183025bffc901add6207", + "outgoingViewKey": "fdd6fdf0677c0eccdc2c90d6c84ca2979b1b1611eb8c9955da2944cfab29ea2e", + "publicAddress": "92156201b114dcfa2c5fa6923887f9a96517dc03ba2250ce4d1a6cc1437002a6" }, { "header": { @@ -2028,15 +2028,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:3iV4QgHYNAo19rPkXC9ZcTo2ees4Ej3aM30SBdcxog8=" + "data": "base64:eJqME13Ca5F8+BB7PB4/hjrxT0/3tXvsb84nFXQOxGs=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:hLPrCCj0QNNoJacXrYIDQ8ORzqdW8UYZdFbzffmHcH8=" + "data": "base64:lIIiSf8MDjeosG6sB9zXb+zPim83QkbNtYqXRKhOKNo=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470861502, + "timestamp": 1671661461224, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -2044,71 +2044,111 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA7mfMuujrTOWqm8iWRpG87ZhZkBGcgg/QV2mHxXpNMpqDehviNk4gw6p2pdsGOcexAQ2eeaPIZFY1Sz8vt0FDyMuw8LfD1ds0lWsRZwPyjnqTh3xKNAP1GniviCzRt7Y3fiHau95q+u+uODwN0ZTbfDiXSBo6+l7enDeQVjlp7DgYV5xYvnBllYXH4Jg2kn8MrrijrYyWgqHA5JNt72IO5BLUHDynGo7bE8BQVea/F7+Ad7zG4AvnYLuDKIZ1yJdSgbdc4t+QP53+SUKqILlXnhn8RMWxL5Hx2NKBrUGTl1Lz0DLwcQfeBzuO3XH4OTZoABpfzD9gPJILSBSenX5bWC8MovQ4tP7HyvfMUPC0sGoj5mlg9G/3b9X4/rfKcpNTkfC1JR0FoxBpBod/jUBx6VU6msd6qAhGaevF25Py4Ab1vwfl8emond/KK7o4W0ywN30XmU85ODJU6nTaoqUneohhjsQlx503pE52KA+4nYgVow1/uLIo7XvrXd9KWjClOWU9/m4u6mj1MY/HPNn2JMElZwxElXx578PPWH8wAHgYp0Xbhn2gudeEtYm/ZdFQY+W7iMW4FZyrX+HqR39AnePS+2fV6Gz7bG8M+fdDI9vYmDsrdlPCBElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJ73wdgX9HrOGiGxpGYPCKRu4gkwUyY4J0K1UBTe3Yawcf1tqCRQ5mXCubwcDbPXzVLCuCmmlHn8uAKk6HQyOAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAACPdnKPyLjtyttfBXhpWr9/QC6l8gKqPXZIgw59DZi4yWRGJQKnAatX8ce2rsePCIrYobiCfWmREYMhiVFdqGeF0Q3h4vOpSIkn+e25Oz2iC2bsOisYkPJm9fuW9QHSyhKsOLlQKjjwQlK1uRkX32qcte77yXBg4P4ZlPXGyRGcMKtE9TYWAyufAvCEoKsyX/teOEjQl86GVtKugSKCvzgcWkd+WQtRiDMmpCjlDiMgaiJXf2jmQiSKoVFNQPX9lfSl2FqiSYZkznVNOMtYP1KpzJHiigmTWkAUDrl05PUdQuARq5EpM3C143/0KvLLf8VxHqAXSHnfRZEFORaCAG3QXTpxCOft10GwCiEPxN1/N+Xi19kbYF5n0asjKkalIGmji7r3ixip9cRCIkorU6rovoO1LH8Ax3BV020akBIIJkrzojvkHmKCS02BunV6+6iq9YQRElgkCjSgtaWCsnhGrj87lrLxoCaeLlMEu+8AU/0Ya08AKK3VheVK2JfZ8ksM4BINN1MO2qmTYXPiBxdxkmMttXzdg4Mhr+foYTP807smNggnsfZRAoc8ynEGISCPk9w2nKvUweIKzEBnNxqotLQesNMn2WglAI2q7mwuJIVyroG/3lXElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwPZ8fE+tqq1b70ETvSUZppXz19BN2qsRfFK2KZgudja4uMKZUM1FJz9Aj+CoHzYUz1/JaCzCzwKsnTfkadGbtCg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "0480F5D434AE4854FFCB39AF559F6115CCE6768922EEE3B4E3C1A1CD037401B7", + "previousBlockHash": "41FE487B7D30075115529100462179213BF4D59AAB4021279133682428B4122B", "noteCommitment": { "type": "Buffer", - "data": "base64:ZMAci32TuCAi+7ZfnpJrnq8MFqrfxijpJGwCUtqgMyE=" + "data": "base64:27LBzlG+w0ZBskZyGOmmHdl5ED2Fo8E4U5jlo7oF/Vs=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:1V/tlwSBsa5r0zYtr2WJgyT7JUKGhmWJQPPc/5/pk1A=" + "data": "base64:6R4Gcolm24mon8iOvaxWB6GckgKnRvi9WGDZL967Ep4=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470862341, + "timestamp": 1671661464179, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 6, + "noteSize": 8, "work": "0" }, "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcxd/vNt1Des2Wok1igMTXhAtwhKVyUcUqxMgFAJLRpyO1CpzqEB5x9qxuLg4Ouuzjd2dLu5ThAQYdyzeApWHagOotfwTFkgab7BEbc0BNS6TMHm9P6mOI1VQ1IS5VbPTZ+k9YBExWOAZNBXAKhnRRWIin+g2Ei07SuRtfwyeGHcNk1f30VRpQCujiczRvSEaazhMiC5A7TcsGkqkyTnATrB3YdA7WKxIIx/4Uri8XK6LfWK6GmrZD/vj00jSp6vlEji6ksinTCY8LVCOUt5TiIBTLlrlmR+PjR/nlimCbtjI1Zqd1v7Di6JnqRAh8v9zeI/WobBIK9H6Q2D/VIk/oZPEAMK/28Ak0jLplS2FYti4qJWQwb3aYFyade7ATSZH4v+B38mFsF/cswbBfuzzzhWXU9YkG2vttM1xaCEriOQdN9RFhDHp5644SNWgAEmC+u7i2qDBk14lsW9NzKjsg4mwmiCZ1bx0kpe9EMW5XJ09uHTpIQEnJjQit982vYhYl2HSoMDCMbKswmLE5xxCwjCrHw2cwpLVU17tmoXaU8ZaNFSA3IQuy6fp1rmYj4s/7H4YivWFHfVnCdJvHIpNO/ZWJFOKkrfOM2oI5rPxGMjXM/LmdAEVpklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwpIIdenSlatumUgWVOZB6MoyhlJBCjK1i6PEbhcAX38xzBt1qC5B0hahV7+WkBFJUWGsMgC0NnGtnXaprR7q4Cg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAToncRMAQNFqz6bkz4FLTGc6tSOzjkMJ8e19VJPRRhDqCspmDKTDKmUoCdLcUB+qzw5m6YbbATQ/FdBY1nBawIJ/NZKyNSHtSogocnhzWz2epBHIuKEZJkvipNXW2JYJ6sCXyoWX3EaYCtcmp8A8f9c7959up9kdm8wjBfjYamrcYNpam+w8jBuXy+/VBr1TYhHCOstTiWb8wVg13dAYbI7/dR/4hZtLQ5KjnLRIWEPuTc/irzH+AM0W/s0ICQwt2vgWCxlsvlKqCOJ29KBLLZmgcdMQBYbpcqOuUPBR4jUNYfG3cbNG5lAsD22/odC2MmUh0RiRcVMIk1obSHmNn404fdGcYiabOJumOXdQi6ZLuU4xciVUdQqZPeD1s+cQgP+CTFHmYKcYcCTIYjCUSoqXrEvR342aIjYYb2WLzfrHRZqautgsr9nQ06NXnBIsxg6tDw8PaRpymQc+aj1+bxLEGWXHAGMl73DHco50eGQsEv61D8pgCu3uoK0fYKy9uQpAjhxMpivTsCzFyReNPeI5OjPfhvW1CZ+zOVSTSR2VeqgU55tPIWTJq5FaptcacGOf+AIqGAta3jb11LpVh6K1hfSIhmHd41w2Nd52HHz5ISoTRor2pDElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUVS2fKvVhMYvac/1hmi/fam5TLNng6NkS4K2b5LiQ8r6v6XTDZW4gLtM5HWEVHlRXHoYk9SrCbs/ug1CQMFEBg==" + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACogUfVkxrBTyleZ3FLWolX8xiwur9yt2K1xiAG5ukc+RK2nes4oOQZqZgBCb7pN3ccfLC06LozoBszBXwLMdlA9iUlHqgQZXeu1Oi3GTLSqFX2medmNW4COCH6MDSgmlnQfEtrQ947IjmKMCHfVT8BtjBYUsWAX2wtwxi8gKsJsR1etGv5S9wyFIgO+sEPVEy/YmU4UBqALjMt44bUAGRGSKZg7agfNGozQclKQDAimR5bAWH0pqasFlJ4X1nAq0zFpaF0P4+XIoKtltZQIBp5cUbvMxWF+XCc0cCvjvs0WHiQS1ggXYRr1MMNoexDnUcO8MqfSogUrk3lyAYppEbXiajBNdwmuRfPgQezweP4Y68U9P97V77G/OJxV0DsRrBAAAALovd3hGON9wvv5AhI0K1W5tZrLnCk1CjL8rXj4Fp62O6SoO51O6xNpsbA1KumIZw1DHt0BC+cRQlf66iRUMgWhWy6TWgL+8ujNF4bBkg3J1Am1dR6XpVRLmjRKsKDm+CIxvAn7HhzvSNTBYDD4n5te2QjCchoEEBYUjc1vk0sp9qa8ovEzhh4p+hqm8kmtZe5nuL8EZEqD0yQN3qykHEoYDZcwejpBCdAw6zFQTw1ec/2nHT2ZzZcreVFgTGUQlXQMGPeRI+zspxLxuv7vCKMc6jFJoHLkmtA940Pay+DOJEtTKsokr6MMden95gWr0JbIb6Cm1E90AYW05Wiq7PVsTCLH3MRckPvyhA/y3Os6vHx7gzrxBk7LdA3cAgBGZKRQIY3e5zXPLCVD6hA4hjziT93s1ONKsDGO3tw/D/X+RbjFm3vEmT3H93I0NQsLO0yNRWo27oOyYXzTBl07NWzaOzW5EVrqGwoXlLRE2Zbg/y+SIXeOBKNMBhZFiwb9FqgVoMLkVsLnDoa5CoS7r5IupfT+f4CjAfjLN1TElMHam4/k0SoGWVvsYQe1IsYw7Hie8Gx9OxlbUUWVIRnlpy9zMT4t2EzLrpwMdLFnd6nU1kaZm3i4758heUXI/sqqpAZ+wPIvFgm4CtdZsK1vZFKdDYvL9TL/LrOvxpH7ItbXzPTk7wNJ0pPTEEuWfYTxXFBYwCJzzpYFvlxzs58R0rbp+0vQXYYW+MIf/pUO8twbm/YqBHD9kzsu7zFixcaH4KG6KJ+8S40vaYI8QOYRvqa/hJW7D7kEK7Yt2T7i1tWzZsat+EjroaF/XyGcG9YF6pxjNHPrQMjO81kp3if2UItOxevaCOn5qxgIAAAAAAAAARIXwrAg9JT17IsayCSdNPY13XGgHm6bUfSfYVMRT8Y3MXcPWxf2z2zlkhfcOfgLdgjWfwmXa9lkorTA84GUUBg==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4TtwRS0Mltjx7d9uqzwi57/av4cu5HVizlSfiVoCE46RiUtK6tmcH5SSgbTCcIGvpYUDJzgDari1wwi3QfCRCqg5b/cOR5CUV7oa2fnGmPauHjfhKb0QtTHupqs2UICU+LwM0a+yA5g0kBEbfHAspJems5L+hkG1p4roOJ65MeQIDf04JT+GkvhYra7SrAsH4eEbagVyAQfz5sSgFZN3yumaD3ItVZd/tAWYLRl3v0+Gzqcl+GcIgFNa3gRs1X3nKd9lw/DjA1sKN0nR08DQ61bOQhcdk9kXviBDIeZoO9eKsYpObpp8/+u0h03vV3HIYjmdxOvlhp7VwKIzboBkiiN6q0ca8c3/XaWYppCTLUttm2/IKuB+6f8DdVBas5VW9o5dyfVxghj09saXGESS8xQTkQL5Hb9FLTlo/jJJQhZZ4o5kh1KqCrSGBUGrNT9AC90fcXR1gpGyD7+eOiRL1fh4skb07Eh0h0vdOqy7WZin0x6JMYyhEjMR5lCvyWQ+XcM0YVYj+GWQKIl8MAgz/qeG9q9NVulaDQD/s/7jxKn8JcQQLXex7PZ2KX7of5D9fEd89fHwNZKH5HD72RwUhZn0jOj5Ho9x5VfdmbT0aPL1sVnf0J5Kgnj6lfKevUjM/mCl9714ciLQJ9hJn3dPa+UrCe0veRo2i3YIB1RQWYrvyJjoo3jKt7vLqRhQsXBU4IHO49x4lqWr8gTiYbtRYrKUlHk51t+SmU8umDu/mud5/SSsMT7FpkwlQH+LT7mu6QQc7GjXlEI77b0KnOTidXC0f2kAfaxjr/AeKBM2aQ2yfyxhHzi2B1tSUpj9hbGGphbz2E0ITHEkSmrznFui9V2bInTtFGL3APn/ugPfcViBs3GtfXgFw5l0EaPdVThUB4+BepyEWQm+W44+nOlLIgdaDnJGsA0HmYgjg3g+xX6YfHfgx98ZxREFcwLfJf53X0ALcBVRFvU5CLJl+yRM9rTMB1XuXOi1S+hk0uA1hRU+uKMnGfoQezi4i0dODwUH/MhuQMGIqZdtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAABjdo9CmYXgHD5HLwRkmh2AlypihiKGCbyWCOvT8H7gpq/kmE5IXeu9c2ablYhReHpkjbAN3RZEwbO5waiUH4Qyy+fl/Xz4WKD/2deloSu5kqbDPpE2CGIiJKS+2PF+0AL7XEBBBBqqaJiszZ4R56P7FUp9X1it3N2DU6E4OWjumnNF2LnD0nBXpiICbx1AA/GtcJ0in0LmhWZRzobZATQE" + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALg8HOoNQRNMj+6oPLqSf2wckThJEBiw6zt73RRAk6EOmHINgIsHgYlpczRUwbcb6v6GULlnssV2ssv7BR2kdtWiffUHxIM/U3risXYvDUtmiTtU2q1miCxbUNOPKUG1CmrVjDj9fyUTOu71Z4TaLGRc4dY/DBwTyUbnNZnLdazYRXJdS5yRD+gCLko2erCmCrQHPGWGNFIC0Q7RNHrwPTMlJ2Kc9u3XP88Xas7QrdW2iugc+27IIdlN+d2qH6rtse7hBoONrDyfOvf9xRNyjlhVAdzXxYd0Ba69B+q+ARRcOejhDBlvKElF5c8K6H+jZpf9EFMzhQ8zzN544l1ZiK3iajBNdwmuRfPgQezweP4Y68U9P97V77G/OJxV0DsRrBAAAALovd3hGON9wvv5AhI0K1W5tZrLnCk1CjL8rXj4Fp62OCDhQK2nvGQsispAPwKpXU7BD+TfIvA1UbmkGdDxSewkjsLGBjrSe7wPn36g0e5b3Z4xd3kKJizp9G0FSR0pxAqzJRLUeDzNuxBN4oNBRhn7yVYCHPsQFvDVMsxQs6NuUGyKZ+7E8+FrEjZ6DovwdzYVEAPkZeKckTuRAuuqORRhLNigcmDZKgCzY5wyRQs6EXxRM69DbasM+5QxmlTWetRSOxFHepLwFyayRlEOSXf49cKi4Y637aNJmw1Hu9lnokqkHa7hwM9hZgA9VDCI8CotOdZJorxsruoW/0Tg2R7TlKuINkB70LmR812nu9XtcDqHQzxp3NxRP2bFTB5+1kLASIJfAFSsql3jNKPyCtSBPGK8ZTdOEahCAd0oAUv1FJGFwRzPeE6N4e+/cqupreUmlaHWqSJjV0JuZoBBgWyKmPBWEWBhjT3b6jLLL3tOnvvebUqNtseVuUyrX1J12JBk8KaswnTqoIcQnlYzzDY+fi1DMQ6q+hX194aIKvy9t7smRtyCpknI0qpW9bXxCUazAdSsGfq3gbsAtv8nSv5m4F7m1yilN9+BLvaWTuTTw/fI1WU0W2Z5mLP4HxQ7JNGZ85LJxItv0Yi9MQUk6VCDRYMV0QT3Wj8GKDp16vC5YCpBdim0zFEoYgxG9YSjEMyLGbjoAbJKJed7zA+RuTKVFjfYtYGqaJXAxtyLd46zuQNdynnn4PIuD6sIVMOLaszN8/vV841VzkZN4DpSC0pjuFTYUchLQisS+3un5ulgwqXzWYIhawh+yF7YoPQkcZvyce9E9B9Ov4+FAuF1cQpkwa4lq2Nid4bzVDri7KilCrEXk9xW4sRSQQRz7B343zUtMznD/gLvS2WEmRmULBRfwjAj+cGuilv51FgsaZrhitLqUiQXxXAQY98E6ARe+N0tWd0RCg6YqMKkeIGXlJc6hDcpsIm9NCt94+U0qSzgw0jilpqyrC3euNMq2yfviLiEXpIKwDYYSePZ6x7bkDe3jx+hLX6FEra0ZDbLT6UeA+THupeofWFZu4Dr8y8CFGLc/9cTOTOnapUca0xJ7ziW2iTrTlA9hgn2+qsUt4hEsmPC5MV1hImk6HiBMmWdRLTfN3dnk3nUFKK/iDxbQq0EQfxSVxuNFx2VekJm5ikZXZk0aU6uPwxLNpLUUUxneOEAfC+f64Z82UaAiPu7z/G7xKNLDpuUkfsXC4lDGmgdA+uBZ7mLPB70XYGJBu1faUCWB3Q4k7dWj0oPY0/b31xBzhSapWYeDyZ6O5+OkSwd3Qkda7jfoRUvClS+WKeI6/Rw9QJOhYZCdrm77a3fzFXkHZsGfCPzYxKGgDXUzm4wPY863aTv+64/5XAGabqKgZS+47OdocTaKCQoEEvoBjNnunqdfI4FCDwCnTggGNeMc/EZg1uXJkJpFNpyG2xWdeTGfunckp0AADVMWAxURVDxQGI6uw8IlV8t5ustbBgktPc2BRRYbjSUxSty6tXdJVZrTz0DuDVgzZbVLGRCJJwfY9BUJHrrHtn+IzzftLz8QipZimJXapAI46ciVBQp7CQ==" } ] + } + ], + "Blockchain asset updates when spending and burning the same note in a block fails validation as double spend": [ + { + "id": "5e3f451b-e76f-4c5f-a8db-bd6fa03915ee", + "name": "test", + "spendingKey": "532e9b851a0afb969a2443c4487b93db8116bbc8c06cef6f6562b42249a0d72a", + "incomingViewKey": "81fc8460345cbd6af9ed7680fac88bf783f06d30b75f82f4364757308feb9906", + "outgoingViewKey": "e4bc95a916a0a16a3d181d4879a214657888ad2c3ce941507d158128a24b84b2", + "publicAddress": "1d37d3f047e51856369de1709ebb71ae43bf29505a5198e8987d32b0476456c4" }, { "header": { - "sequence": 4, - "previousBlockHash": "0BA5D22D6D547D227CD54476014FDD3FD07A19051C9AA0FBE54B2D6632550CC1", + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:1/s5sOY6GBdY/gClFJy+AQe5hfGPCImQS5GX4oRp+hw=" + "data": "base64:oeAZV6hLBVeh/kKvkP7wvDincXp+kHpm35YdQ/lGaTI=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:DveEzhPZOvhDlFXKXqxNBWH4rqiw+USkTjP5GhZ1paI=" + "data": "base64:cLsUygml7F94wqd3+Rb0+uK9rX2gBX8XNg/K72aa3DE=" }, - "target": "878277375889837647326843029495509009809390053592540685978895509768758568", + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470865150, + "timestamp": 1671736082983, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", - "noteSize": 10, + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAkNsAFlqJ0ZCNXvNOVKnItFUr3fLTA4f9FEXKQS+Ju5GtoNYdil7zPLsu4Sr6BoXo2CrOHCBqhyvgMbR784/jBsPPdLIKvuZKheH8ZxS5Ujuusivp5m7Z606LXALIuxt3lUkX0AVAAiwj9/MSbi4BldNox9119XDCp9/CH0am1wUJy5LQy6maS8OCvsXktgbK4opUBAbO+uJlo6k8h1twR0NA2DYQIRuO8y06trGsWQeAG/H8v+K/Xl/AW1r2n3W02skHPsG3RBGaCGxHg/3zDgnqSLtNU6lQBlPnlI2zxv2BMmpd51FHKZm5nfj3F3bKiFYL+RILdlhywj7VoBh/1B95kod88GSrYxzP0EjJ3e2+6vKlK4JD+Fcm8HN6aNMnNSqU1uz534+PkDZ0mAEl+FkR4jXE9D4MlteNvNf4i+oUG6wC8EhnXXTsmzswDPLF6Ff2huvVwfQ++7UkknIFclC4iEOzsqvTZpKtFw+fhXSYOAIzi+IAeWifIIdANXlH70Oso7z07lnYQERBo8SVK+auvjsZSicwJnDFCjzYE0Fxkl1TiEhEa1BA0xMG2s9EMA2553r7Len87o0j3kyIoCvhmsLrovSwq7kdNo46KetOy7G2QUGuL0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwdgSHpOyoRncL7phhTchwX15dTJK+zXCScTwYdycdjCfK5KIpDgQTIZUSGTFHJKyw8lGHrTgShKn2zL8vKXdiBg==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "FE6C999EAB4AACCB702FE7FD0244BF0D2D82C52F5C6C313F254D6FA2FCD89075", + "noteCommitment": { + "type": "Buffer", + "data": "base64:Y8PCRLa0QtDRf6Da1McsEsD+gmcoUFjK7rXbCS+syTw=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:k6TZxxyvUytfmDsYg9A69ud7a9V+/dfXGtP8jfdJfjg=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1671736086066, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 8, "work": "0" }, "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAmUkUSBM4jA6Eqi7qbV7geNdWG1ZtvoZDH9xEIyms0VmjW9vOlC7Wfn3EyDywlWEUWu0uhakOuly98HN9kXv4udeorDRm+O1FWqWytfjcVDGw9tJDvwEUBTkdnrJ285auj+VjHjbeO+/oFlNNKHFEu7e+y+b/4KMsEL30GFxwzY8MrInHN/le4BQdJ4M9fWcjEsGqLRpBZcQsb1iRqa8QJbeBySGIqKhfBSYhoVJjsuSEUf/uvqJ5p0io/XnyQaF0mQeAD4ANIxIGk4EgaWrUuHwcqqcv85yjond/G4sxoLcuhTtOMqkAJZ7sAFppbtmPIA/ki/lxRlhUz0rhI7lChL9EVkk+AhFQhHAphzOtqkjUAvgB6lyjtBm83lrr05IMuzIgV8YBI2z/q34LgzGQvu9B0fU71Zvnggn2+cXM5Fja3hNleIiC/iK6bEtamImfaFYgSTDhfIKxEobWbXObnXLmNMSKu4u7aJYl2AQjtmRpUaJyonvJsuKiyXvrK2tAjHlYU1e1asNwWjER2kmNj+b4bY7r2vrflYkIyntgjMQ2sLVspluJsKK3E/jLysxJEal+J3Dac2akP+Ks6Wc3kBXBQbKeGynG5em69LfwMroKfydxZl+okklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwITKo5a1PimmODT3GB3xTZRAzEjAlFy9/LCFrWWZOkCHwcRGg5B5t2l4FRijtMwx9tiBZQpC+GvXqzalUJZ5YDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAvAGL2V5nnv4XKs3oNhwJDyLTrqxKgSuyfz59m/nWCy2RIIABgFrzhBq/Wp89q+3no8SmGU+o3i/j2flrchNkzkXwox7N5gmM1VrV9EwJzj2H8XZVrwvsHPReLGIAqv4SSAM1DZmKZCg/c5Dj8XfMvd9E7W4xkWkcfvUz+hkt/0wSCKi6T7IgvmBesdkHbGnjKoEDxYh1w7YUDtP6iXaEyiuyiBu2gJI8lEkUuRILv7ujNxjsxAQ9FFdhS9E3Em7kKvNpXFfZBuZkKWsPlmjOeVfM/tMUSj17OjNaXZANb9UsrXk9opH4FfO8/8wkZZPjTVkhdcJo/9loWcCBqmzclxre49D6zYjLx3SXcEzE/u20Iqk+/wuOwb70hgodLsgsvquNz4DwZuctYw+gEM3ZMS8aVEKBOnZyemF+Sq91WgOEpbH+QySjPwIb89NDId5IuKLmnIQX9CjYWm7IjTgwjTaPNwGmflBQUYRjI3KqZFMVAamtjGYTpwF9WJGhRpgxc8vkGzlpYVSETh1gb154sMeK44eDfZrDIshTyat1YxueGUspWafsaQ8fQ4tMdIYeIp1Buid+SNjd5R5mBFTwSsuIT/GRCChAra+mS6Gm55s0nwfji2v390lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw37JvvLB1D4GYHu89jaYLtg66soW/Ymej/Ab42RDG7QrzFEMxUwyoJO3LxKkVezvL0xp0bp1egvytSGcHrFsuCw==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA16u9JiGwP/zHCSeHJTsnJd2GePj4sWT7dma+XPRZt5qPkPoWwOT0JU3CopWtL4uIuDRKTLKbuv+2KguBL+Tp6YpPRmdQWT9+24GIy1bqpw2ojSsE5rhOeRrTNVMQxYqWcxZoW6hwd3alvWRWnD37Aqy9+NUx/AZ+43zMZz5HG6YQAv97efDT8PwE0epfXAIz+MBlTjH4O3ENX2vqkRzdUWl2Tl+2kHyIvhYX62xJC9+Yj+igEqd6snwjf/myHaUdHS4hZZtP0NHkNVUhnhf+r8d20ry8UMe7jssfJd8X6ue0CcpiBG/q25z9jC6+F9j7VdZeuCnAuU4yQOtf36lH72TAHIt9k7ggIvu2X56Sa56vDBaq38Yo6SRsAlLaoDMhBgAAAClqRmnYeOq/UC5qv28x/wyDpHM7dUgu2XQ7okHcgSP1C0LbQ8+RJ0V3sOQ+hN2Y8v3c1zbYGgcEn1i06WF6+myk04LrCE4bLZBBveWdVV2Vr4t9bVEktJkgvF46FLiRAY9hvYfVxxtAGgew9nAlRdv/D49i8rqGAsrMLYh7d9o7ThClcssBmbJqYQJNGfhdYajqGlqSgbqOjJMefks6Gz8r4sJXxftHCLBbMCJpLYycsIfG93ELXIC24LeZxUubKwp0JWwdEDvhpmHHfgUZokMMV5i1CgqQuqd+kIS6mShxcL+TO4EctSvlrYBFB73o0YX7sm3Hs8Gx4WB5VPX2qjeOR8Mv11iW3g5a/DNKLa3smAXAs0Vnt/9vYJEOcPR42AfIrH8XWQYEIzcKiYDlUqwfzUgJ4t1NnddSxK8z5hUJWcSHjfcl3bqzREZJjGzgc2g8a8IgiGWDZTmepqySEHKZv348aCwXp8OJCtnoBU5POJA6m2IrRFHdjm1V+I0wq4UKvBny2JA8hkTDwjLSS6peXHk9e/x8l3nb1puZY0H3Igwfg4EYZkI8oOmZ+oUdPsl3+VTFpHUtKSBuTKFzD7f2vOIYpsg5lmdwewc7pvKvoZATuO1uv7rXyCEwQNo5Dwc0uQzXDcMytw84wX4e/95AFxX+6EV7rf7FeKTSXwYYtGplwrtO+sgASach3xgB3j0x/ZnJ/kFlMpSM1clblLvBDKoQAbhK538Bq4hVGeZkN529pDla+RVL2rqtMP8DjaPgk3VuHDdvTzhVTh0hp1Y7TJKUwhbRLnfvSrs4ncyT4o82FAwZcoRpLyaJJUCvxgT64a/HT53rUabbG5XKOMGKVGc9E64LbgIAAAAAAAAAZHrHvPjLJTf9xr+ixUSRicuK9NbFA2a3sFuFLvTGdxQlhFpdgBg4hnyMqJqxvs5fAp3KMYRcjTkX+jgdsBL/AA==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAly7Odd5T0T36Wc/LbkaigjHMHTOirChcB0hLAcmpTl+AD8gAn0S2lRdjJST0P5govaVy0dsobzD8vigo6GWo+770ZE2VSJ57CQnSlVOhxGK2NeoiN/vRTyfC8aDpOE79fPbS6xPJsJymcE6XoUWsoenE7kUGRpi7W6pUe84xqDcHfaH/3ODFaYDJFM3bC4DePSZ9oNipswI0lNpXZhxp/bdwkQIC9o2TzXT7UX4ysyigJfHEIyiDPeDTj4RBBGIFc9O9vykqDIIh0/5FBEvIEK4w4UtynXf3VkRcv6RRNN65MCa6MWoMKKSY6ua08R0LPoHbM5dSsD81Hgj+CtYea6HgGVeoSwVXof5Cr5D+8Lw4p3F6fpB6Zt+WHUP5RmkyBAAAAFG+kVZg1LyjktjEAZ2VeCD8fnUszp2h2d0c+kPRkEtwlfdhGGcpBVyTc1mDtVCU6p3DuW3jm9cPsYY3aCeK5Q8vpYJpywKe4bUTuU7vKrlSs7KG9uTBPTs00r+ANJXXDY/rZEKax/2fJSYA3rQ04YWm10GAORKEUIRj+aKNSBbe2KPRBrcPOl4eM5+qzQs25rhmyhwlpoUqDAbY7ZFfz7O7O2RpPK/xyNOfsrEVDhOidwM3kIoRec/8zsV6OkxJywpgqw1fvZ+2RPTd68P1YF2FoEG7Mq4yY/fWXf+QQ6qZk3mSoDtah7SbkGEwdjkSupQVoO6lzDqwVIzCaronbqje9N18uqkvxeo5FI4l/4+mJPfePkZ1xg7SWfpS36ZXPv9TstOaw9MPDLswGHTGwCoT2KiQWHoiFmwukVjppF9cBbHnnL25+DwimJR5UZwaOlxm+UxUkIOhhmHDQu6e+UbjOa7PiQFlPlVOmpJ0+XzQs0UmqqyItQpySgrg2sx4hVD9o5ZzE6l7qIZiu1w79kr/7ykKG0Q4jHd1OF/H2B18CMXhted+PaOE7euHdS1IXOW2/M0p/0a1gz6ZTamM5ebMdis9nuzeDvbSmitE5+KK0qUOfJdnhsPFppkLf0SqQLqChAUNI79m3IaOC++RTBeBi7iLu/bKmVuvQ+j8poaZkYtRW8vqgmMDm4EYgBf6CAcoMbdGxe3dfQPvyHH1FQAY3iX7DzZtpcPPF+K+OCT19vlEFzj9Ccaj4S3+ylWJfqLtTHmXeu9zwRryP6I/HupUWfKjsUJNm2Awm/u6wne0c/t5f+BGy2zXyGcG9YF6pxjNHPrQMjO81kp3if2UItOxevaCOn5qxgIAAAAAAAAAhvfjMshK6VyQemu+7h/+JtQXi8oUhbw0yJX9PSQixcOYsUNqScMlDf/BLKwUOEA0ffL3Yjuh4ej8pERx8+s0CA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] } diff --git a/ironfish/src/blockchain/blockchain.test.ts b/ironfish/src/blockchain/blockchain.test.ts index c3492b5d6c..dd6b9f46f6 100644 --- a/ironfish/src/blockchain/blockchain.test.ts +++ b/ironfish/src/blockchain/blockchain.test.ts @@ -2,12 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Asset, generateKey } from '@ironfish/rust-nodejs' +import { Asset, generateKey, Note as NativeNote } from '@ironfish/rust-nodejs' import { Assert } from '../assert' import { VerificationResultReason } from '../consensus' import { IronfishNode } from '../node' -import { Block } from '../primitives' +import { Block, Note } from '../primitives' import { NoteEncrypted } from '../primitives/noteEncrypted' +import { RawTransaction } from '../primitives/rawTransaction' import { createNodeTest, useAccountFixture, @@ -19,7 +20,6 @@ import { useTxFixture, } from '../testUtilities' import { makeBlockAfter } from '../testUtilities/helpers/blockchain' -import { buildRawTransaction } from '../testUtilities/helpers/transaction' import { AsyncUtils } from '../utils' import { Account } from '../wallet' @@ -1240,60 +1240,58 @@ describe('Blockchain', () => { }) describe('when spending and burning the same note in a block', () => { - it('throws an exception', async () => { + it('fails validation as double spend', async () => { const { node } = await nodeTest.createSetup() - const wallet = node.wallet - const account = await useAccountFixture(wallet) + const account = await useAccountFixture(node.wallet) - const minedBlock = await useMinerBlockFixture(node.chain, 2, account) - await expect(node.chain).toAddBlock(minedBlock) - - // Mint so we have an existing asset - const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() - - const mintValue = BigInt(10) - const mintBlock = await mintAsset(node, account, 3, asset, mintValue) - await expect(node.chain).toAddBlock(mintBlock) + const mined = await useMinerBlockFixture(node.chain, 2, account) + await expect(node.chain).toAddBlock(mined) await node.wallet.updateHead() - // Build a block which uses the same note for burning and spending - const noteToBurn = mintBlock.transactions[1].getNote(0) - const doubleSpendBlock = await useBlockFixture(node.chain, async () => { - const burnTransaction = await buildRawTransaction( - node.chain, - node.workerPool, - account, - [noteToBurn], - [], - [], - [{ assetIdentifier: asset.identifier(), value: BigInt(2) }], - ) - const spendTransaction = await buildRawTransaction( - node.chain, - node.workerPool, - account, - [noteToBurn], - [ - { - publicAddress: account.publicAddress, - amount: BigInt(3), - memo: '', - assetIdentifier, - }, - ], - [], - [], + const doubleSpend = await useBlockFixture(node.chain, async () => { + // The note to double spend + const note = await account.getDecryptedNote( + mined.transactions[0].getNote(0).merkleHash(), ) + + Assert.isNotUndefined(note) + Assert.isNotNull(note.index) + const witness = await node.chain.notes.witness(note.index) + Assert.isNotNull(witness) + + const rawBurn = new RawTransaction() + rawBurn.spendingKey = account.spendingKey + rawBurn.spends = [{ note: note.note, witness }] + rawBurn.burns = [{ assetIdentifier: Asset.nativeIdentifier(), value: BigInt(2) }] + + const rawSend = new RawTransaction() + rawSend.spendingKey = account.spendingKey + rawSend.spends = [{ note: note.note, witness }] + rawSend.receives = [ + { + note: new Note( + new NativeNote( + account.publicAddress, + 3n, + '', + Asset.nativeIdentifier(), + account.publicAddress, + ).serialize(), + ), + }, + ] + + const burnTransaction = await node.workerPool.postTransaction(rawBurn) + const spendTransaction = await node.workerPool.postTransaction(rawSend) const fee = burnTransaction.fee() + spendTransaction.fee() return node.chain.newBlock( [burnTransaction, spendTransaction], - await node.strategy.createMinersFee(fee, 4, generateKey().spending_key), + await node.strategy.createMinersFee(fee, 3, generateKey().spending_key), ) }) - expect(await node.chain.addBlock(doubleSpendBlock)).toMatchObject({ + expect(await node.chain.addBlock(doubleSpend)).toMatchObject({ isAdded: false, reason: VerificationResultReason.DOUBLE_SPEND, }) From f7e1d1ed084446f2566e7b9dd3fe73e9544728ab Mon Sep 17 00:00:00 2001 From: Derek Guenther Date: Tue, 3 Jan 2023 14:23:35 -0500 Subject: [PATCH 22/56] Update to Nodejs 18 (#2768) --- .github/workflows/build-ironfish-rust-nodejs.yml | 10 +++++----- .github/workflows/ci.yml | 6 +++--- .github/workflows/deploy-brew.yml | 2 +- .github/workflows/deploy-npm-ironfish-cli.yml | 2 +- .github/workflows/deploy-npm-ironfish-rust-nodejs.yml | 2 +- .github/workflows/deploy-npm-ironfish.yml | 2 +- README.md | 2 +- ironfish-cli/Dockerfile | 4 ++-- ironfish-cli/bin/run | 4 ++-- ironfish-cli/package.json | 4 ++-- ironfish-rust-nodejs/npm/darwin-arm64/package.json | 2 +- ironfish-rust-nodejs/npm/darwin-x64/package.json | 2 +- ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json | 2 +- ironfish-rust-nodejs/npm/linux-arm64-musl/package.json | 2 +- ironfish-rust-nodejs/npm/linux-x64-gnu/package.json | 2 +- ironfish-rust-nodejs/npm/linux-x64-musl/package.json | 2 +- ironfish-rust-nodejs/npm/win32-x64-msvc/package.json | 2 +- ironfish-rust-nodejs/package.json | 2 +- yarn.lock | 8 ++++---- 19 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build-ironfish-rust-nodejs.yml b/.github/workflows/build-ironfish-rust-nodejs.yml index 4a5b644c8c..df0978d023 100644 --- a/.github/workflows/build-ironfish-rust-nodejs.yml +++ b/.github/workflows/build-ironfish-rust-nodejs.yml @@ -45,7 +45,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' cache: yarn - name: Install @@ -89,11 +89,11 @@ jobs: - host: ubuntu-latest target: x86_64-unknown-linux-gnu - docker: node:16-slim + docker: node:18-slim - host: ubuntu-latest target: x86_64-unknown-linux-musl - docker: node:16-alpine + docker: node:18-alpine - host: ubuntu-latest target: aarch64-unknown-linux-gnu @@ -101,7 +101,7 @@ jobs: - host: ubuntu-latest target: aarch64-unknown-linux-musl - docker: arm64v8/node:16-alpine + docker: arm64v8/node:18-alpine platform: linux/arm64/v8 name: Test bindings for ${{ matrix.settings.target }} @@ -117,7 +117,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' - name: Download artifacts uses: actions/download-artifact@v3 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cf93388a8..80fbe99e37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' cache: 'yarn' - name: Install packages @@ -50,7 +50,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' cache: 'yarn' - name: Cache Rust @@ -79,7 +79,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' cache: 'yarn' - name: Cache Rust diff --git a/.github/workflows/deploy-brew.yml b/.github/workflows/deploy-brew.yml index 27c4dfe012..06dd202ae8 100644 --- a/.github/workflows/deploy-brew.yml +++ b/.github/workflows/deploy-brew.yml @@ -25,7 +25,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' cache: 'yarn' - name: Build Ironfish CLI diff --git a/.github/workflows/deploy-npm-ironfish-cli.yml b/.github/workflows/deploy-npm-ironfish-cli.yml index 43662c01fe..17999d8235 100644 --- a/.github/workflows/deploy-npm-ironfish-cli.yml +++ b/.github/workflows/deploy-npm-ironfish-cli.yml @@ -16,7 +16,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' registry-url: 'https://registry.npmjs.org' cache: yarn diff --git a/.github/workflows/deploy-npm-ironfish-rust-nodejs.yml b/.github/workflows/deploy-npm-ironfish-rust-nodejs.yml index 737a4840bc..21ce76620c 100644 --- a/.github/workflows/deploy-npm-ironfish-rust-nodejs.yml +++ b/.github/workflows/deploy-npm-ironfish-rust-nodejs.yml @@ -26,7 +26,7 @@ jobs: - name: Setup node uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' registry-url: 'https://registry.npmjs.org' cache: yarn diff --git a/.github/workflows/deploy-npm-ironfish.yml b/.github/workflows/deploy-npm-ironfish.yml index 4dfc453c10..d247ea42ae 100644 --- a/.github/workflows/deploy-npm-ironfish.yml +++ b/.github/workflows/deploy-npm-ironfish.yml @@ -13,7 +13,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v3 with: - node-version: '16.13.0' + node-version: '18.12.1' registry-url: 'https://registry.npmjs.org' cache: yarn diff --git a/README.md b/README.md index d88efde5c2..70c5921bf6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See https://ironfish.network The following steps should only be used to install if you are planning on contributing to the Iron Fish codebase. Otherwise, we **strongly** recommend using the installation methods here: https://ironfish.network/docs/onboarding/installation-iron-fish -1. Install [Node.js 16.x](https://nodejs.org/download/release/latest-v16.x/) +1. Install [Node.js 18.x](https://nodejs.org/en/download/) 1. Install [Rust](https://www.rust-lang.org/learn/get-started). 1. Install [Yarn](https://classic.yarnpkg.com/en/docs/install). 1. Windows: diff --git a/ironfish-cli/Dockerfile b/ironfish-cli/Dockerfile index e0d862116d..bf981f1120 100644 --- a/ironfish-cli/Dockerfile +++ b/ironfish-cli/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.15.1-bullseye as build +FROM node:18.12.1-bullseye as build ENV PATH="/root/.cargo/bin:${PATH}" RUN \ @@ -13,7 +13,7 @@ COPY ./ ./ RUN ./ironfish-cli/scripts/build.sh -FROM node:16.15.1-bullseye-slim +FROM node:18.12.1-bullseye-slim EXPOSE 8020:8020 EXPOSE 9033:9033 VOLUME /root/.ironfish diff --git a/ironfish-cli/bin/run b/ironfish-cli/bin/run index 6949416502..20d67b346e 100755 --- a/ironfish-cli/bin/run +++ b/ironfish-cli/bin/run @@ -7,8 +7,8 @@ if (process.platform !== 'win32') { require('segfault-handler').registerHandler('segfault.log') } -if(process.versions.node.split('.')[0] !== '16') { - console.log('NodeJS version ' + process.versions.node + ' is not compatible. Must have node v16.x installed: https://nodejs.org/en/blog/release/v16.16.0') +if(process.versions.node.split('.')[0] !== '18') { + console.log('NodeJS version ' + process.versions.node + ' is not compatible. Must have node v18.x installed: https://nodejs.org/en/download/') process.exit(1) } diff --git a/ironfish-cli/package.json b/ironfish-cli/package.json index 70c1081765..20dae0cb0b 100644 --- a/ironfish-cli/package.json +++ b/ironfish-cli/package.json @@ -20,12 +20,12 @@ "/oclif.manifest.json" ], "engines": { - "node": "16.x" + "node": "18.x" }, "devDependencies": { "@oclif/test": "2.1.0", "@types/blessed": "0.1.17", - "@types/node": "16.11.1", + "@types/node": "18.11.16", "@types/tar": "6.1.1", "@types/ws": "7.4.5", "chai": "4.2.0", diff --git a/ironfish-rust-nodejs/npm/darwin-arm64/package.json b/ironfish-rust-nodejs/npm/darwin-arm64/package.json index 463a3e5b3d..dd1dca6fbd 100644 --- a/ironfish-rust-nodejs/npm/darwin-arm64/package.json +++ b/ironfish-rust-nodejs/npm/darwin-arm64/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/darwin-x64/package.json b/ironfish-rust-nodejs/npm/darwin-x64/package.json index 93d541beaa..63c7872e80 100644 --- a/ironfish-rust-nodejs/npm/darwin-x64/package.json +++ b/ironfish-rust-nodejs/npm/darwin-x64/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json b/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json index de577dee3d..20c79fad11 100644 --- a/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json +++ b/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json b/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json index a1ca19c631..d7ed74ae8a 100644 --- a/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json +++ b/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json b/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json index a2cbdda434..16725e2d51 100644 --- a/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json +++ b/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/linux-x64-musl/package.json b/ironfish-rust-nodejs/npm/linux-x64-musl/package.json index 7ebf408c9a..514c3fc79a 100644 --- a/ironfish-rust-nodejs/npm/linux-x64-musl/package.json +++ b/ironfish-rust-nodejs/npm/linux-x64-musl/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json b/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json index eb3a41f9da..8a6e998a9a 100644 --- a/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json +++ b/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json @@ -13,6 +13,6 @@ ], "license": "MPL-2.0", "engines": { - "node": ">= 16" + "node": ">= 18" } } diff --git a/ironfish-rust-nodejs/package.json b/ironfish-rust-nodejs/package.json index f423b4e3c8..ce8682df21 100644 --- a/ironfish-rust-nodejs/package.json +++ b/ironfish-rust-nodejs/package.json @@ -30,7 +30,7 @@ } }, "engines": { - "node": ">= 16" + "node": ">= 18" }, "devDependencies": { "@napi-rs/cli": "2.13.3", diff --git a/yarn.lock b/yarn.lock index 9a94e40b3f..a830907a24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4002,10 +4002,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.7.tgz#36820945061326978c42a01e56b61cd223dfdc42" integrity sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw== -"@types/node@16.11.1": - version "16.11.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.1.tgz#2e50a649a50fc403433a14f829eface1a3443e97" - integrity sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA== +"@types/node@18.11.16": + version "18.11.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.16.tgz#966cae211e970199559cfbd295888fca189e49af" + integrity sha512-6T7P5bDkRhqRxrQtwj7vru+bWTpelgtcETAZEUSdq0YISKz8WKdoBukQLYQQ6DFHvU9JRsbFq0JH5C51X2ZdnA== "@types/node@^15.6.1": version "15.14.9" From 5a835c578b4b39cc1674e2e54d6db2e2f7250bc2 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Tue, 3 Jan 2023 15:08:02 -0500 Subject: [PATCH 23/56] Remove useRawTxFixture() fixture (#2804) The ultimate goal here is to remove - WorkerPool.createTransaction() - Fake witness creation in MASP tests - buildRawTransaction() in tx test helpers --- .../__fixtures__/blockchain.test.ts.fixture | 1070 ++++++++++------- ironfish/src/blockchain/blockchain.test.ts | 41 +- .../src/primitives/rawTransaction.test.ts | 9 +- ironfish/src/testUtilities/fixtures.ts | 40 +- .../src/testUtilities/helpers/transaction.ts | 42 +- .../workerPool/tasks/postTransaction.test.ts | 6 +- 6 files changed, 708 insertions(+), 500 deletions(-) diff --git a/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture b/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture index 842ef24df3..328e589c48 100644 --- a/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture +++ b/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture @@ -6,15 +6,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:/L3Im7NzIxNDQRtfzsVRK+WLB3Nm/y0so2qPi5bJ/24=" + "data": "base64:jYR9fJkiVm3FxLtRCcKQt7KWNyRIbO1Ko4FPCk+DnBk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:IKynaZjiGbJVBdp7HmxJBHRSBSD1KVI2SMcW8Y6qu5c=" + "data": "base64:yv4OFFoDIT1BM9q0dvdmCwdfA/dFBuDeiOrqX2Mdt0s=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470815748, + "timestamp": 1671691590810, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -22,25 +22,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAP0dheORc4FXaiHy896ENNA954AY7ah6ePjr2PuSjKw2mYs82K6xn/WiIvlQiTBv0FuG8SlfK7dfxD+eBoPRBxRL74c83wzImJCrGHRYF+UCR/BsSTJqp/ttmYf4xcal3+Wk//bPnxfM6d5fCu9LgQ99tNC0Fqomtz6x7lh+6JmIQbt5j11n+dyEGnRl8LUAFCwmVGllD7xOcupo1jxkW7vyuTeA7Dk39JQwSvMS5WP639s9ofqgPuztY7kLMyrz83ep4n40RPCJZdXasKXU5rOnCzgYJLfpIeaEj92LBF447tmd8bmL8zbaHASaYGpxmadeWG7fxx9ceP3Y/Z077vEBUpp/CP1kqd42LBAscYq+NPpwKxmcJZKWj1C1NH3IqpBQhaltVJnDOOUXwcsfeU5RHLCXzBaLo5PB08VFaY0Qjzy4jwPNJDnURVgs2TcF0d22a2eY8NS0q9piG3c2DJUHeFZFvzJ/d+gD5FFxMZRi6MJffuK7iAa2dSg6+LZuUv8Rvlc7m2PV7d6hgmpnOGXxltFY7p7PXud2DgCwrasmlpc8AY8z8tY2X98uJWNNaQTt9Vr/LE00b/XChYacgH3ACV933Z/ZYrWVKWF5oC0t07czYY9UzdElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwkPVn2MGhm59CBD2JCu091ARBmNrFamdihRQ5NpnPEQ/8FwrHypX6YEL4k8TQQQY4A1ah7XSqr4OkoYfEwmggBw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA49EVdPUUB+xAZe+bwUj2rhlw9hW1IEcSF7VSYS7qSpSO6YoxbbRYOavyZfIIsCClvE7kUJZf2Zz/Xy5EnodofKTsW67xQkpOhIpcOG2ViOiLwevGX12+vJOD1Uq4nTBB2qKCnbJHe8W0p7RLIbxyxSzzbKL/SM+lHUITjqD9JOwWM/IHGcPre+qgynmeUwPuMj2CI/VOxo2n8lfkXN8mR2QXWI61tv5Ggooz3vEp8qCJ/iofVWnmvloGc2vs4+REw1zdjaM5w9k8I6vNHskXGioZUQaXGRe0aqw7yr506IfgDReUFtTdyyKP08YiFXN7FyAVUKsl99G5GNmEPDIKiCfo/ynWhfxEiNPGEs/yrUuz+N6g/RWgGDR/81dGVXpTTevDhTXC8OcaAiWF28BV8Or32pI6ng18ODjE61PBj+lxcffXz6fKaDXnmkGlnoxfvAX63C5fEMSP4CzKhq+nI32yF4e6V59xY3nOxzxh6r0tsUENYZeuqfodhL5uvUEV4vKEbM1XfLn0KpImeJY81wtKnPpQjXwtyXaaD/eT6XtTqUNsEzyvhXGW8S+W2Vn+TmbbMB8Rvfb8HzmhxPw+ZULyilNvoabiZmPdQASORDJy/18FidrABklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwXzkX3MqlZinmhAaNvAH/ykF74nhcEAxQUECRRcHVd/BjOog4sRGiI3sBdJUaO7FvBV8D7CRJy5QQIGTqo+ftCg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "3BA427E93B48460D63552B983F93E3A45BBA70424997402C354C7BCF956F1B04", + "previousBlockHash": "D3654D0561B3ED16B997DD0676F28DAD2950C6200C64277F969B7AAA63AA8F87", "noteCommitment": { "type": "Buffer", - "data": "base64:n5J2gX9PDVXOImZNAoJPcOKfEzO3HWWeVGVtk+Mq6zo=" + "data": "base64:lJqnVykep/YNVijt3ox97Vvz5ndB4sW5eiMpAhiSyUo=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:ZBJ8BBWdt8tY5nsSLtrUipni4Bh61D/E4qQqxDMQKW4=" + "data": "base64:htz+o7wCkGYEhPaM9e7R/14mclOZXe5AiK5IgqOuqO0=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470816073, + "timestamp": 1671691591143, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -48,25 +48,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAN64ILjIDzoCeeGA7GLm+/8mu+8hQe1FlhZTAimGSvAmEl54QyROqOVqdl0LDPBF/A0pbd73Obt00f2WIsuXnB6bAB1FmIH2ae4sJvg2V7YS0snmzTIyFlZsKG7gfaTTPSwVVfnW2hCjipjXAyNnhNkaE3BvoxJ3JGUG3/h6BwTUFk0izFzOqtNZDwDxibQ+EzQ+63u5vM7yUUrXO9+izzGmHqEcVkoHWpPEtzyJtpUmRhbOCazc/qUr1+1CNlfG7MQ3I4YkRaUgXJjGugGUjObOP8Drn27al83pSq17zHj1CTt7r646iqwBqqWPLfPtwiV+LlZRPvoMAVIDd095UTcGVgpTfhkpOnZpc4ItcegMdkziSVuGpVUyJprD+aJg7jAaJx+ev69rrMqVY4MSAJK/OqJMKWEcjNeihCToZIlIOUmmYQFIwgnpXILrnGsIPgKuX2fCusaY59kQHiakiEcfQpfw/Rse3uFActNTDAvBAjS6YqAk+luLlr9lmE+xfUW8DvPx/8sqtRPtHRZ3KDDQ8bvddC0Xp0qMQMb02Zu/iuxPzsPSR+2Kesc1k/IBC7Djb/x3M0DaapcNDJTx7eMRiXB9bjgNINpqfDHq4Ie9NG5HuaMoh60lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYIM5ZI5H17VmThClNnUH5hWkZ9dh9qDMJaPbNeSJ3T1A9xNzDNBQYReamkyn5D9hhXpSmUZAIp7QWtrRRxOFBg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAxK8ECVAYVlg+kh7uoqV1CJaDBuTeBflInybWg+s3lKugRzo2R61QPkl8mTfTYXC0vd8LKioZR/3+PS9wUdxGjLIGGVhLLxyDtFZH21SJ1xmDuGeh7h66iqFrMKtqfk1v/L9Ws8QC4mhpxeHaSE+lqpIKSk30yqJ99jWmJt8o5PAPXdMh/Nm6Xq8XOGRbwzEepmMrXOaz02bnuqqOZWp2BV6UYff086Sp4nUbx2IoXUKRJzVV3vW+eMhtRVUVSCvPWjlFENMN9fNkeRFRbrhWLXPLFrzvt7EGcpJFwBJZwuoLe1plZwoss303yhGovCsPPy2q4UbVKw+RHJcBZDG8Y1K/u5oMHDLdsf0+5ksutGNxnoF0n0wkANY6J5URkhIZsqMiBfqwOHsQV1zq3k+/WxgiGWdnQfeeCnT5Cu3Gmh1tDSACa6PDzMn1nlID58aExR4K8WgnO6SGfl4i8uO4xVOWNt2tBDQRGbHhSlhYsiML401E9QOz7bRwui8hYYC14V4JwFSoFzixgN9D2SdYGXG6Y2IwbmjOmWQRfLGWJHU5I6hbR92cXv/Sqz3Q3r7Am9506E3eENskPffivW1Gpv9IMzXFAnXBov3Wc70lnijHrQZIWK91/0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwuAF2jeySrRVP59lU7lkdNFrPSSbLDs+m9PdIAvtqJZ7Yzr9+A8f8fr+/VB3VuJImRH7+A7x0hGfRRoKGTEoLAg==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "19DCA4BC7B3B223B0B7DF02E4438C38F4EC5D109200E1A2DC265592D613CD4E3", + "previousBlockHash": "9FDCC40D242E04E2571FD3AE0E5D31DB272860D751C96D227F660798DF696182", "noteCommitment": { "type": "Buffer", - "data": "base64:rBPwD/rJevTu/PyAVpvzoVXfM0vvzq/KMkoUqb4pQBw=" + "data": "base64:jSWPO+YedPLgaIdBsML2oPWFWyhMWlTR5rpkIjOHRxo=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:nEuAr+1h2xR92ZyWjUz12Q67+BF4asVuOY5N8h0zluI=" + "data": "base64:0nmHq174XM8mV6nYFFq5c4SSr3iYZe7PP5Wf+L1exyM=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470816372, + "timestamp": 1671691591493, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -74,7 +74,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAATqvvZ0J5a6aM85ufxYqxrvWJYgVZBy9UrsJdxJNcK4qnwx9t96fw3RSS3YK1HMD025njVZNHcMlPss3yW7VYg2xpIr3vu+O6H2ZKl3tJGZeg9+LZlRaWf6MNIU/f51zPqAgScNbLn+HY3aokooffClzSJSMTKh9Mk3ROpXE3cR0JYthmJlBES/bNkdKrdmNcR2PI5l7RQRMe/XE2sGW5/7v/oHgaxNib5LotAY5nl3aUuYSgu5/SsUSUllnbScGccazO3VbpEl6rmpDcDzu6awj3uok/RUCMf4JkVD9y81reRIaaKeFOGl7ZT05EDywMFPtSVve+r5AZNiqoO/gPF4Mxygh4lAviWcHc5SXUaacAcc2iCxpGc2itxPOFh1xkRwJ//5tnd1ofL/sX1FHqMCSmeEH7CWSfWKMj2PeiyArour9XGJjmxHdcn0IlsEA3GoeZaH+n2I67ZX4rYzaV4ePCus0IZ1y1yKI5MzGUuts2goBh4xWRPxNyD4s9F6F1SZB6UCV6WwVEKR9Qg8I59mu8vH27fTBSe262BWjjKTSWkOX6HUup0eYkdeNherOdvPQqwg88VZQgK6TPjWakOZZQa+bl305e8L9Nb43qwttnPDmOWpuMpUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwgtIy60DaOw4Bx5/qQVVPWfEb7uynhkLj4jih+cX7kkXJtX/yb8cGx1wYFYc21mOX+B29UA6vG3gXEo4eYtIpAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAoz2BNRY9ZzSLHLG+R3OfOGmb3RtK1eZc9kS/DMhXxr+v77X2ZguqZ7blPQ9ZdXYNvcg5INeFnYQHpcz5PJcISQSrFN9fMvAlG7UQCExERXK3OHJIVNcfo0v9NI3QLg8TmdJIPkVxKOsyZ5RBBdbp0sRwzCjNjxscIeyVM/+aaPQXY4lxziekcKMhiSPvag8fgSJ6ZXGva/8DjXkBG1cqsdA4NxQjC6MJKPpOVXYZ0LSNOMPNtL6BrctxGXymyBVgdRklyf1TDLQrjTEJDT8VbJKA3YFtx9CySN7LDHrvuYqBBzIaocc2JI2RMCRNtC4JRPfXVPspNyS9/fN+a8wYAFz3quALAs899fG5NfZkbjumUzTXA3Pj2pe6MEce3Z1zug7R/YJyO6zdLnLT4FE4cupfmRxudD/T8WgTPnEtkOUeRHqQHttcrJwq2M+/YXnwGw7CllKLLD+39F7J+sGNqWPARw4iX9KDSyNPnjUgALO4ItaqVexUB+BWmJHJ4iO4aqRZV88dR6zo1NwHA/dMB/w3oX5ImqzZxb6012h2c1HuibK1SmlYuiStL8apWJeMAo/3LKBb24kXo1Ikc7lN/CQ7QyXI8lYkFszf82R0mLASulVg/jZaZUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw7SbfFH14K9pRdJNHc0f4KuPqh4VGiSW3hbppBovAZTwRCAcQzs5RL1pKYKUbyg5nMx2cRpJxeR02OP+BVOjzAg==" } ] }, @@ -84,15 +84,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:7vzd0QIJBxgYqjEm6/NeVguLNtTCfg5NKHGLJ2uviwg=" + "data": "base64:ZK0CSxHguP9iZ1oy1wvqZVyxwAC9av3CPz8hdme08S8=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:yVQrYPhpcxFavyUVYAFqxA2HCBz+Q+Ht/6sjqCkzuic=" + "data": "base64:e9dMeyUlHxr2o4mQG3R5iYoRkQRiN2Z5sS/2eQ6C9lE=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470816681, + "timestamp": 1671691591816, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -100,25 +100,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAT4RYBvfSU7gcB77dW9Q+iJzUUwlOMBp/PNFVqv0gGWemLzbzkhVKiuEBCEJuyhTjcFl/sKjr4wk8/tFBBdEKIenStIDOCfQUD84KeVxLfouoh6JrjIChhzcUzZiiFbmYI6W1ZJp1cqLQFdI8HV99VQBast6uRVwCxHuYWgnNV0QHreqO0n5frao7iqFRTghLZtZQOizlQI+4CVwNHK0JbxGfebyBkGluoC5UGOe69YyGAAYhVjvixDpQqL3BfYHAaKFmtBsr2c3+EyCsWztyKJ7LVkDIdoUXjKAjLPx9co794yTxzy8ge9iDipVdYr+6IKvaPWX8fm+f2TsyWS4T0RUFgJ3U6FsD/Wc8rzH5PmpVi9BoJB6juwQ+JxC931EbnGnscRiHX89JyedS3XzA6IXDXSiTA7txW+HBnJ83AuMldxHO2ajeRaCXMmHh1b6QkNdRYfHsV9+4ueM8RsmXWTqGsmVdOpk/RTOVqaVte/8USU6953/gmP3ic3xQ9UVl6ylacaspy4oxoXpUlU0sFcbS4TDtSk7mIVYwi15iqxXBUFBPpspQH9nI9UBItKVrNri2imQU8zgoZIuksOtot22mnMtX8C6iIHYXK3DbzAaMG24gW+9GZ0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw8zLIgva9kIjjtEUjaqLV9z+8ZrW2PALpElMkzjuUXxdiKeIrOapnPMs8dKHeLgugRO9n1adRkiU9dltFrlC4Aw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAUa82H2qC2qVHzjigNoV3MbKQ76doe1IG1nrfOfU+Zrq32vn1UpZXOdPzrge+Ra67wz7UfKLQPXuLwJ3Q7hJg0l4EdkNTDr8gXNmoPTm/uy64vw5iAhY9/F9cIsU7OGjvZGTLO1lZgVmx7ffzufflqH8CXcZvGH6z8P9CQqTQayYIHwXjQ0B4UbpIVkGP10mPsoCJVu+cNy/AV4sl6zYJWafQ5zigf6Rr4RRWfC+mtOCHpy/k/HtUYdfbzQGM88QngsGA28idFvMTyQZ9mduu2oz1ejO+XqeERNj8hXaovM294GO/dcdHVmNee+2Aa2rye3QmQ0nCA9WI+0H40I2AA0QHiBP7XvVGBLVp29DiJ6fgiTAMfTdh3lC6uN8C9YBLX/e0vYW8prPCjCAmtmWDpgN8R0l+07hLhzXjjaiu3Mq6x4+V67k8WRc3jZkQzrOAddIl62F7jPplf3XaaybJmnTrGRGL6FgQ/Ntsel5oLFpWV19CJQaBJttRmFm9CBlUnBTfPwLjAQ1JcjMBTf/is26uJxmAAS25s04uerx2zo9Pka0qgfG+149iSXOAOa2WTSayFgQuyckq54ysGAxuFKZ+9dV2NnEofOkbmHxhxQMHK/ZEhkrLJElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwyaBFYFpWpE606PQIVmzz3dN4VqP+Iy8cTJ5vntZNtd06ZJtnqzI1122pbG5pucRwvaBOKYpSZWKRgilqLOV/AQ==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "51AF19D0707BE47F2AE360AE5C39E20E93B826443F828E5C7A8B2FCD4C107973", + "previousBlockHash": "5B7691CA274E6C0B61D12961EA61CCF937117B2F1908BDB8ABE04BE0914D0FD4", "noteCommitment": { "type": "Buffer", - "data": "base64:7x0CKd35BemLgIUeyvYzNUbkvDVIi6B1nRH77nIrhCc=" + "data": "base64:DXeHhFyGB7JsuLfU6BCBIjsHU38Bw9gPf6IpHGCytEE=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:XnjwDW+ksM5T+r29oQ23m5i/6qxwMgGdJn1BZnZKLk0=" + "data": "base64:V9fzt71wh9900fVmbkd5y1iMpV2cEZLztpIR15VCtJs=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470816995, + "timestamp": 1671691592121, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -126,25 +126,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAiUfqyEP0qaFslPl+v9Yxh/M8inEreDGU6Z+UWN5KLTiFla6nOIBeYRPrYayDU1VUdKp9pffapWMJ9hN2xiUfUM2ENbSUenCsDFobKY8hP2mQzlh0lEd8DFCVC9CQqerwOCJ5OP6UY3OvroyQq836eOSFnCWWS6gP9Kjzgq+JJV0Q58L8Y7KB+WX12U4tiVvEOUe1ppIDvxUUWviZW/apQcT2Yu4vjDge4cqM6DUAaNmw43MSOTpJdZGh7t08fK7lIy6sNUIbvBH1ikt5UiXcwnfJbjT5WPVUkOpjVF+uBoOD2FF5z2yAHoCRLQiI45kXwPxGXoTBBodjXbdJDGWy5fHvjMUppLT/1sj2bZt0mWqQfOXFiAWK8wcD581k19g3HHMq3QwzqZHhcaqTSZc9D6kXfEiubfb9tKSHQp2vQpPh5uLiUVc61zfq1KaoIDwJCE9II6OtRdSVVSLg15kiag5017nOwEWBSn8DdZmKUEPLiHBA5fwF4vGv2miqLBrZxDldDsGBls35Iiqza6CyxDW7D/9V/O2u9cdtOavwVFupYS4K8hpkA2jKIAN88Fl+lzBNZzM/AXLrmSPSuEIgxIB2NH/3CEHYMMPEOyEuhVFiJqvv3sOolklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwA/55lj8P7+g0dCx4o0ZBaRbZ6UQb4hzwWEvCfzvDqcZ2Ht8jyabo8aOMwC004lVAA+OI+kmFNH516tGGTP/JAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1sLcScHnQE+8yJTCFGYQuxzIT34wPRLEFUfPPSdgI1e0d+K0Km3syow+Zv+91DEdKS2esjSodSqHh5ljk0RKJMUqLJux7ED3gRasfxgWc3qwFSZ74kn7pTWtnijfYkVD7bBOJLa2Y9toUeDlpCQUkw5dEpPRD4cpcifVo7v6+fUMRvlmjxfscbLS0D7eceUPpS43EOO2UkxtnMcL8oLigJnPND3do3sk3Kv2fH8wXH2PfiuALYwWA4HwmqTway3tBZmAxdmrRR2D6P6sivoXHEc2Uu0BSPXUn3PYq68j0ghOYsj3kQCRw2G9PViuDVcbbhgM+uUS/7a2uPfqUGCCLq2Cswp5IkCYr07OBVRFSuxDOpP6m9eMgD9V3RXEWaVaXTRuXiNQ3NxpP7yYQxPNCjll/UV9OCNsDQMtCsz2/geRZcCQ9O2P2NjoVj6G+P+X/TgyfTkVPj/aF9dz4Ngq9UWfTwbRiZhIdsLpB2Lu2qJwgXvL4hLWvZm2M8zRgWlOLmxyoNBUbvz3SVJljh8rWDNfXd/dy9cIrttLY4BvGVHxrqqRAW3QfBSZ+wIOVnI17a/jW0LE2zOD7z83HWXgXel1X/WwKtmpkeEE5QSzVogoJzNcgYcjPklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw8pKfvcWST53OeIXNnsbk5qKTdbHChqF60QqNRADoIYdi3y28XpoiQZ7jK5uGSVF3fuCg6i0MkVGj/Th5LKyVCg==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "5451C2DFDD9248BF9DF51195B1F68B17A95FDACEDC290B761A2746B60DD2ED2E", + "previousBlockHash": "102DA50BC85EE7397CBB913CF8911BED37B891FCDAF354A0B7FEF38CAFF81C6D", "noteCommitment": { "type": "Buffer", - "data": "base64:Rn0T1o+UCpYSfmL6udBFpXTlanIjm1XzPxd8ov1Fngk=" + "data": "base64:pid4X3+6zXn1NEL6nu96/SJgZijUQysTUH/6tXnxiB0=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:YlgXCnQLIXpPefe8VcH5roIu3DXLDR16z9jfd5VM4WE=" + "data": "base64:mJs8FyBbse5uElb0rY5Xaw0/yXddjKU8YiVb/Zj0Ia0=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470817293, + "timestamp": 1671691592435, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -152,27 +152,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAIyBQqrf7Ihn2OiGi5cKvdf/6rv4vLVCdOZtrNOpKXseZg4PXMrkDgJrm8Ia6Dz75mX/xy7mQyb85kleZb/cagLaJMgw35h5nvgpTHv6x0yuu8hVq8/wA+B83unXUWtOuRVSP+YoQX2PnVruhSX2syZd5hxgkT0fSfY9+EMc8j8oZekin8DXdvLj6H2Xffednt14HF68FXdFC/ulsX6UqIuWL2aLCdfwIYFVgutdI+9iM9K66aFX5c7jU3sxnIeYTlt9SYUTkUs0qCeIcMTe6zbm+/oXoA1r4nIbT+ucIgogTWyD6bjifRrJmuW7Zch6GG92M3gMkhGyWYetc3cn5FQMf9QkQE/VRTXMH12d02ffsV/dk8BdOX1DmqEi3x+VYtYb58gRxOtKhybE0EpqWcOnXsl3RRFIiX9ConSK2+e/vrXHR1Jdbmsx4fUffb9h0rQd4AaReP+uyrd5NQKjdnNWwUj82wMgb43u86UDv8WHVcag08vPR0mi1Yaz/p7NKjH2hIHyIfkmepHmClVCdWPp/IPkuK0sebT5ESuJNPOH1kKUQt3IjIToYMfqXtF1Kx1TyiaJQkg51Cr7Q+wWXsVqYMW2EX0oV8SUUkw4x6Hmutv0jS3omp0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwv9mpp8mNDodzNzmYt4CIDE0/5ZP1VLqt+ihgSiwgQkC9sABWhBx7iIbBCEkaDrJJ04BDNogevsywe0McpiLACg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAqM3r1OMfMSu3e0hlQ4Fedj3J5pnAKqCtZVTiCm9W1LOhqjjgU8Na9aIKE+BdmgDRn/zHMgizvNGcnyBpCTrFt8Aun4zPcXY5AaUnFxubtkG1YUeEwkR2SE2oB1gjT52LjwCFyYvQVbrPc3zWkL3giBjlMAtqfqK71s/7MNDVGV0DR/qbT/12UHrCtgVDbf6VTwtBRkgZ8rMhiWJazJaTIq8EZ6vTYdRTOWv+AXtYfeCkDHz24McN4H/1SAZHKotEkjkM99sCUJ6/ZEHTFiEewvm2TzimiBTdO3k4QBcetEpmEnlcG0VrsR7KlFdv2DFhzvBE7BhknZ0dRGTob0ZSVyDpnxrbG2g1xkZ6O8mGZY8h5piccC1+TO3WaHehB2hoDSPC8DqJPhxQd/obNrjHVFjXFqwChjFwcBiRMxF6wYCrwHwueJZUBg+I9/55eCUbboExXrtysBHiFqetvI+HJVo3AJcBd0Zg+r/BVV5ommq27YxKOgvF4hUtJEYCjRhSRTV0hiG0JqhH+6QqfSVdI3ddN9PcNVmFExWvoIN6YfbTisaTxgAwVbK7e4fO4VDZ7IEWiF/oakaMDQhXq0A8lBI5q8Xi/e/rJNnQxPbrLWkw6+oUb0FWs0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYO26+hKqbB1cVni/0f/cjZCn6w2auUk4nEpFyRniMgE76vsM4sUIIJ8DbucY1ahkjUNxpf8Ajevixl9cScUXCg==" } ] } ], "Blockchain MerkleTree + Nullifier Set should add notes to tree and nullifiers to set": [ { - "id": "9c23e24b-588d-495b-9b22-df3d2f03319d", + "id": "6cf7f681-6503-41d6-934e-325e621ef402", "name": "accountA", - "spendingKey": "e78f98b10a27f20f99a5a889813e77ffc241f578773fef31c4a7da104aff85be", - "incomingViewKey": "0e977f8aff4fb22b41bf7029f48af0900782cc5c35d133bfce1d18d24a3e3c07", - "outgoingViewKey": "940f5d03ce50fb02826bf867e5851a30e9b31678c3c6af6d8847d13449c24928", - "publicAddress": "b5f4cba3482032b7602199a04e9a623cd7aade46c301310c8476e9f8418ebc19" + "spendingKey": "6137d09d3414857a87973fa7142a46835653ff178952750892ed9ad68a0f6b8f", + "incomingViewKey": "260951e258a1189fde706a229f24061d2f7e384b0311d3abbbd62c002954a805", + "outgoingViewKey": "695815148fa656522a2328af7eb54b6713d3fa881770788a89d5b1d237a13d77", + "publicAddress": "9553aedaa417f4343893ebb08898cd24a8bf952f5350160fcde5ef8f4a5b3553" }, { - "id": "77eb7157-9b92-45a6-a45a-97a7253599c7", + "id": "141864c0-c38a-487c-8c5a-c559425c270b", "name": "accountB", - "spendingKey": "b349f0ff05590e036dcf73973ccb033ba0f02cd419d6683ada94447eb1becf26", - "incomingViewKey": "1233737ac3ac063dae6f14561548f4de9679b0e72ad147a91c39021cb7dbf904", - "outgoingViewKey": "3dab3ce50aa697797edb5ec17c533528d7acb3dcb473ed184effb31550bb1cc3", - "publicAddress": "daf5eb809c9c8e114fd25540aa4adbf15f1527f676e52752b1b53ba4068c8471" + "spendingKey": "ecf9670527268a58c0657583873cce109050ef6845744337a548583a2b0a3b91", + "incomingViewKey": "f86590922c889e9fec3c880d544cb4831e55ff29438ec539c3d90442635c8503", + "outgoingViewKey": "d841fd5d01888bc2171c6ad28cfd79a8b1c2fa87117baa81f9e2af69c1bfac9e", + "publicAddress": "80e76dfe312a52d75c692331a946102982add6fb3048d4cddf13194486925c00" }, { "header": { @@ -180,15 +180,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:v2DZOxO94Ef+SYEjT8rXzeNDgJQH8utVpJBGVDwZkg0=" + "data": "base64:BH8COP62XZLAIO3YVjKMVVSYNd966ohcuVZyzDP432w=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:Cm3iYSe5NvqaV2HcomVZktiJmJ/SO82c4NXoKTss0uY=" + "data": "base64:JvXliH7TuTI9Zv9Ayr4iTsZexR1BEfo+woZjRawlVm0=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470817760, + "timestamp": 1671691592910, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -196,25 +196,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAXaVVrBL35flZcqpayw6ETwOqB09ePD/x1km3YSFdkx2DKu9LQnxQ6gUCLWvQgTY116ZrzrL3EiajZvgA+yzhJIGVfF/XJAQFUp7Fuf+7mgiOklAQopSuZlFew3kanYgSsW0gpDuLQePiJfIracPssnLo+lkXNCOnSqh8USptOCAUtiJnmSiCfgfTtQqhQWWnqVKiwOZSaOheheaCf7e6otDc7mxiZWr3tIiw3ox5g36YTCFCn1vMjLZBnJnlBtCHW1Wnz9NFKoEDc3+JDZ7BqeE8OuXgeYnDJVNBCY8pMY8vyuNMwagYPagtd3oEdgexw9PUye803YhwPiFPKvsRAQP8gQciKz2mWpXNDXZ3RCAzcPwHpjrH26wfNZK/ts05JykXwNlDrNugZT4BlOBVmV+sePbL803yM7lI7+fM4UaBAZsuk+tm1aEOzB0+Q/qPvzfnUK70koMxZNJeeXSUP0Y6TgBI58I+DdRcxilLr8i/BgVGbng+bcw22b2Mz25O2umwqa9lX0+JUytCTLAPU8opVg6qkZRTJb4RQ7oCHG52Z/W9erRrdZiPV6WDfz+L+cOREXydhAQluJPuT8UOC1KSzsQ8g3ArkMEb4AGxBXkMOGMAaxyR5Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwineBVW6GZbLPCtFSFlix+LKY1fKXkh/HTocy8uhvuOe78zVgDJDEDcmqeKvUlwJBiNdhz1ndHRCSNqdojaWXCA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAB9+4K4oseR3oKv53zirqZl3kiOg0UKPD3Uha03Zq6I2pRF1TqXBHEuhlPWJNEt/jabSm92kAEuipt3RhOLyw18WXP3zvG/BZAdHgzBRRYCyFykHjaCAm8Kl9Q3hzD/IJZFGz+2Hf475AQtT/Vpk98lJBB0DmzqnHMCLa9GY2be8DkGBK7pqv2VTPscq5ZNro4wm8Wqax59FdnrVuHtu/Zzl+egoBUilKyXxrhgKGjg2XUafp8KVJDFLIRPD/HXetwQTMP9AxIuu9aQNSvKkeydVrbU2TXfRONx+MBF8e8wYxH+KQ4Vfhhwru+bywUuPurwbC/7+aYIxhvnFA5/oG4jslqGwh/rvJpUt8KawZnWtd3PAH6YReEyjYoRdfckM7Lv07D9JITP5NRCGNOo0byqLsmk7VWmvexCerfcdxwLvcC/gMiKF3rUMUSy0cqgqmTjmHcMxulupTXXWFCsRLnNYyJota1kdsZoBElQwPi9t9nq6vgW5rX3AVfl2k+V/LVixlVXZKF0rVj96WlY7ZKxF41LJu+ItuDmFyYKYUuqgSsSNuo7wpcz3LA7+xj+Z1l4YxnrmTrCQhdBY+axFtYzU00T6XMZ8DHiSeSLlGstgxXtXHaYA3N0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw0ua2k88REzAbthzeVQlJzMPaSjc2P9CY/ZNM7TtoyTZDB7KMJfb8iWfsLePGkho2SJVF3PXrDzJ6fJmFOWaxDQ==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "F15650DC435229CF0337220068250128FCB533028251FAF851625594DD1C22A6", + "previousBlockHash": "C1519072881A8866DBA48C3862F76943A9A3F34D8D356538E3AD2C4D95ECD919", "noteCommitment": { "type": "Buffer", - "data": "base64:JWJud/IpaBf8+Lf9yBvh29C26H+9Mk6S9Fy/tfFvJlM=" + "data": "base64:SR+miAp2ZRFQ1lgO1chwC3ndAtk+3h57Y+chCAA8AWE=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:sd+LaN234xcLbQ38L/x3LP45EDlK047Rg5bXSaYbMtk=" + "data": "base64:e54im/nw3//sz4wtLBAuUevx52p8gR+SHD2pXXQSYj0=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470819445, + "timestamp": 1671691594571, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -222,11 +222,11 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAA463J8a1Ldlz5adprIiJxXSq4dWD2v7eMZf/c12fML4KYoL//8hYxpe/HDoNAYraIu9LVTh16VrzdSLIw9SaV6UvXNndAoGQSmNIcwbyR05aHnCyA9b8QVTfE391SmdjVcPWQMRsTeNMjhtIr3oBUI1euM0Js1booQ8WU4ds3HpwH1JmdfBHPQCUudaEw5Atw8vK0Sk1Uy0s5CBrDUonAzvXAgocuW6oWaPHgc2R27u2UhlYaNOATNG1w14VIYk4nIaXaoaZ8m5GmK0A6KewdSX2L4cf+sfpovOtPyzksI+L6GvLOq41tpnSoVDz4NySHusBVVlLUvq2hglYvfEYGwoXZcHAwcAc2NZEXXYZUCVHZa2dn2hVLlHedEFQU3yNleqy8DNP4mRmbd9RBeX1LOA+W+rNJj9G6eyEEKo9P6+yHp/NDGp0JuMQj0ZDLuZ9vlMnOh3UiwfLtsRq9x4oolxnQ8ZEd9qVFbx25tlBMSMCzkXd5wNmNDroDCLUxFwEnqU5xIQgk1OYXmVn5uKsAJNjfcgC3aXgkCR83X1HwpX43Wgr/dcAPQ+oLqessLoeQ0nYsZPbQR8oalZ7APvv9TNvdZf4CTzFrV3fPhvbdzEgKoEckA+h2Lklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcmXQA2tksKsuNg50Q6jV7wrUGqlsLg+8dC5wA5FTcRM8RTLpDbGK+QotYyWWv7SWxwNhF6lqkosHHFSa+hSQBw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAArVLnFDc6kWmApeFoDpuFejO42XI9Ozm9dKwLWFdG2KOE3ThaHnAoIFhx2X+sp/lLTCH69C/cmxcPGp1rlU89Fzh9B1+J+NWyJKnxjxdz2ZaZprC/dTOeC5fYlhttPjSpjsaN02IiUXSQUr1fJu+UG0eTlSiEtejwql7ELKYoy5EUjEOaDAIM/Usx/t+IwEkNzOXL1trVX49F/NvonBKkWfDWQ8oANXOhUHozgyPm+AWOQiZCldEVOX6b0Ct2wQaKyh1M2BxgEGtVfVM6m+X8CP/i8KezQ6vebFMmTZSmvotdlcSirxXBeDDVQVx5xvkRwoV9CMeUb6K6t/1M8HlxIPnDwkfIIB/4kJpDy+yDsvoDGXfiUNRzMCNfDB6kVD4BTbIiBQfYQKu1MExINUgCC2k30YTZdme29Kl6f3BIn6z71yZcczH58rTM1zZ9wi6qGxTL3BMnZpOm8vJkyPxejYzjbK2pY73kgBU93MGYhkh0k242bOHJBZo+w+aw6BHiGTEXhy2JdIyKxAhB9gz6PsGa1R+lTONV6mqZxat1SYG0puvtiW3+gWgad8T4vHPji2cTFYuxae8RiA3pJpKd6HZ64jQdU3Uk0CZPSXgcFiDsWL3pyiZj1Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw/KT+x7nCoVty1pixIM4Mwi3qiQFiQJtMLn+lkH5r5Z7rAz/6jrCCqHLRnzDlhrfqrBHpU52l2cKznCUpU7q5Bg==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA7wWzuV0lGtfeqHuOJwFfk0IRiVuMw38oov9hX/LO6V2C9jW4ypvlIDg9SxTLg15aNqK7pc0+M3NGP4AyLZLDxXsSbbEHxtaX2BCSoqhx/N6uKq0KTF17Wc/b1yRwvN1gNJtVWaGQ4AgOx7CAWKO5tnaD+PCLbLVPyYZPwhbUv6IQsICKIVITJBe0z5azA4hrwujaeNxGwhzASN5ZHGfTEX8JCTvz3IJgGPCBPMjDmHaDa9JrB3y9xIE6Zi7XkI+E/OuzXrDujKdD5QfJAZLbj86HAEozekXoLSY0ECbJE3td/NYACNjopWtbRQit1Rif8IyOlknPxL19rOwJZ6fGmb9g2TsTveBH/kmBI0/K183jQ4CUB/LrVaSQRlQ8GZINBAAAANZlHR3WSvr1iGDl5KsgINcUe7cwpNnIBa4rwRVqMWJBwl6+atuOh6mXtJlOP1wgGTxw9gL/X23CcN7RWQkZ21rGqyzsik4dv/aikXOln7QENhSPKWrGhUDLKG6PURJYA5heiLo6BNi278KkxvYWFZftj3Y96tM5VTOdm/FxBvd8VxgefwfKGAp3jRzYjypFW7YMIO7erChq+rHWJXiDKlZGOJR2WrrQcdFx2TSGJFatPjns8AjAvePRGpwSSh79iAwVvTXBUqF7YK+TggaJGZhE0/8Bx56L3n1s679g7NX7+Td1NX/mwyPxoYNYLHLZ9KyrkeYt+9fsN9UArxEnwb2CjZd2LHU4VxmGisZQaZ5ienrS2i0rSK52b/JsTHok82KvXeZXSnnPK4NiQ2HetCBXjvCr0YyGL1EU8/HqbpdV75acTCAk1qXkAOGsAm5hOHd5QjABOga9JeNlwhg0dDpAOP1ijHmqTszM8iuB42MeYy5yy/Y2RXENQ1Xa44TYCG6SWU39ldEUfbhlber2Wj0bV7TVpE+zUQdCcE2aKL8d9QMCGmlkLd2NnSLGRk3ZQTQCUZHHwfUSgMH6EByi48cPW3PzAD5mBKyffSTwX+zQf3vmUSlzoz6M7xp/n/htnDoE8fwn8cf5+nj1vQKpqK9hv31YJvm7lg1UM1k+1gelySoer8oF400TVAIHN4SsTgLbB+lMiCRKYcw668swqZ9RQM65++os9lmiXuMhm6NCWD5EV0aRuDrCXxqFr6yAu6SxVgMKDuhTf73Ognd+Mx77LdlB/wGxAHdmDOGRJO1gCNGBI0rIrU+TTxFSVP//l4ow43YHwWO4xPLHVvsywMFMfcxk2m3Ugp3BuyZyQ3Y7xu+hdcs6+dKjGEcSmjKVIIbWqPsbU1h7x7fJtmzYUnesv11in6+T1Kc5SpfP94FtaWSfM6gDhOYAFwdsJZ1WJ7hluxmghakpxtB0HyqpmpMFaIZ6ANMNQSck5gYI55RSIN3A+lWU3dihuFq3j8fZzy5/5ZvuZU3Al32GG2aJTbX0g7vWveLzFifCr+2m1pfmIXOkJggupTPDjIryyF+bia6GUCIiUZUTWWGihH58pDhR8cSSkJ4/UsToEBb+PUjsXrInuh2y3JN5FAnDhMPic1TzViCniIYH4lNbLZB3FFuCpa2Iy8+0xZ6oQC9H7pJYSG5xvYX2oHGirO09ojcJerUOlFJD66y42GO05iP7LWdAxXrLxZq0LIzSctMkxPNN4gLeFEoKXIVH4fMLdSi2IuKs2lnUXrrIJINu5ZfESbs0FVPIU2xnKipWKAcF0NSWtiO4ctk6+tRS4Dqnp5T0SLBjppy57i5Z7/mWReRlHP2rDl/ZQDpW6NjK4eBkGS8iVNrm56TtQgHKBMiqg+yAOjg71+zrzRw3jLH1etJfsYQVVa/iCV9x+OODK3Vl2KGbdEgC8r/DDTFcxAeEQdsw3HMu/i7HO44dkRgaBxp5MTv6lo6pKnZQA5YwbNFJ9cOoaHU8SjMy9KfNLfACepGnwO88bEYvDa/yWq4vxdGM6kuTc5lP59EZrNHuFdY5ZTWGI6gCAcuMnHIwJEVGyJ2XCw==" + "data": "base64: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" } ] }, @@ -236,15 +236,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:iDAb9MA2jGY5b8kutDvKUcEWk+3MPv4OY/bKdZyhYFM=" + "data": "base64:4CAgX+T6Z/mtcCttKY8pxnhHtGrR3qc+ijXNBUsDXGk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:2bKsMHGYzhMQPY6S0BOLYfvfiiLdP5j7/E7cPsafnn8=" + "data": "base64:LJ4uzYnGl1iOoXaMyvwSI0wzA8OcSbm25ot3QW2FCD8=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470819756, + "timestamp": 1671691594892, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -252,25 +252,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAuAi1k2BDqQBudWcwOhdz0rW6MlQ4zQ9BUVe8n0QgirG1HrNirY+fGRitmAJwpa9mSnVz6geWeOxUxZl+/WOapar2EJrR3slldjdmXDRhCKSkWCuO574TzO5aOvJ7rU5+bxNWJucYaYIbq2VrBCb7fODM8ATm7uZmh3rX2hO3rbkZ0WJqypZKYubysXo5ZmTt7+gPc/xZphpqjLtI/9AcrdKd9DQp042KNr2ZpTeVCjOWU/m9T0Bhd1voijnHXLhBcllKd6T0cSysGAp4LuAxOF07+PwH7eJyUdaZLwuzCLZdE9PuaAM9o6GLnljQKYNKdXgslZbXqtfzepS60KYurhYmvDH2Gp8KWOxwjioBMcrpIV3otlzBaOKHuYydkUpUQ3Fvcemb6UDHY0AoziGkjWirkz0axGGtWSaEnKKxD91A0WRwQipb25YOUhHIKrgdqDG6nq9C2oX/4B9kJ2zvOSEeRBwwiZoUZTznVH0CIlANrNwQO5npYedgtINz7h6b9tvykOoY1YTTtIuNlZ4zU7veAgbjqwUjTb/4ipHt3gDWXoYEwWNVi+yVNO8lRffgCwTOtznbNIyDsWrbpiGXB/QXq/zD6bOBwz0CRopHbMj6T5Uli/rqXElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwlakytoClV4npXPrkDnOXeLaW/Ffzs8M+wvTRCiq+T8EBiD5aBNQnVRG4AX5KNIpY8EtUSL1A64zuyY2HIQtWDQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAWDuQdI8tLCrYeKt9PFB5RBYm1HsMGpNflHlP8EIFbJyjyT02UQD4Ctcx6msZUpLhzPsNHj+n5QlA+MPLcwMT73yVTVuCTo4XKIDqfndNjd6F+irBSAS0fA+06DpHaTuNQPdoclipjCo725sT4eRfsQfYt0t81/LwyaN3DzCjmoEIi7Q0+S9b8lvPDGv3yoIJb1mCUE8U2eLA7MBt+sUBXTS2BK7OlBintaWhj2WimDmkG0YWq0RYHw3m/C2YYJyIRQsELIjcGOmygbuSrr6VolQDnK+1yZzOTrIs2Y80Hfo0GAfwNdX2KuLvgKtTmfFLjXxNImr/DcPp1Jug7cxyUF2/x1xS9B56hB2iIAu3DqMUYGbsnmPmmVif+UJ+WjQhrdjXe1sp75RZsZGUUOC5JLIhRI3l3EhxBi5vsGiZGaBPBrpvWrcKjhVgEv6aF8PXLOo5zm8qe5dS8WlkES89YX/0P5SGlwehe24RTzRmwY4emj1oqj4FZ3fnRcsX+3GUYzRHY8zhlcsN+FSyZLaqjkShpfUi8q1ja7v/k6Y4HQ54cZL9HMc1fgFuHqicAjo3MPHzJ2fsQMUng0uda74p4zuMUgEQoI6CwtKwjc3u8++RfjcKaQ22NElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwVU4jVi0WtD4Ft+kbZRAl7l9cMhNfm6glTjN+5SjLDa60v0E1/UJTQLYuUdD/dgWbFz+wRHc41p7o8JJ6pZzdCQ==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "731DA321CBE0F48D11CC242024D42AECA5F002152A416395D3FF6F0AB84D9860", + "previousBlockHash": "747347B8C443D69CD30D1A52C6C29E66ABDC7738B42CD64FEFA907275A9BCF7F", "noteCommitment": { "type": "Buffer", - "data": "base64:FmgVVhzgsTSeHJvyEJ5p1PnkH/xCZHz71GrgrYMTAnI=" + "data": "base64:CIS2CXk5woHoNBoNfcP8kHYyEx/bh4tf3iynmtFOfms=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:pZCVLNEoT/8q01gxSV6SVRJnwfaGf1DNSn6o/RWxxJc=" + "data": "base64:TISWPZ6GawfqRlGZ8daSueL3uKXPQ/92v7+aKFWL2Is=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470820058, + "timestamp": 1671691595207, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -278,25 +278,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA9T8YWSBuKkdhfslNxrNPfh9fBTZZpvWzxfpl5i49gsqgN4SUKhCRzTc5q/ZP5QhsqFlXBcQatbT05XB5k+2Vcg7p06yJD65nDJElJQaq3xCFrjsGSRUEkhZeprfg/vLDLma8RWVw4bSBsAFcwjbmxYyGeW2tCcu5VF+sx3BFaVIQJJvdeIkBJwzh0n6HRnFV7MpJsfwl6loQ1OlbAznNfPb/rjoyyRZ4dfweeWt6KM6qYi5wqaGpSsiMV589p/mO42jpqSXZtszFIFb8/I+2Jo1pKTVRYA3aMCqBKU84euhcYKYc8jfTNpa/rZp0kRPsURQRfga5LTMfu6fFOMaxhEEE5q8aI+f4OHUf825jxVj7UofNyTz2C0aphZaMxp4OE8rdF2Ycv5JNT4vx51k9oJrfY0MCXjqqdukPb7PbyDS8Bo9ZMEheC29V2BPBWSQDpW/WvrrT2RblxBh1zi7DVlfCTsKEdY3yJ0ILt7loj1nHzZbPor8OnJJ+BZ/HttE4L7w0Heka+6KxHF/4L5B+zo6vdn99CQdMjqPqNGpmdscnFKdfHRILbbIP+WWpM03+jSUopMY/tWQEVq9wYivQwKctfFa3bdaMBcMp64Rjsd9RLPRcbHmj/0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAkthLSDF1d/eP+h+OOJnKpm3RssKfJc/4Z13vQZc86b3egFkk7ADnISql2YCVFkcAfcnm797pLIc79PHW0X+DQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAp1jQe5x4r1lNs0smiOo4l0lylBakstUyAxoSzIWT5ZmAnyhpeexeTmOW0jRFiydHnQc/h2vckncB05NSZeYeHUpu/09M4r+U38rWbRXUsyCsQ/T+1LzHXOFjVmLDAh/kEsIdft7/c3Ax1IzuphWs2r9kx42s/00SRlyxD4GM7pMOC9tR15EY0G/CEEn69LVKqa2mnkO6uzPSjA+0SD0iBpp6dFEs0Eb+MFClXi/SttOvSD/0ofF6j1aT8qr3WkYKMMsrwBtdOZj8AVnJLomS4rfQFzHOP9rZcnbsW3G1VgtkO54DABtJeIdt7T2yAbE949KIks3cXFAYdapLrG3q1x28YTRCp0DllvdkrVP/nXnsrzv2GJMS7WiZi26MgItpF4V6pslTzLIuBzUN/3gga9oQ1Wv++aB9NbtnkdqlPgYZrdiZd3QGhnk2T9anL0TO0QSdnV+8knZbv/2VheA5FB8tlaVC8ozJmVm5JAUnna0shOBTFwNMbcqQhy5GKQ5t9IJKlmswwu4u2n47im+bZyYm/GucyGsvRihKpoiSvjb5xTD7+l4FM7xG0zbdFBP/mlzxJ5KklU3Ct6Xea2doBmP+D5qhMg64AMOi77m5pLIERTLMKp44RUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwWAjV0Q6JxVUVW+Dcroa8dtCZ9NlfWTbXoA9r3l7Gp/Bx8U/i5UfHFbQPm1DjMlKwaTpCdgC9rew3UoSaWgu+Cg==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "5A65519DB7524A583DF68DEB333157D94F62283652373992253E447102E5E8E8", + "previousBlockHash": "36F99ED8DE75618A8374773834984E37B226A3F257B89EF4FAD33F70EA1AA6C8", "noteCommitment": { "type": "Buffer", - "data": "base64:xUSa+rALH9xeW8uJs5lwNwsnDLPNzkX8r7TJRZw8RS0=" + "data": "base64:r49YCZc/VquPdVlIEmc8Gf1I3aYgxxP9O4+yPxwD4Fk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:TvSXjawM48YYXn2lr2dgRX/2tbmDufl3cd/EMGtX8Bw=" + "data": "base64:O5ShpK3vY1kg2N47iv8Q5KaLfw8Lr/pIryLMIzB63+8=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470821744, + "timestamp": 1671691596882, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 8, "work": "0" @@ -304,27 +304,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAANGTzsLhb3adxDItLQjU78qHplewlj48iVMevJV/VxUqz1vOBXz4ZguV85CBFP5F9RC3XZDSelnx4sjzkMNB6BuYlbCOTfGAdYVOp+rUNH5yQCm2j36zHltgK+TNhynQxHlEszjknjM0jo4G3VdF97Nn8x/XPHNpEr4i4TPwQRjQLc66fUipJSpaXfCjS6ufT8mHPELSQmCAWKXoBmnfTpml+Ps94mpIT+OLM+u6KwOSvnHhRd2ptIBHOIVKxnR29NbXQ+rWGm115qVi9AIVbF8JDm33ZnJ5I5eQNSFVPZXHXpL4qz3fxwRs1SREMl+Fr1STRJMaPZD4nAQWe4/GiZ/L6HaXn7RvbuRlg5aTPa0/BN3Bf023GMYDld6duN7kXYYwNW4gBZHRLXXeRoKC5+HBsZXIfeXdcxdXFyVErNpl+h6Cva4KV8C1QvaE3yr+WVSC3MGRU3u4//aVNqxYcF0thRPs7QMYsVo0PSHOIKhVvWWZXMTwyPwOYOiPiCifXaBMop7Vz6ozfq2Uf5gKTlsyXEWYYugtaeql7dWnaRoDhj4mZH6qkfwn02Cqb8CIcS8Gku7eWxLk/IoN9X2EU4GUZMnZ8puZkuVtre8G0vKF9AX0rpHh1O0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwdXPXeQOoxPLRF25mcgv2nB8OjFrI4Dq231MMfqGqGdW0JCR4xWfg3/pI5bt4oNwo/9pGb6sS33yfLk8sBQwoCA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAfgr3MRXl1WPKtGad/kDwbLYMhwp82/mUxMpaN1DkB7Oh74eooODiuYlQDvXcrfvF9KQivBJ5GtYYRkQycM5HtdBOBnavdp5iuyJEzyj97gup1TrEYhruBj7IT4EtlX7xnN5t8PLGMw2Tl8l761RLlLeEM/S/xq9MsVHL7UthTeUBLYV+0HuGC+bExKXINAG58cxh5ozyE5NElYQ8MsENIryStPGrxeseDZk9wS7x3dyMm+3OPSp1MpseD6lYUcxO/bo+yjrERtSz0Po3wBfbEMOZ99oEXCe14ym2PD2jBoAvt44rOE3j1LHv+HQPMJHw/1PmgU8t4LYwscD87zA2Ok2W1+5F+D6XsejekSxZcYwxGu3B4lvX4qyqdAwXTQdBwBnqQDRCO0I5df0+ebal2ipkUIublqXB96CO+4NXrRXQ8XWFW7XTGLde5q6kYPyvMML8gStLeobe5QoZygv/Zaz7jin9K8x5d+G13dmqBar/oV+29+2zxqFK/vMdgl0TbuLeQDOmSZouS8KME5EJN8x7oXC6De7igZZp9+X1K0j0VOFXz5lfyOBXXNDRz4CERVzQ/kTOgkDvOOPzNjp3VxG6rp0cGfch2X4sqMz9qTo3n0+TSaBL+Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSSYqQk2WaqPg0L4iUYLdunqF/Ae2rEAjF4BgMFTJrpZ/dyvae3GmNm3FU2sdwYKLB+jca/ZPphbMf4j/nvwhAw==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAf8PVAkjdL8aSqVqMgouhIoW9SHil5NpGOusFVsstf0+q4EZIqMl0nUHYYRluLaeCszikGX3n33SkfgKYVEAXwzilQVi/cuaye03Sv1j9jMKnGM9uJE0Cyt+8PkuETQ3dpDukwovmvcVJFgMBURO1wYP1Tg1AFECCxmZpkZfPwJUAhu5obqrVoEmEAsU8VlUuJWxIDG3nd3yR2NF0OS8p/9dd5uMbKjinIDIJ782665GFc7KXv1JymoasEECUD2CCrnznK//UBDLkJ/aLrYQHtxquuIH52JdytfxuNaYHW1zSl+CxSz5BNV0DMbldzIIa6pFuR/FEH89N+FHt/3LvDAiEtgl5OcKB6DQaDX3D/JB2MhMf24eLX94sp5rRTn5rBQAAAFyiINrr4my8fEGe9x3rMyALaq0ymmthp4q8EQT+fbf7xcdWLnfHcH+z0jx6MDAfPg7+fwhbG325JLaiDa7wUxCehGi4CL5Hiao+FlXMw+oClt7m6nFBls8eY0yWYmSgBLQdYLmy3M/t6sUkgByBvV3qhj+hhaRlEH4Qjx8c+he0JW0012dNXzAipzpzgp0CVJZX1nNZofHtRkUG4oYknBBCRPmQVoo97wZ/Ye1pCXzfBmmk+aNH5hxiIlIo3l1PfAC2v4R2cjWr8S9y9RZhKTTCx/vyCh1OfDyeTIB7h2KlZtHVtoKr/Zz8IeQo5pjzNqFP9b6bw9nEDpHjIui8WaQJOcFZOktZmRxepSctLtDHpcpKGaELNUTFTHK7GFwvfCdegiyRqFtC4Z9cNhpPRy7axtQOCdukytO51H0kINAGzgLi3yxUMHZKZGWz9RF9Xhdv1CeksYCr71OCoxB3xTyzhG4GGBB7cChVRIhjimHmPi/Ne9JKficpDvz7X9qVmyOObwn14qtFy+uwg6a8dLvFj8Mg+wpRb98q0iQk1In3yWBbv6fQa1cyqKqvTVet2D7YLlP9VA1IGYIN+bX8H1JEYlKDMD4ANDDv4EXbGHnBNYdPrwcVTzVwoR8/FrZtWQmBqBvB+CfAqsPW+M7BWoQee9vCd76vqBWTtUN40UA1WYlEoGt4aO0VKAUzzimwoOduPBKHSjHWn4aY/+gZXHVzSgoStzn0pKmdcW3PfXDg1+nE3ay3zcTHwBa3ZlV/Bwdc/POjFHpQwrCQWT8gnt3koPJfYg+oKnJ6EF5G3aazQbAs35aD6GG42lgmIW6FhA6zC9Y7DLkBl8AHAZplJzB7wCqEsmUy1dlGdrTXokF3NT+f/6hwkQ+LfLUU2AHS/XgSBdnn2n5aspzCOk/z8PKHq5Kkr8D7z0LV1ie4zb4x2/IYtW5mJM8FW88n3DtcohQqfFnxkF2y21OJ5aFkNQzl1iu9ARXJaMg4XUvCJInxXu93gD5PV3uvaM37R5ggDVMw9UhKRyyocQ6oSPrMrdPoasntjnlGcxyG5q8FClfhyfgsYEgF7/RBkICACBJHHmCnCgZWY+UG/hni1U8ZAQ+ABZwRgX+J5ThthT21ad8jtAqwJcDjMmotwWBXk8GsAC9/RKH8JghKJgYTLY4f2hv+lt6w70v6jX9M76Gnsr/8hpo2pJprvYFagyE+NtdEkbUWgLUGymby+v7wlZxdcG8R91CTWkDDFehXgQgrs2pFWW9vx5XAtKbJFb0aZd31tPkqO7TEkPBY2rRwWOimwdN1rKxcKcN3d+/tV7zj6XZIANufnOwf8KJGqNya4ORKFcW95C1xPJQ7ClmTNmaDrOEF1hDKtF7mm7xcdJB5Z2Gr6JwDzwWmS+V5prylMR5lBKep48VICax5ORGpw6upQqsjTPu7O8CNJUvWq3ufpAOsOgc9CYx7JQ+JLRNi/w/rrTTts18oB81UZ1vrM6coahRKzMCL3pKI4bphJRNkRTHoiXCz6A6eeimKdoMkqotFtjaWtAgyDCMPxT8LCFnzroQd4apzpjCEg/AWssYvvtjJ6afYfRDlvuHiFkvSvU+/BQ==" } ] } ], "Blockchain MerkleTree + Nullifier Set throws if the notes tree size is greater than the previous block's note tree size": [ { - "id": "aab2de7c-b36d-4069-970a-f8aedd8ad119", + "id": "3b528043-4fdd-4fb3-9087-6e87bfece89e", "name": "test", - "spendingKey": "4680a4daf57e7e8a5d2b30c0e2f4707318f1b7534ab2f0f2eaa4db77c4e8f078", - "incomingViewKey": "ac334c80d692f13ef92d414d81db8e870f75481777257233e89a3b522dba2805", - "outgoingViewKey": "36e235dcf6672bf2dd900f168ae111a5425e306ecbff5435cc7b886b547c0813", - "publicAddress": "9eac7dd14f0c6cf088eabacb414271bd5c4c91c8126067dff67b6ef1b5599db1" + "spendingKey": "8e8cbfb20ca356ec33f81ddfc7167a0e82f56f0632f2c8120a82a2df83d37b9b", + "incomingViewKey": "ca6cbee44b204259779ffb02acd0f6f2b0dfe3c478b13011a13a71e58110ae02", + "outgoingViewKey": "4c3eb4c7fda019b3468ba581043b32d1c966fb96368ee9afaf5615272f7023d3", + "publicAddress": "87c5ee8518b7a91f8bd2e27380c68bf33c5818b4c58be4302bfb755e60c0dfb9" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAj21cOwDFfko6dI/QKdsHi4UtQK14WmDZb+DlPLRHWyWhpwmnzEnjM0Iz2tdaB91uy3m3Hj+mNTc341s9uoNyEutHt8hg5H7O6+REq23PDEqVZaRk8xk7SYKyBH1zo1w3Bn/+9fdctyGVL/lGa0SC1QIuUV4bGpTtljCza8xpiakX0d1/9bSF2n6XMj2z4cpNJyqyIAZ2QqTV1h7PgUqJZ34hjTix2t6yATyJtqDe2JWB68q0BBc8i2hfwv9UNmLYSWb/1kioY50EVUd11JXrYDPUtIpRX1TUf4cvaon86iojRVpnO4MLnnfWy2TtPatNPNMpXjy/9n0VV6QnOeomwXq7XGXigKqCzk/B29oXL6LdLUR7ootv3qpO6238ejk46PBpRXAE/tZIUW41WxUGQHmNEeTcnKv/NRhvlmHmkK8QrHYSswLFKhQxSF1iMvT1XTqnEAFdqP/oC5hWDZVFa/3BRXuV2lPML0SIWhQ293t/P9ki/eaH7R8BU/kMdvUfnKiTsHxtdUWE419ApYVYZ8LkiNRxcB+Ue1cX2Sw6i7XhyimRGaW9mikHU88OYynH8lHv7lc/HNYUKxokirr6dIqEEWdUDBjTzQ4uQEYtQZSWAjwjJZ1EUElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwScR+zZ2UFX0EGmHCR+KFTtiUO2F9cyIClgfPkbnuSmIm7ty19oOMzsSiOHrZtBq44M0dJCURe2FCGkNcFTQwCg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAglRWgW48Axb+Lf7FFDhQzT3Q1p6kmjob2lGmBOE9Tuq2pi6uvmEAOpjQBBEeE3fgNoAsTfFJiGf1Tza6bx6wYA0UvnQ4OG2E/LObYjwrrRCVcbvfgRNYNczLh0mfOrdzLwXzezVVXkf6X2TK45Q2w4mriFEiL7SvZvYizfKNdyQVtOHq8IjOVAiUwpO6wd3MtUDFTvR13Ia8dOM2pnk0OqUb4c4KXK77UJuq0jFjxUC3eoyXSRUZc4gNkeo1/eYuNU+QtVZ3B9bv/11QNiiTf4GhttcpHdl91aV6muPENR375nwkEXZLsI8ksFm41dhStKbTli8kM3W4apgcI5KazJUbe4r6bnYwf8yFPFPNJcAT8CX13qn2I5eJHqxz6wQGpa4Nv6sqwakkBZHeJVUZ6SwC70dnL2BPU1rxp1q4/mkh7K+y3G14W0Sqykr7N/7hd03hFudufx3xLQqeDGj5UWglqbeoqxd5bPq7i/rqsRb9r+bfOEH0MnVOyBwCVlQUcmGtjfWERqIRVAqrxZy0jakUWAcKAZFt4iWILtgQ7jf4RFya5Hjhc5HS5t6Y1zjMRGW4ms1koW5aAmN5UXM+ozwoGpI28nJg9PCfLMtNvD50EkEjEKyhoklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCR9kN7sseFLOCW+ViPf7vKsR+ZppR5hSkDviBCf5p46ewwV1bTl+Q3N3fIugPZGa9GGtWVo3drjQHlu6z3JsBw==" }, { "header": { @@ -332,15 +332,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:QUjoeAF6hmvoq4Sopc6pK/gAW5E+VoLEqYKLBeOMmFs=" + "data": "base64:Eacc0TErTEpxkfar0WAUDXOYUtVdl9kijUkfek+eEQQ=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:yrtK9wsAZ7QbEdgN1t4Xz2wV8LZV1wTnQOGZhLjhUxo=" + "data": "base64:q5U9C0Pn8AegrJzKhpuuDcnyUddrlMnSSieXTuPZjfs=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470822477, + "timestamp": 1671691597587, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -348,33 +348,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAUA/ss+mbg/F2Rbhfi4ObGLp4sHvdcKzJhWxEGut4ooOnJUmyBku5+iM+hMYHN2UYi1BYS4njWqNVKYyZFAgcwS1AsdbzKh0a6IVCBHBGVwyDdr6xdaZZ3BOYsiDYUvUcqwPek7NxFCCqq5MrX4ZPTj2Ci9yFnrg1zs0umPULQyUVCUqgl4kls5hDwM9iBGadKzRg6shyFAdHMugXYx+KWPUrmmAEaCYZ31F6MP4LUVaFUEucJuFRwWATRYZMVkFFsQzbogb2xdCUX59ZcXH8WIFvTOV5P+4dxEQ5lVmED2roz80qizIBxHYb9F3qX37RTXjxd/um8KfwWp01K+DDS9eG71oPbR4nHJPE0gPalIUqC3Nd6tyhN764lXKfLFQbOEXAQxDVLEbg5yuuhfF6X/Cs/9lsrF07yKUx3iIKdi1eO4hhBf35hwaB2zncpdIbIVBUY7DM/XW0rZ/u/BSAQr7+vJJTmCptkzGAi6kQGcRPa1eTeR5+fmOLfxN+Jt0W075iMl1dSYjlB+tp3xmo4AuGkN6n8eZMhHGydQToxanVmBlSzqjt9x5Oje0mEAJH9fi0g+up8TE0RqYHSEUXd/9jAjjwfoIn9ub+Dk1des082KWte1fUDUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwsvQIulepZXAMjkqkxmzM+X4x+NM3hUL2O9WVzvRzr43pO0Fe4NcEuy9wXjZxrDos9tqjweWgVWgs2D3leBokCA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAjw3T4rZHKDenTIO2Q6au832ll9D9cTjYZG8Sw0DLYYy2l0XwadRammmHqM+cj3648FXtLn49GU9bSNz1NliaU+yTT+2zWg1HU2W5oglnYNywJ9vlvsqdR6CKjEfTvzgxutLnDtvvmCx1Uf66oN+kbpbx3gYRBoaXSBCEEWKeqIgFBNfR1828aG2pr4v8EynL8RMOfq7aBgkyjk5cCfAoXUM80FG4IKgczeRNg3Izz0yVm4DrlO2deCmOa993TLRAvWtVplwICAe60YyRAjcfYNyGAxqtzP8GOL612QjZtezroC4p17BBQsiLIENAUCTvbYUaIr8e8xWgn6F0pz4tbVqjxgSbhkyWOwJBmyzP87s1AsiGwymGa2bK/yIwn1tA3NM3V+m1CyaCB25qr8HlLV6hLAUP8VVhX9Mv/4sXjrVXWRrPHbeEYCMVApeTG8p+ZjM3+99KebTAKFsVAGV9oPVIDqFffo3+kywXOEChJ1GdxdFZst+tp+4oJkAMx/jwvciL1loty6VCLgSOgjY1fOze3yhBoK2JAaxtppJii5bj6XC/TpyVzU2pvoWX+YDZfU1jJTtsSWjA5yeXm6cESYvvmV0nY24o1dn3H/KTZID+EsnBeV70HElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwlnd3Q+Djsgtzzt5qJvzNq7xUr51UI4ZpRc3PAsu/fYIRBzyD4Am/0LQZkVmrFtS6/FwSAxb4S86iCLbvhkNRDQ==" } ] } ], "Blockchain newBlock throws an error if the provided transactions are invalid": [ { - "id": "fa47d776-6525-4a72-9d17-73f6ccd129a6", + "id": "dc13ebe6-33df-4613-b3f5-d69c63f36b15", "name": "test", - "spendingKey": "82138acebe75bcf81ed5a0ca98456f93fc417977835fbdc3bdea2a8d2b52b64d", - "incomingViewKey": "3754bd879cfb8ecc85d304ef8e5aee73b20cad370b79924e338bd1d4dd1e1906", - "outgoingViewKey": "097a39c18121228b15bb7b4846621cf57a6a9f233dec5f69ff4b3ed0715e27f9", - "publicAddress": "16473da8d6ace53f769664f812e1599815ca63ff382f9c3a7913970b12cade42" + "spendingKey": "6b94bd4cc45c3ea08fe2487065647fc3374fff5b21433d92444844dd236cfa02", + "incomingViewKey": "7baf04f232ee6ea89eab1ec8643f680b0bdf88de5fcefa332600344656e84a04", + "outgoingViewKey": "6457f22d9d1382e0334d0d2b514ff5dbebc58caf9c26ce9799f21f659bd57e66", + "publicAddress": "275f6d9d9a61c4102eeabdb68d0736c9b6ff185d85cf4e1d12dfce9bc9b9cc46" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAARS/IsgsoZ6E1yx4YsKFQ381Ee7nl60mBlzwKnYK/POSqcxn4e4YQ/QJsCwZoID8leF3jCYQzzOyB3Rglv1a58Iyf5Egw9yGCdHy6DrVD8lSgpKXMNVas2TtWnIveK45dED0U0Fg/nXrz6fi2or7/AUOGunqj+VtQq6Htfw70cu0ITTaPl/NGRj9KaUyPPPgwnIofEuuj/HhQhK/S//bq+zKu8Lr04XjA9+2BAx0Ynjq5ste1RmnuLDWIhZjyHwl2ZmVPRL17CcpJ1dw415kTvLeEwU8MQ01NWqIpmCEi+Reni7HGNco4H34oG5t+CWbMr/iM0wxcYCGHnndM1TZXUiR7qnYZazVcw/OOE4P8xXEjd69GUiK8B3lxViPh79RmMhdoPzjumRxzvWx7yA8C131Cx72dahADDYTGWpf/2yHRNl+rGH1Ww5XYd22BgNjDWyhU9Ocjm6oToLvO/Vz0HXM+cSb994XEWkz8peucP0bL+uZX1RrcLFb9bSqElXESH1URQwcOyF3s16QLV6cr2LB0oeegqnFrHboFFSDhWIPx9rK9vy4r8JssjO0TCQix2vGeJTYT/mAOcofSrZPBFx4KEFZbIKFim7RsvDgAfnHjjhts9ygVKElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw9u1yB8yjRh7d0LnmvTFIsww/pZUX1daNFNuOVqHaXg/QNF8TfCXn4BvpkbqAkAPDpeH7i/pRjGgtCG4+P4CMDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA7pI2Wr2pX379wSsJD/l0w2tOCowJf67uSqQIQ/d2rbeKM4bfen0nVRDM6y2ORJrALYbz/YlP6INg84L36Svq5jHT6P10I1ihayfbyun5FquSxQK3kw2LljATIKiarzOtpP+p0ewOv03MHv3VEEDkexHzfwA3T1Dq9SgRLUXVh4EJrnxGUuBDkn3UB3r8TXc3vZrlWpmym7iCqBF7C64ZVoYhmYfjHA8vz8+f4h3JSTaJ0zx9gmSbrXeDjIwhyylM0jvdmfxM23gBlPFBSrP2gatP6C3gSwNlxRCNySRTVsTp9OfLrNZVYrvf4O65z8C619atvB+lGXJebREKnxh5XxW44+E0ftz+1kdzLxWhaBvqasHBM5uACTOe4zmeDm9mEJ8oqFPF1cROKSHJXWIXE8Z3PNdH6cRgViCFhMHH28SYNBfE6+5MU8CpQYkG0Ekn6y2HM7JJsRg5MubZf1kVNwI3215nnP1MDiJC+tIPaDlLz2JV92bvwrXe6WVNNfxkPFivCk8npvaqiY2hGlPKM9lDiq4wcynef5lHp4Uu9UYUkCSFLKnssESu3vzuvNcIVcgmoY+E7n2xd9EYaPAQ7/9C8rHJP2rYKC5zut0+Bdcub66HOqFdM0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwgTDrv4cKDFCmGdkf2BeiuBil4lh70vG3qs2sso/gtokNeSo6T3Uzu7KWzsBWuXoMDutooDna47LvVtbyktF7DA==" } ], "Blockchain should wait to validate spends": [ { - "id": "a4994440-4c5b-41a0-ab3b-edc7f03bdc28", + "id": "8b22b709-50fb-48f2-b5d4-d7f0885c90b0", "name": "test", - "spendingKey": "22ca09274eef4bc9c9efbda3ee91c58245cbd7928f811b7bcec4ba4290761c41", - "incomingViewKey": "2fbc97aead3c713dec232352baec26863f97bc15f245e050519dba8c682be302", - "outgoingViewKey": "0027483b54b18efd913d260dc1b1006821bdec86c4f930ae0544a6f3c24adf62", - "publicAddress": "96ecb003a227755398f259053297f077a7ca7acda0d06620787189e4d8f943bd" + "spendingKey": "6f9c176698b621903be9ba539025137d8a089a0fc56e0b43585207eb677dc950", + "incomingViewKey": "96130c31cf37120a11b839b29ad7a7b691da4cd7c550526b8742a4ff7812e302", + "outgoingViewKey": "2d8b7a5e64ab70562d63fac7e42424e097b92a044e2473ef397665cf483a9b35", + "publicAddress": "d8a35b417a42c1e525865d8d7158084c0fd4701edeb6f370ae0064706ae7256d" }, { "header": { @@ -382,15 +382,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:UhnxGjrlL3NP3LpQ1Xvb2/6NUKzYd003dK2C9NKYiCU=" + "data": "base64:mo+CDwuFlD2gGRyNXuc5HSHxjgntJZX1MV9EE/T5ck4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:c5jHg1crafO5l0Uxf5gc+QspIzjd3c9l+7ZR+eTmF1Y=" + "data": "base64:nNSoa4YhmJ9lY2HNSjljUh7grqtnkXeDLvzUPdvESKI=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470823232, + "timestamp": 1671691598298, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -398,25 +398,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAbGqg0wg0XiC1oVPn450bnlCS1HPo8+WdOdGoYrwuCqiW9CnuJxpm0D3wa8uH429g8zTnMqYpEMSgaHj7TJaeenEPZOI5z1eIMUSrsutY9TeY8sJzFn8g6sT1rVAFZXGjnFeem7vcA8RZuGyHT3DkdbZs3ApVDrD7eKADbVDOsOEIi4yxcknC41vbiYQ38TPB3z/FTYtQH8zGhR3x7UQe+6C2A/anJk9+48rjKYHYyq2GqSxlETxib23wH+qkPOu6eVa8yjza6unLtzRxxV1ou/NuyUB6RISv2/1v/Hy2CsbJAahadICQskU0RyaJvPgaDMITOCW5kALfq+BBE79S5w19pZEKqM59xee1a9xEE+S9Njyc2oJgSZ1BIkobNHpDnSR+K8O9vkUVwnpGHnLaxo9UUs1wmesoGHclHet74ZlW5RSMK5rfWfbYPo+M1kTmqnT56ctiXsik0nZBlkLhDfg+4/GlqIhuWMoNioq8TMSf4obMJ9KTZkt3S4RQdMwzBUUK5xTMBiCpjoE+ImDug862Uz832Z5UTY05x6LVqEVmRRTGai73YDmhhqYUTraaqrFsBgrJt4Up/tncZ9AaNt6KP2rCPWwrL1U2LdGZ7R8hyjxfrlIo7Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwD6h7bNGUZChFwjDuG5X0tjduzkYd6QF8C8wo6Nh9gb8T+b8LoeJ7Bv+dbcdwxWbeKhh4BEgeTjcYLXjPFHjEDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAxiNcLXdTlMYAp+1Dlmcf4pvwzAfBL3cHSKbmDBZoRQaqSMjbM5tGjnjUos6dRVuSnw/Pjti9vLBupr/+frNvKLyRz68X98LqHqMFLTXo7DOmc+7gZAfKh9BzDLacjaFSiW7HjkIjyDELG8fBBd0AGV2BvjP7kZxdqFxPTqrEiKcV/YRxQf+0+Du6uoLyNOMSVyKjHxmODVGpHmvw6RGCJVI8qfafwyDEWH8dNaQa7xaS147epT5b9uD/Vgcemh4pMPwlpoZSgMVHT9Ptli3ufJcwlOh6OEx72DV0EHzAdke5FNvhpIxDoef+hbSQnACd/dYDkiyOKlj0/L4fTvKyCUjf8p68idI3dtq676gIjWaCCQmhBvyGDLG2LnmhMnAKoj+1x6Nq1mnagfYo1eQ9qGIJumTTsDkEKQSe0MfCzqzI6oEyfGYJyoz6dGCJP8K+sxUN30iFVWOWW+mBYGCCQIHYrW/06K0GnLHEIv9t1uHjXAgHPC2In6RyROnB5RRB3xEas33xryMbTxgxIglAhpyyYrKzV32c6C11k9Ia0D9a2k6OYIPiLZClb+Q6UTUBLe+y4IlBb/+xHHafvuPaW9DKyJrb7ChFxBsbenjCb0akfJlb0jdJkUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCjeO5ceKVIfDcBAP2J+cMKmF82vS4YjHLPQXHM3wL9meyDMfuFaa2VwYUxa+YqMjMQhXCPyt5PrGlzMWL/wKBg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "64FF5BF855444AD8F32DAAD9D936800573309A22CF836ABCCD80CD4478D1A3A3", + "previousBlockHash": "D19F68AC5CF0F467DB4DFC600F378671405A7B244F33A7549850FF244802EDF3", "noteCommitment": { "type": "Buffer", - "data": "base64:X0pjXlWpIHoIxebOS4c4ZK1XkTkkdY068B1JsZVuAls=" + "data": "base64:lzA9K6+2OVnaf9DMdWMw8HQcfjeLqU+aLa7BQKXB7xw=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:hzLjfHQW8PkawmabBAaja8pU+aiZzxR5i9bXjooPRsk=" + "data": "base64:jubJ+rj8VP6j5jPLoynzKTRlzvDs0e+6k27/ZmR8Nk0=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470824893, + "timestamp": 1671691599992, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -424,29 +424,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAA9Y41cTiU/XMbrBK4iMsFthTQ7S/8YSlOiL/X8CbWljWonf/lEBc8UVQXIUsGOUKrGbr3/hsZ/6o/kYX5853m5jkVQInoAXbRN8YYFGnEI5ynvJThBHQywnziBBk7UBwrD7a+9CKxRUcVxVDIesPxngdzd9PqaszsIAlAQvC8QZMNCBv+GKzSNKGcJ8J4D3yvL4f26Nm5tLxKLySNXiBPmaTDcRlTOYvWQdgy/IDtuiWpWKlu5xnqrwuUUZ2gWpCE/V4xOQ8i9Bd23V3oLR9IPqBGfZClROOFHO4T7zwBbipNz0RipRRGJIt37rTFN+TzkYp5xhAtByWVqC0uJx0QZcztOmmMbVF9e6v6MqVnbqgrNdGHao1EuV4pK3LT9146lOGInly2qFtj3GuhL8YupoA3F3i+MEMYC0cN6VO59rjAlmi4SRJBxWdWQBifFh3mrcb1GrzFq/6pjzzBqH/YCZpoN9JJQ3rK21CjrXmWXXs3myUsNleU126rCoo4sE2XQ68a1fQp0pu5E/9ZIz/1gCR7iUCjwOW3+oUuypENsoHMgJOZbPdz6rXoijpKWmUUbmu3N64YKlKbqRlBSsgf//UfJE1oZ2QZsKI+LoEO7IsJXlpyVxgSXUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwp20XJ9qPE0kbILiu7UT/uIU53esmLxukAZ7DStaplYFQQjhsARjpPpJVx/Bq1q+ntVPrjFm0dNgPNbVx/pAiAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAidYlP7DJWxs2VPd9fhYbl8qsCfyuNNLGgo4jLub/otak4mkEiuLpxp/eec4evvM33eCKOw1zq36FucNdzWD8LZ9T8tFFhBFR47BH10xHEbuVeOo8TAfs725jVT2VcsodDs9mOMFpBe0OqupmgkX3R+wpseqlcn9LxaxAdxFZUecDL7CWB/1kM9DPh+G2JOYXGhYAhLJYixZeC9NAEnY6sEXgK24qx0LwzOsN2xLxz5yNYDWZ/txH2IEpjf+2xKSpx7GORjfx52tFwQUaSbpxqcbmShyi+zh/fwCFTEeuVfX7/RdvP4iJ4zUG1wuSRMU3UGklhHEyn1AMQv0UpIfxl12AEUStxmG7h1NKUQLw6IODbN9fV0ncDmAM0Dqk9FAZqgAH+68SHWkej3iW6EC95qpMbDaiLI+9ZiucZe5muMAAoRtAaWGcjcfwxKoqnqo3qtBQ9a91Wk29Ew+5kgkyyCZTMpx3wOpkji17NNwdlwFT/MO6j7i5f+EDKjKamHuA5UJ50Ghr4d/E/wl9aJxpU6mdoh5dtAssbYUFkzzmdLE9+bRv7FuDKVJiV/9G7uDAiszlJd1DsiYVUtYDBPjtbL5k9hYibwEjoyB+wX3DtzPRun/Jfgqjm0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwm6eJdE9ZxO8hJ+J2omtByMCmslO91C5tjFD58z1vkAnvkc5s3KfRBqBt//gyblWaf+Ayg04koDBL9WOS1rfZAA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "2DF69A9D8950859C86535F5809E39F799BE41461BA7BD30D257102F30512AD5F", + "previousBlockHash": "785F1A1925003A7990CDA673547896E5358395C36F782F025454A3A0E564033E", "noteCommitment": { "type": "Buffer", - "data": "base64:BXr1cs5tbrsJlika0DPxVRChbPZDhmjFVwt47/5DrBg=" + "data": "base64:MkyByTTxLOHbTAoqg2lDfMwJhbjAxCI4KN2tFfoBj1o=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:LYxZn/hcWpW0SbHS3rJ62wQzqLfP0LXwTH6C1NflTWk=" + "data": "base64:t3oJyjMzb0Y+USJNkaBzZbn6v0WjJ4dSpUNhoOuYPPE=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470825222, + "timestamp": 1671691600315, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 8, "work": "0" @@ -454,25 +454,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAVzYGdjg7XnAtBdAHD2hOI1daSk7UIik7aGMmq+w8WZCH0lZQkAXiZOGIQP0AFWOu8V0+HZXhHjn0H5DEwOTRrqgWb67O/2jIabigXDbmaluD6qtP6VIMw4QReUS+wiQncVW0ECOE7ntBwmS6M2NU0Z3Pmg5v6qz5dctzmQmlSmsJAllOXNE8NnfKtbpkTmXHNQyhJrvn5XysdriGllUbRsTgdhTRX7fNzaOa/Fr9qEKTFtLbdKamYln3ode+TQ8PCl6gUi+JXpEMQ6XRQjhryulqmlTp2cFvSUUbGn2tPeM1+AYj6iNOHqYWKtlw4Azy5EidqlefsaiJbVg052bYikj7g6E9o1KC7hapY8AVDFxF4B1MixAVi55aiOMofpMQnT/gQwV+4TudZ31yIR8kaGiW1CJ9Ybs0NPVjXOX+QBiYFcX6u8fCVAvH6OYjQKYfn4A0feMdLZnNOUiBk2KKfkv8+xRovHQ9XluTI7AlJpIcM+fFMqT8ahGEfoOrNuL0SlrWW667POW1zyxuXpcRCbOXZcjM9fqykbA/rWRtFbEEHp9AqgpQh3k8RObSZKdPjzdGCg/3tSG2SOm5M8PYZrBcxMxBDQE9aXl79vF98RiQY/SH7etaGUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw6wUYBxjs7AUahbTJ3MQgBPEkzljGSqR3Xja4K6V5el59tOKq1MNxLsZUbSWOWBH9jMIZn5kN4l6lc4TstbliAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA+GUzb8P4f0+uQjZ5cwBpD1Ku4ZQvGoEXflvmQB/sIRO0JLqtGmJR5dFnom9Wska2zWKlcU9g/CE3sntrJxPGNTxC0rl9WrHrDZBFwghHCTGLJwneeNfbV+PriY0gxzLbDQ4r+UDzAxga9tFna1DO0ur+MNaSNzdh/4ADbIeFjOsVWeZ6z3gEQ9idnpDxaUXRcextEvh7l6nzR+m6ALSMPoXpUSO1T8nzzWpUIuikeImZ/4Xmvgfeykv7utX3GlpQ7n7YfnkZF/Z6Wrfnmt01azBeck3fTr7cab2cuFw9rgFifxpOQ+j91baRGWRJ1opLOMBzDReKC/e6d+fwvjl7kLUwRwMvUUYeW7gqGqHAz1Azhe8dnINkhVZubJD/1LRrGHm6jR11+5gqfsjKEUIC31Z/hnNO2CpSndXS+2KjjUL/81Wzc3GaNy+GyHTeQv8pA5Q26MDSRfX5/zvRHwEmmgKPzAkanuO+dxlRQ0/bfdbBybPHP/4srnSwssVjh8qOUC7wVa80MvrwIMYH/ytHYoYAF+QgiU0ZkI+2CEICRumjSuYzsQWH8ADMrJTvoX2xepvymMkq8WPhqcILZfhfanfKOeJ8P1I/N7pG8R0+/4ocsAuX6aWAbElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwDuB5dXeU2ksyFbfIGXDwL7ceap7R8z+f0iIZAa4l2lLvfkj6YiopL684zUg0wQJYUKd7/++IVpsTy2G8d3hZDQ==" } ] }, { "header": { "sequence": 5, - "previousBlockHash": "A7106D1D333BC4EDBB4941006C4D6A2B85EE24B334FA9F6493D32771FEC18E1F", + "previousBlockHash": "29A3231D2038CA3CA058DB8866901B23C6D5B90013F0F074F28B4AA891E052F5", "noteCommitment": { "type": "Buffer", - "data": "base64:uh3zUeoRLUr/u0D8AwaosQCJesLj92kpHBJ99bEu+kM=" + "data": "base64:frb14QMRL8WXE5IME0Y+/WLGIwlfBCGqh2uLN/v6ICg=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:IQt5T3fUBsVqxWvQ0F1nbXohO1HbjFhtq2MGpi4QkK4=" + "data": "base64:8nthCKV3Ppsb4Xvgpz6vuWibQSOkO6f7KB0PO44CHTU=" }, "target": "875726715553274711274586950997458160797358911132930209640137826778142618", "randomness": "0", - "timestamp": 1671470825523, + "timestamp": 1671691600622, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 9, "work": "0" @@ -480,25 +480,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAPCvj4EEnLS8wN0YRYyCO/wdi4tmrw79dw9HV1oimwWCoWtZY11znKFeow1wIBFtTDHrLhOYncebZ/uHFE/8/oIw7g6XJA6cRYG4mebB8T2iV5RrefReLxdHrfcfQGcsFeaeYviHKuaiVfzvlk3ONfCpQnJx5s2bQwbFbVtghh6sBmS9XxApspb1w4sup5WunhiSTJqFC8bfO6j7wQhJPQm98RzIGCSlwCHwaMLMljp2p8MuSYO1ZDZo+XeJh0vT37OPC6g42VY+WG/56OUxekgB9DLfho5LFnrHD+CtaIhTItCt5u2s32ClyHCem3MEWC+SR3pTL5V1vR8cVJx1ZP8RuQ0rc5Gs62g0UFgvVdbglDvG6FHcS/i/i1eAT9RIXGquye8hWdESGxkMP7GJqycbSUT+ITkGeV/EpfR1zr5hYnbZi0TP1NuczhozITjnSnu5JrW31D7ulc8wrg+IId1TU9ljsRdnmlm3hLbwCQEUGPt5DKYrVNYL3sVjwfnhsgMjcX9mWcruJ0VIC3PLXeKLJTiZcu6tRmIJ3Zo3Wp6RawO9D2YvbcwJy+1Q8snBS9pN5d/UG56+VdW77Jhz5CkyIWrJgVKyz69Ql/2/VU3UaZEFBi8owkUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw5NoHN2rIVAxNwPSEFX7f5XXOGBVc8emZu9aunk6m75flRFv5blsjOa20m3oS6y6xLrR97ues/EurtJeqLVs0DQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1f/6KgjwwCKiP4qEORnhjMClft53N4TpUYT7YjVOzo+E5nUQyyU5CufrPdhOu7YsPhU9WCReM26cNOQRVDW4D6+YDaVSnvDqFWAkva51+nmrm4nnSL1pCOdpY1qsmMgKXyf3BKYRXut6iZCRu/vkx6ibYzWrefahxFoYbMwVn4gAN/sCaZiN3WtubvYvNK3j810Ymq3AVK3+jVFQdK6PrfEELHrdAhjOOBvRgzF2OI+VotophYYvHALoWVTEIHjELrF3UKAE4Ypi4NkBlYhcJC88JxX66j+kH69mFwtwVAIdJAoeu82Yb4Q7aPJLgCrr+awMngqtXzM1Xdx3Z1UTLsdOPjhqjQDZbdldD15osBnlMTnEVFA4naEsxmm6caYd8ZlUORKyZ75fEzMbWFn5UQc2R3Wkh/H1GqBK7OcRNddGtB9AEwkjkNQBhFgm2ltLz+ty5a8dRwZnKYSfX+5Hks04LHAILGgKmgE4CFoESdBmFqjQ3/gP6fFNpJyVnlr7zJBCvJhX55Logvd7rgq4erMD4JkGeTI0cl/CDygYvhrA3uDKDcFhjIjW8jkxxCC81BPnVYOBlHbi47BFJtqnScMmCiygIbyHHDXlTXs7oH3++x7+p3g9MElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNa6+p1GhSdzVgDUOCCzO92KTlhwuJFp2B+6sS0E2UQRSbFgs5mNJt+wcxdGrophYtWkDKoA6XiJd1ykT9YqmBA==" } ] }, { "header": { "sequence": 6, - "previousBlockHash": "E0C3A776C3BC223E59E2C5902DB10A47CC9988E3226453AF04546EBAD63716C9", + "previousBlockHash": "03807F8E23B1BE033874BD577C85B57DE1BCE183D2234D2B082A78DA2DAFFCF8", "noteCommitment": { "type": "Buffer", - "data": "base64:Fc7abktfYB7fiRywXfX++VVf9oOQqk01aIAZUKXwyCI=" + "data": "base64:p6wmdD2I5EW7pwpmsmnu/WSwUvg51f0S7d4MNELCvmU=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:QJVV9/+bu33poAbyBp0O4i7qZoGadyYjNsttcX228RI=" + "data": "base64:gIge8UBt+RreaOxvblL16vpkuOjTsYszLuvZIgxav4U=" }, "target": "873190827380823143577845869093025366895436057143163037218399975928398962", "randomness": "0", - "timestamp": 1671470825831, + "timestamp": 1671691600935, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 10, "work": "0" @@ -506,7 +506,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAn6gLV0zTz6KIw9Li1p/3BsCJdNrcEYa9U7/NGB4xx8KVgNJKemd8OeXqNPiOXj0TMstzTABxW44m3BI2aJYqoub/RVd/neICbFRgjsCT81KxU45zYU70ArE6gc/c+fMjtbAUxBB+gFPBFF09Gqron2tyeyfG34LOnhbkhm0503sJl+nBut11aJTgc1BuqP4B4gEyQnDN2ZV5c0Q8aL8DmsjkNh3+xYHKY5DzUgelJdq00U2IjxdnDaOme56EqmNUiuS3cXP99hNYk2kcSWqc2J86KXbI+OLN906EOVzhioYfbieVAyUCHQBmbmu09Q4NLVlv6FxhlTdY3zTP50iH5sAFafwgdvchzvRVbLSFk3+DWv4yQhRlCamQlnUUfnANHb6EzUJbE9Cr+AOWZZ9g+ZbbHsjXjNGnlBcO4PMl34eq++GWCl6QOwcbLpekLRL959n8J+6rnO3okJ8RjiEbVEO0Vt06ljDYqIQNsX/9tOdZMASc3yxljck8XHy9T58FWgbhCbl4KJREQ/TXxzAFtpAt0an577+RfATzAnW4NSF4Qgi2JB/nCGVnVj1+2xZeoR7ngqz2cEm3hn1woVzXbyb0K8eqhgYZN4SVKpbKWK3WeCHJxTpPIklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSUMt2D2S/uisjNt6x+l99twzzEb9SnIjjagNUjQTf7ucy8yn/9ITKcRY/SSEEYBBk0IptE68fvj5LFkQ2qwpAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAWYTYh9lTmoQa3/RAplazfJTHHxU2WPrOqlgviLLajayn+MwV/VmIYm7NIcaaGpLhtpCrB2wtzcWrq7hvHLHR/VQl+7lw5gKzzMF1Rbw0cvuGnFjGS+0CJUh/VkhZoiyNmxMrqT8lev6mc4InI2qxdls6JQuzD5aARing7HOn7wEXDjH71WZe669JBw+vxUctP9JjTYY+tj1ZQDy3oViUv3qIDGDczSkNK5r2wX7bdmSmjWgRPz1y+jRatYljEzjaIrLyv/LP9XQ2xvGLbk5eXDq+UgPExZHcQ2El3MqJSINyhH/X1k+TGKbqkU3FdwTVyqX44vy1+VzrQkI+uho5Rdp5Nb5mJesIaxi0blaGxUe3dnJnLB6bpr9jxkLEdk83Bm6RoBbEYJyb6cngMNWmfAegv/7ieqAmAY6KbPvuLeDDnOrxTr/VKVR60WgTeZYeRa/pLuuZLi31wfHVE4rHTG3YAsLiBTRJkI3ilkCxskrIGtPnLrBRwK+C5SYFUKtzEu4t716RlfcCBuI49s2/UvKBkL839CV8CUBX/xIVO1+hg2G3wr4jBAN6aIKPW2/Ownpmpz4/T/NrCvKNIhVSL2NT80s7YU0cZXmjRvV3hJBIeK+eyOrelklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUlhACpHT1BRr2CM64TuHKVA0fCNrRaJYmau0chnsVq2AeXJp88I+M3ERn7kBEUMatYx3ZP0ySUeKftPedG+MAQ==" } ] }, @@ -516,15 +516,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:N9j/cJXf3z9ZZsxAT6Kk8olsZ6Mea2szh4G/aLk04zg=" + "data": "base64:JDesVx9u5rygYcpcS23I8ZTTZENP2TTSwP72BboxGlM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:zw/gHA7pcGaygN1/yTURqE2MLNkamMb5NX7ssOFLyTA=" + "data": "base64:cGbNaPWMP4wArGzlxtVQrQCOW9Cdh5Za8IqaEcIQCCA=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470826141, + "timestamp": 1671691601239, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -532,25 +532,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcnlGstgTEiGlJwZsfZlfkI+1njLW8DLS5V2bewk61vGJbFOGFvsFxjenTxiu8K/s83VLcsLfea7+JjRfAe1kYHrbsp+0lNZ4l8/EwgFZDkWJRjxuDbYBZ/wktOoAE/5+c/jRhacY7c0dBc/atl7ZbW7SbWm1Tgby+QYDjGFxRpMVS5+3RdBwN8qVK4jKcPP13O6deORqa0bQnu6KTOc75xqrDQcwXalrc5Gr1XrJyQ6MBjBxKItXgvQ62vL7ZEiIDzylZQkVNlUmXLAfb2RaTXgi1msKeRa+VoHgYddZLWK32WA4uYODAPdybOjVjW0Wm2YlpWatGMEvy2SsUvfqF9b+/QR3yONZD4nXmA6/J9lqPsauticlkN/umM5mQ9sGYBg24zdKI6rwmLaea2ZNb3ACBxzdj56SUgNsIeV1PBPmvSWHJPaWReYWlmrc+MjBB/d/Olsj31naZ7vEpneEsVHByM44Ir7CHOiKqd35XUDM+BRpf+GLGS+7kh55fcNC10KD1t7lR6n8+FEURrgZmDtdHwnSekPNmz0LidxIA53da42lxHR6xv3k2h5qWgSykViP9dsW2nHUnuqXKvfuFhayMtatH63SGDc9faj3I9z5K9/OEvCTyklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwd72Oc0jvdbMCD5TBzEaBN43cwEmsOLnaut89tJLp7JzioI2HT1wcKBV/iBjqy3uvgPV3xuBoIkYoOCvum5e5BQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA3/WIbU+C/fcxeNnPzbGvxKWwlXCJ1xv+X9ilR3Fe18OSW1s3gA8EV5gZOkQZB/X15gnmfUzkaaJj0opykRVMrKJQDv0S8dA5bDES/z/dGcyModUVR+3CvSooQFQsBh9ppjlaT02CWEwCeCwQv+TXUMG2jT37cJ/k6XARt2LvNKYEBf3pJjrZ4llyZUy6nGLXunn+74k7/bwiHWHAxadmXniqP8hxzJ3kb3oKQIbCm66ZXzdAbgTjZd6L1LJwMqwBclyHYVJDloMHaR3vrIENa2g2ZrVllmOPqAG8PsQLhJzxLs/0fRxK1cWN2gfN1Qa+SfnAWBXd7QURlCBXVI5msETa13iqiLMjINvj15H3zfd8EnsMmAUMC+rQnfjM6KMCxgFGStprmWlOWzqZN6cXq430FcvUIobMRd7Vkb7Ykmp3YNdaArCQPFyCKSqaD2sTCRZhj3k5/h4kY6kbzcwdcL+d9IZYw62W8ioiincY4Fogixw9HQs5qou+IL9JfQ5kp5rf/anA3Fb0b3UzLl9vsOaSe+pZC1FLaNmfEcKwSWwd+3JJ0Ckjzsen2J4Ad3KMe7E33Ww0KfcLO0uiz3uQvtwk8j8S9yHf9GQFh2lLrnxdzNWG24HC30lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwnkBWzJTqU1r1qdAAA/svk9439CtimqGq9yNfOZ/Jst76ErcKgE+LLQt8AkRffDcWP8xoqE/9X2DslShOo9i3DA==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "03BDA6C9435FF666BA9A48A1494DDB0A3ADC621ED75EF3AE90D4A1FCA900724D", + "previousBlockHash": "3BF78774FE7862AC66DC49635B1A0DAD1F66A8234093EB054CE4F06571972BC4", "noteCommitment": { "type": "Buffer", - "data": "base64:zPryNxuT8b7+lhPKZWfbY1tRLv7tk1Zq1uePM3inxlo=" + "data": "base64:4MmHGLQWg8D64rzFAkWzrblJUOUIuNVJf8lyk8Mqb08=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:aN1mpvMMYoFzmfM3KAVXL2TDW4gweZa5jA8994CsHu0=" + "data": "base64:5928ff3TabkmWQs7RhbuiBtOgSWP7RnMbYszlVp/7cE=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470826446, + "timestamp": 1671691601555, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -558,33 +558,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAMfh2jthL8zQg9xy3kTT/uz+eNg8lM7dBAWyk0vjUl4KFZ4zjIbnmkwXausyZTCF5/ilO+5IYxNjqyXuiA/xSibFoI1Vagcko8qn5klkZoS2t1tpm/7KJCSEXs8Cs/L6K5jGYlB5LoSKmYsuItmrLkGqn0phD3CZ2ZMFUVNbaZIAL/GCVLzL4MuMfgjbemGNhyM9RBsy0N5weXs5bJ5bULYMQPvKYWXzzgHim7cw19EWA8o/N3AbY+4T2TNytX+41idXnbj1RM/HjCOdxO6gLjvb8Ov0DYebJtOSlyb7V4mdGmu1X7tlZAIkeKYzSGuU+YFpmrm1vVckS2I/oI8gAvcAVaHv+aynhjIZvDZ63v9VVOTH4+wZi7dd5ZpzFbBFnqlC5BYotc3Q0AkN55yAc+wj1x5RZGpxQYBFoCf+o4rRob+MIBvvbbo6a/MwFCYBUJPF53qpa8Wq12rx3Yo1NNw8yT0mzCuH6ZSBUbasig4PEgs2Vfxv5Kd84ZOjJ57qrtgbs8CCYUzaGvNl/cYtyXRhVGAKEpRUbTCE6TtaEj5ztEza5C0e1bB/1bhveFrJ9G1SEDPJiq23EWSB3NpiuaA5z3GqmIXOQ8xriLIG2uWegvN6x55ClV0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUnJdX2wZYJhxxV9k4LuUyKylsKQ+TCkcNF6vQtuik1NkJjhUJvZ8I/UUOKAeVlUioeknoJcKHptGyzVfa380DA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAwSn3GOqfeZCksXk01IqA1iMTmwqDrYX5eOz3eMRqaA6HtoPU4Ge5KOL3tsC2x+ksy+Jw7cuxnLSwhmdDUC+hQLnaf2o7OuvMF5IXnOnXUX2F5qB7IMtXKt2m3rHzD4uTs5SLvCJV9q0B5U1F011XUGg8pmQrp6TtDayxbHeFg0QNNiEJr8YsDkiMJZ4b+u32O4hnSAe77p2SMUYV+ZHe4ZpWUQDUdmwYsM5zMN6OMQS0QxYFsqm5LNn3ZA6N5Gd9DvnqW+kUWH+VMlgyaJuoLmFQJqrBtBxuK/6pIy90GSd53LG6JJfghPZ+tywbb1+bMH/YQkIqROban7J0FuURSS05B80lWnglC5QlfMEeOFn4yz+Vy+/SjcOAy9udWX8h3tKLeOdUjEWERwfthc14hZTnLatwuzo6EkvUa6Mc6tOKF5QmPDasCzbKMdL8p5g8o6mnfi1ZpHybkz8pVfOiN7EeFgQscfAGrBteEqKcb1QYLc1GxGzqBXQSUA5CtMAbYjGt/PA8oTvTtAWGz17LRFJWQOcX/JDAgkMYoc3OexBmBjP6M+iJf7UFXhMgN0/1g4yNTybOqMGx1ZQwmmMTk+nMuBMc66RGuAOmIUBxO+zV3WGST5bMtUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwl0VCXE9vRYrY4MEsXpcWU5DxvgZaFqgWSpp4KtL9kp244zZj1WabwhXSlRKnr9LzYqOzv4CxeiGsDV1BrAULBQ==" } ] }, { - "id": "29d31e73-2c0a-4438-8ce9-dd33b9c33328", + "id": "6de08550-ca21-46fc-8711-f01a1ce4cc3f", "name": "test", - "spendingKey": "f9750dcea6cee2740ab2645152b3b24499675cef4f71b6cc66a407aec1d77541", - "incomingViewKey": "56adcf70b89460dec201c9b614f8cdc7700892cab6a0ad5dc81524b7b0dba407", - "outgoingViewKey": "e4426a5135ee0e3c305aecfdb9b5d6a2ec751b26c1822fb259ba71bd84d54ac7", - "publicAddress": "a93f0193bd0609ee6c4d8cdc2ac69703ef0c9e157d2f1cb25e4d7b4afbf37842" + "spendingKey": "f0c4fe365f78726ecaf1d5aecea682af139a245a75da8a9d8e7f6a329ac7fa3e", + "incomingViewKey": "2aee3855f24d5b5f42446591940269846613d5b01e9c483ee0372f63e7c14103", + "outgoingViewKey": "4108085760f939575c7baabb3f30e97b53b31f11e49b5d7327a828ac1072153f", + "publicAddress": "8daae73944820e0e4176864f6c5d170e07e7e6412d2d1c71020290242dc5f65d" }, { "header": { "sequence": 4, - "previousBlockHash": "EEF0373D23BD2C738DFC735C32C262F60641C1FA57F4E440DA3251901B2BBE1A", + "previousBlockHash": "CE2A3DE1967BAAF8025C706A337B4063E0F039D288796282A7456EB728CD2CA2", "noteCommitment": { "type": "Buffer", - "data": "base64:og5HNkmZAc20RZpz9bakjo+DZa4SQcI5t8nou/7sn1Y=" + "data": "base64:QJFeSS62G1Nzg+MvfqP8UhzpXfBY4sxDEpKAaE988zE=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:TKTDmHd/810rwW+y5T142ZYbjV3ogXPak/Y4yJONEoI=" + "data": "base64:OwnaK3WUOCBfJqHGO4YPqUAkT7m2en7sYnS4rLPSoj8=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470826774, + "timestamp": 1671691601872, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -592,25 +592,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAmp5MZsN+zBXeLDjqhFFmF8Q5ZZJkV+63zt5wAZNiK3OVkvwsFXy09X/43JQtjUl42+W1ztqC8kxtOOfhU2BGyXfiuPwN8m/31wEy/baz3mijcID2qkCFHH6BivkCsxYviJQrEPMW9jAkDTT5Vo0gdDtM04PIstQ97bvF0yyA7nEGJL6qntdBKQJPd0KPnNoUwFNitdtheTb0iTvg0hUuvhmK42Om+KLwibhTI3AAclylWZImw7buLkADilLZ6TDWse6MEvndG5ddLaC/x06nEq1Gp8PLT8aDS7sI2goM8+M9QzVTbZnsywSil/M9Z+0dxvYo6Nmy9iyhrUl2aatj3lajNJOvl3F8YjrwGjrm/QCzbujNkkjoWu2ffPxhEhUfp2wTGrQAtvma3Tmd6kXy6VAPJs42NfEMhdQqTFJT0dZ8fsLkvPhfswFptmyq0twvmbs6KUq372oir7kWgMCz9Bq5QCwu4xNjOZywiyYEBdMZOHVmlwigUdyJFyVMTk6t0f4CO9yf9FtTMFC9Be39n8aseRgFJOK5VLWAS+DTicioVTg/WXuIgwD0jcJm8J0cJrFEzvobnWdVMWKFGRXtBxF8Q+PZVA2Eg6YL3S+kSBC/F020sFBKhUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwpHiFMKTVBzyibv9wmZ+mdy+fUPPiP61ZfYUrf05UVVFTj0FP8w8faKmfamhiSvXOly3RDeVreS7u2tAERZz/Cw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA++QGgQB6FVnCOnvmw2khKOxJY5CNzBr6L5jtxIBUrZuX4X8K72Vyfj1Rf8oJCjcufl7+X6DCJhC7xxCwgW2CHhClIVSKe60Ks/l5BQGD3Yeiu0Xdh697xiMfozGMIeDesUe195VJw69ra4OWqKtUOHGMQ6xje7AY+/uNAc/s76wFvWdhxrIXnJM3jezdGzKhB0YygOIoxk7mzm5c7q0m4VhTMPguFgmSWEhG3TB9cbKQ7Ef76LTI6o9Idb14RG7MwoAlvI3r30PYduoa+WsiaxVTRVxldoflIqv0AW83Z89tnuJQy9KhlOGD51Pet2m8cJ2K6YzE1QBjOzZr5cKHz0reDNHhEtSxMTtUUPT3kxgNI36IRbJIa31eV5qup21EZgoh7oAItbDzBNsviMc5jkGdqzYOurDwEw2fb7g+eVEP/YxXjtt5nfTqLYxhKcAqh0+1PGJV9Raer+NkQ8Jy2V/zbSnw7uE3CkEmKqnz7lHrUFqpz4AmDf1UbKE03kf19TdjzhnRzTSNVzvvJ/aumT8k5r3rtzQgKN/hSp9+QaRPqfPCz7P2fA2HqR42vMG7LapP2FuNbT+pKyedmC1dE84CJbVIP/6fNrYyv42dHDle39QUjUDWzElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw0iBnOIH31ERl9rg9VGOfVoayXZzYWoOmgWpMMnQLH16fpa3K7xhsQmOd4M6nv7rcmRXS6oD85/sHs/aOwZLpCw==" } ] }, { "header": { "sequence": 5, - "previousBlockHash": "1EF94910D2B41E2342E76186307BF9B866DEA0373A9C8CB58B12986708563514", + "previousBlockHash": "12F152D73F14F0437C288F469AD533EFC0F2DE82616223201CEECDF7B47A1660", "noteCommitment": { "type": "Buffer", - "data": "base64:5ckZUWH1qyf0Wp9jjvUkbiLa7UUMRDS6iOrUEu++TR0=" + "data": "base64:vH8yLIpJQ0oC2j0C2ySTcIY2xHq9ZTRUJOPCXdDtgGs=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:ZLfACrJ7gjtXFAy90CdZuJmsSgJ8mTt8s8xtlT/xe3w=" + "data": "base64:dVrMqPm904aU2mi6p4JMiVf/HVARI14M1qGCKUlCfkw=" }, "target": "875726715553274711274586950997458160797358911132930209640137826778142618", "randomness": "0", - "timestamp": 1671470828438, + "timestamp": 1671691603547, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 9, "work": "0" @@ -618,11 +618,11 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAXdCXb0nV73ZUQi6Ey4H9owIOOtS1N1WIzBvbW26c5h6yMQS/6pNRdYSZ6p1ogL+b0jwifhRsNQPoOyrdkqGOgY65hXh4uWfBVFM/3VUJ256zItZRm4xvvFSo9Tg/+H5sb7nuMzwF/7fPiloGnlAPC8cZd6jNfoxHqZNCvpVJNB8NGOYAF4NAw1JVL4Rw8cwn0AliijziHRx8GuL/7pdQKFvEvIRPMHUwWWdzUT63RSqMeVVV6aYG9oUnI2kYVHuVn1mhhkZwp+8Os905+Lg/IWd3A92YNmgjj/SyoOPFJgtZWmoJyUoBwd4BGogqh8ZJzDNt6LrofCU5BolZJrImPtcbYq24hcLTWzq0rHGu0DXFnNXwx3q2cUBsp3z5fggnUESTiHjtobRY4GayqpogrEBz9fWfuK6yDl8IeIJm2p5L76oTiauyNk/riFW4Gl+EZzK9yclFR4W9XmFoLgZSPMtCva8d8GsepNmvyKYjZLphJI5SeXucveCMVUx+MxRtgfkCNswcQgWqaLZd/BbkIdnAdFB08bl1i9gJTPbT2FAmKTxOyIynqMu1orT3pufIcp4yEIlt9bDqosuJHNgq5Aus5bjAHSemS3DHBqrvO7bCsKhCISa1DElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwtIbIlruODFla5OGYxzeFF2KmyWjKo3AJ+0GInL8PyByoJIHQsUjNIybaQhkfb/OzM03kb8Lyqn7q3gJgCfAWDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAn9yJaOMRw3CwZXdXM4O/hmZmHi8gr60q4T4fKFoWSr2uZ2EwUvK1K4k3x05klVMQ3WZCXzUqAoMI/hAd8B0BgPoXAG59+5Ks1+WD/Wbo+pyOPW5FyVBcOSKcHZ3DINaFHwYZgr69JY6IynaKugyitIzXLsw80viw6Nq7nEboZD8ZLnNpx6nFwRBpoNSoTekcieU3NSs/u2BmWTnoNHB+yTjvqAF8U9UNvtX4A6UBW62FyMqY5K/MjCk37YWRsbSjYJZFIAhhSyC/JWJ8akaRCr67tvyEk9+mBaJOJx7SAOof1aFui3Vi2NCfEAfQu7JcZZu30c6X2crKIhNacpVTkPoDd2zv+TonSV1FnDT/rIr5ggdJCJB6XDJ7r+gT9fpc35Nb5UVxa8r180X0oTS8mTAwUq58sgpXA4x0ZBVtyIBorMGhVGjFGBUMCIUN0iX58NiL6mAy4HJtfIQARz0LjzZ5X072eEunzULQPx1Jn5JfZPi9aKAyyDrQGVnZVNAkO4qtin41BdmnzNjmbxjQ4+6nPG/4XTrMoBET+lTXjG/v7lAbwawUBeKY6JqQcu4E1ye73/4Wp8zHp8eUP0WV9T/1xXSdi425dgLx9Zx17/ZETbsKNj/+6Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwEfeT4oyR+WCws4EUJrMrgQ02C0HwzapyH4CvmOs3Oa9Oj2ctiEykW0eGhqUprvJuAUKWSaTF7bepFjKWTY0pBA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] } @@ -634,15 +634,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:l12aDuMY1LOuOS6f6VnhPalvEOFKdwS8ppMMhMJLqVQ=" + "data": "base64:WZVUPeS3sDJCWAPHvBbsah2KJ3XkfwmxrlSZ6FCsrQo=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:oEQGxKLkoTHyq+wpFN0yrWyH0h4WHmatnAvDPoUHL88=" + "data": "base64:Jcq+VzPzlmKuk8o8fFc6mihv8DJ1JHi582BeUfZ53Lo=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470828915, + "timestamp": 1671691603955, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -650,25 +650,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAADNKX/6pNqcSDucEA6AXBMkTD7Xx5GV5eS4EivNYRdOQpmrb3GEdBa9YcJLvgl/I9VAvDit0+UrjNt2toLVb87RO678g0sloDU43822YDJahOXtdzAXPTc3vffsxU1BXYXvZE/9MZJXuYHrwO9P0W+IH0ZE1e3JXwOtJEXhOaaERJqclY6zusosCF/2exTxw4uggpQeymHlzn/6jGri5+QK+n9m+BotKu8/eYV1fMgqmtTNdJMKju1K6yg92vqvb1uuxO/f2yNKQvwZUq8jNdC1yVBgDO1k4LWvLk1WH2QCcL3JIwYCqeQfk9T/e43saPmgz6y/8ZHWOEqq6PprxQXrOHuqmZarRaTbXUkNzwmWs4THfNHhGe6VG72NJHvMDQJWzNbJ8JPjzCUAU5aqKDBvzLiHDqtqmjVpsMEnpgIlVWCimKnFDSHQN3Pn9GqMuc7VGilbdxzhQ0A9n1vwL0959mKIieOiVzcZKRGag/nhdXaIrMI+3Kce0q0BQ+mspFJxKauM3Fyhi0J3en/W6GZ+HbAMryXSgEtoj/zVLON9C0KubJ40nCe+VHODSpWqLG7KqQVrbbgSzIwORBTaLUpmlhWNQuM6LTBovFpSHerNkwsF9vfxZqklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw+mPSMSOmQsfvBMt+SVJgB7Y5je80GqjTKejCfaTDQcCy2CVqK2pX+OBb0AYL8MvariDN5h7Co5HOpMJbUbhhDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAaL5+GQoFK92uUWC/sBslR4vcQoIDFIuqYydo1TrG1KW5w1RlIbvZNPwcHE6tLGwFlm1XvoPu6R9iOiOqBU7GEo7HxoJYDZqlxPzCXjJsnQ6Nh7SiZ2dLU6qocz3HRfVp2N264QR0MR0uhEQSYAsJUmIDNIymu1tHUFaEdbM1oJUO7Q+vq3RzTraR6h98r+/WqCMzIoFEk4PDrEF9qL9aAoqY6DL5eAULgPoI6/qAh3Cw45XOVw6XbUi0icWFod12eDHJz/1KrTMMLL22H9DqMj7Ln8FPDX6cVLV79Bhn24LnP1t2Syuo6od3pRWsckgOTDLHvkV8daSl04Bi5xdnD4M2f4tVxhwtNmUCDHFh3Ktxg17j/TshvGFAORMJKFdT0N6ggczgGmeU/4kfH4zOMVcr+YqXF+7rHeb07f5ZJJtggicWmVs8MAtvBsI/V7eWKxJ03r/hop1DFl9Dt5jmrJ2JV6S/+96SATYl5y9Ay5t9ebxu3f33xBS6YYzx3cEKW6epqXaIRJaI2I1lrkcnyYikxC6wQAYn6IfdhYRPdvmEAbC7+VjCaFo2KR6g/Zc99npzVRO8yUtB/iuaJiEhGZMlU/xDRWp8U9LkwSvqWsnZ0C2XegwofElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwiKpQQiL9o0Mg+6n8tDm31hrw8wyfE3yEPRFkKCOyfbY/GuSbqfvtQBy129ZPGqrE6yHaFHrimumoCzZaWKznAA==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "14906095BC56624FAB9FDF58F38020FC22C5379C6CC27DA7D0D7DC887169CC80", + "previousBlockHash": "E560B8B3DEF75E2AAEA2A1AD959CC127D6B0A9C223333D48821CCF705B492310", "noteCommitment": { "type": "Buffer", - "data": "base64:8wgkt1HzR5hmj42N5Pv+OTtbSAmo0j3IgnRIGXxFH1E=" + "data": "base64:kbuojKayCOlTcuL0dCP0Atwv2uIUDIDu7FUpLTG4Lj0=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:u6/EjxdVhTjTv/pPGqOZCLiAYixErf/HFyNVaNvQfT4=" + "data": "base64:rwiF3DE7aeBzBBe/3qYTHl0+ZFq9RwLsqEK+ebV+JCI=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470829240, + "timestamp": 1671691604253, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -676,25 +676,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAATsG2V8/jQHpjJuTZ4uCkO7LB49SMqEI7/t/LL75M1D6Xt2yqO/CgT3U2LS8KNuq9lXCXhDbEuHOWEkRlA+Zowg0ZIJoD5KxiAae0l1kTFvqWFQzxI+gAwFuUIEffSjZacZR8VNpSzKevxmJX9GblSeQUVhwINlvWXVXeuN4ymK0Vr1BrpR5dkWvOfYbhojwa4giRrP2pMtmJ9aH+t1Dw1rbkRQCNAagNOl1qaRBKMj6An0+A0zRiYt14F5Kng2evUP5s78y7+vWntoSc4CvUxMRgqu0zxUC25IWHHX4T92i0lPpHJJYXCTNYs55Dk+5UIXxv8wcGZL3WFM1QDt1kpU7iOIdoOI1lAAVW4kvSQp3QgPfCw0rLEUA28Hd4tpJbsSm+1tcr6w6Uk+epnvJ/e05sm6e6kfSVOUMCYqAxe98USYagDZOwW8Ev4W9EUywKerbvAyF1hiXFEHK9h1/NtGnwJfQEzczp+/7SqaGjD44EL1JC6pQ6WDbB3+Gk1n+4aNMsetfthvUxfbH+v4iuDrj4OVUfQYVtLBOfotClgRZctSL7pIZxbT1Ako2KJc3kyywkNK68hAWTiKUQswg88UdyuJIs7H8fcFula7sPnGjnMMeFhXoivUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwsI9mTGcHyesUUOEuxptVJtOZZVidXnIsFQ+RffCJIePozvi6/G2ek8ohw5HvSg8M1SK7Hv9Jws1dAMJqNmAzBg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAS1rirX3CZadIHNR/FDmkZdGf40VyQMLGtLBVwOHgdG+TEkIm2TuSXKL+xhZhBMhAgJKnx9WObXTPSXkFfmLCSqANgtmcT/VVao6JBcl2KgK2H7t0u0L25jmfMLmuTjoYNAG/IEoraIQUEYFGMugyiuXwxDQZRePZUHWFR7nuhbUNCfFUmnP9UrlfBWUflU9eFWNR4YXVy4MVEcDQzy667WDDPIZUcyrZWPfo3nTbMCiY1TOz1ICbN+tjbW7zUfLHDKE22pORqzTC5mwlShrtaf1+NVb9e7MNuaGmYS543iOxu0LO49jTSfLsCiyDYzILYGICv2R/KlDptSK/SnPhCqG30UHdXUPS1oppa0UXkQeuKgJJ7+QQcuNb2uppG7JTdt+4RObvKlRyrt0F/JJO70jCIPR/DPJpgEa75FN3kWN7GgO6bLgRiJ016k5EiP5X9dZanXWz4gMiUxJuLm4sIpbMybysij/l+VYheAQawM9ptFIrh2m4YNCw8Vj7G3Hc7wtqkDZY9Wo8eon6gpYIgbpjNBZ4xAgxtvQa3eiXSwX2w8Y81ntqN+geLCv2jbgVNu6jQEPzleh0qRfmm7WQdBx8r/oWsJfnvNlTkizPuTsOphl2+Dy4cElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmiIm9V6POA/V1TFtcVRZUOEcpJ7k7kix5LRxZMp3S4jYQSQD3G7Qf9FbPWh2ZXFxaAMZvW2N/qeGiC9+cF7ZDQ==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "097DAFE24329B02F606FA31E98D6BB19075FD6F84E16F51B9C025B311AAFCCFC", + "previousBlockHash": "482517AAE137D7132518E9555F21E7FD1926260392DD410DA6862E197DF66AA2", "noteCommitment": { "type": "Buffer", - "data": "base64:jl3YVqvNyK9qXQgrztzi8fPzNlrXqfewYB9DFRu6+Ww=" + "data": "base64:51jgf32/S4Vj+85IdX+7knnNe1wK6O/gK0MNFsS2YQ8=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:xd58D1TNu2ZgjnPaBV81d1iWFOn58d8fpG6ut8HQN0U=" + "data": "base64:Gt+xCog4p4Q8s3FN2tW3ypbGp8A3u4brwpIXLhxqXT8=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470829545, + "timestamp": 1671691604553, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -702,17 +702,17 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAprtv+hwVowu6CadczuBqA0nRxnKBSPEoMlABM8Ppdz+A2Ft2nTVjX1xUIzukLXKXhTHOYFDGEpe/De032wPUwLvzFwNBd+QSHv0fcsL8d2azm29s0hY3Flktq0kOw0kXp2QQ0/PNt2CD/aQn1zdJBfa0PsYyth6WnnVzYYnqSD4DLTOmqWnnN8FnOqqtr2EcfkbARTwL3vUQxfyeA/lxzXvUyAqY7YISdyRVWSKQ4TiXLf2Eu99d73Yuz8mVySI/s/l6um9oWlldRiWo3NLL3iyAJpG7yGRbW9K1vFFndsbu8Xj98Yq1lj6GnaROLSn6NDCADwjEkXHOmy8r9aJ96RiPCBhnbMCYTSy3NtfEZPawW4V/gIH7WV2woqeuNKwc3f3GIUf7eiSoemEOx66NJ3NxpGiDMarpW/O94EtEBueWZyf3Fa//WLR9CB+VK27jue+3Btf750qIUAVBZG1nDSQ6QpdLum+46UhWbayLtvTJAMUI20jbeNbcuWHVAfGg8ifLDYSx4ERDKrX6KTOtiveupNcXTJOO2/oKose9pvMZRR4z6+mYRyeRNZj/R/OzkAhFe19pCppu2p9IwRZdrBFdL8V81KicfWR9ASbWIuvRknsmPnDgoklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZ2YDHg6q7G345wvvTCblrA9s8DgObR76OS3+Vqj2L5HJ5pfZASDvNmKWe0mKxSvaRrHvg2+GK4gI8zLVi84ZAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAErVyE6E4e4nfryYE/HzsIXk4w0IiINiusaV7btVBv4OzWD8bjtEXqMxNr1+HW1fXd0W0jOacrhnHpPFEvsjlCbscfa28xTDxMqiDSOksPBKTpP0RZClvbUS3zAmpWBbdaKzXG9Xixw3c9NHcNJzuPiNKW0dL0x2y7M1j6IJyNsEN1bLkL58+d0ylLy4BPR4Im/5INKQSZl62nwzOeiQdj/O2epS5C1vtDVhKFddBogWC1OcPOKDKjbX9S0mm29nKlDlpUmiC/g0307SNPEvuLXUyQlFeAMfbZT3ptXlIGjq3Ijebo488qriKS9vPf2GyYyssskRkKHdCIGkp8D04E++HudAfdr8u5atDAHfPZ06DXxqmPosIkKFHiUS4bOk40xPTuAdSfYyXxPAp8XAO6YV6JPy3Mv/tTH8fp54ZqUnn+s+quLaZr7Y4ne6Q/pSLHmh2t+KiOH7aO4gVplfGV0IUV1lu9Yob7S/xpgqraUVAsX6dKOsSCBtkjMhJ02vV9WHNvCAUGmRlOLn0RJW5Pi4+TzaRw1223gh0N9T32e+SXriUnx7HChsrJyoHw383P2ERCjIl4SutFZNCy9gd/BpQp72jnD84zUqJmbK8z4h838Txm/OwLklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwoz/p4/OPkmfEEjX2r0VJujD/8g+T0/jrGuIcZs+dG6zahvYFWOdIt2jyqgqVV5kWHw58nC8veqvhi/fzdnIeCQ==" } ] }, { - "id": "6d98e637-298f-439b-98e5-63fe6acac110", + "id": "eede487a-fc4c-4df4-a771-760b00fbc110", "name": "test", - "spendingKey": "0de424a88e359da1f8fa7f327f3c6b8afb3ad5e2207e74d6230eaeb46c8576fc", - "incomingViewKey": "879bc0bc76bfbf149667b8e03e32aa1be0288cd7cae74bd7cd6beeb6572dbc01", - "outgoingViewKey": "ab21f864a03281ac50af6c0a966f8e4480a23cced3f31b506b067d79ed81742f", - "publicAddress": "c6d87d18b6b092d9d91f1c0e8c7301d8ad8e4913722548151847d3de4692f4b3" + "spendingKey": "723f2d04555c10609daac213c162727c203326514308bbbf2baee9b78c24fea6", + "incomingViewKey": "402a0225e6a7b2db92ef38de44bae635e4e71a9fd385be7821bc74b71c427607", + "outgoingViewKey": "83f836db4f2a171c91886a0c37c4c8120e1f68dce56bc93738eccaa7b3e871f8", + "publicAddress": "8dd3f9ef0f8d93a985c3bb87e244c5cf11ef3c6ca1d62920772fadbaf950a2e2" }, { "header": { @@ -720,15 +720,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:zOHVSxW3TbBuDOttUSxzH9sA+SOaOHFdk5MfTr6MQDk=" + "data": "base64:40fXbrMyaY0TRonF+T/2Md4Grzhmd0bKJWhpEhV+OFs=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:ayI88GzW6LFjaQ9gKR4ENskxHPJE5RSyBI/LAN1dK0A=" + "data": "base64:X4kuigrStB48UjKINTU78r58MqKiWgvWCPehmaMh+Eo=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470829847, + "timestamp": 1671691604861, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -736,25 +736,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAvg43KLrF+f8e4IDD7Mlf8Kc21Cp47Sx84RsiY1g7kQqgKjeXwhfnPtMG6VFXX0Ff393CLdCkQ8ZR+knzYWW+QLkQIyX0SgvKyqwr9+L471yPfeDqhVORzZSkryz4OsljH4vtEUN/izDujdHudTWakDGjrgJ40MrDiKqNRLaR1zINFO6oHPnPT8Zpp6y57xJr05nvmcn1UapWfS4PL4ee2OzZ5brp2MjyPXLa1urSzweBIKPh0ITbSuKNn5fTSDmDkSpzxPvWnLrDoV4LkDr87uR44N2jaWL+8kWxsPRhTts7fq27nheIMq/e8mVJpDUX/mBSNAvcPmSKbt9epmXmrsoM85Ztn4fxwZNZMbVrfZTakpUQPbyMyGRGAE2W7/NHJMWFmQ/nPK98zoq5H6vYY6dl7i8e+f/Su3kECPuci2iZGdZocMpRZNzxUeqoPUar63010odg8Mmei2MnAoju/rLWr+Nq9POCCN2ePpaoWwhH3Jv5Ph1wsStSbGshQdDosmN6HMiG5de1ewy8y5u3Os1om9e977OaCRQPFaVJqfjpS07bT8oq8l9Z1KzLj5RYwLplWqr0iIV6jt7VYeAGUajxiw8QQ9Fg8zND5ub/BPRZFHOjSWx74Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwtrpHOJwk/RkPE1Yv0hVgDYCOIfEICINBokpZZ/w4T0/WjQ27yJd41LlvMJxcS6BW39PHxQYR3tmz8NSKJOzOBA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAEieQcGd4sP25McFtLoP6jP3J2XotecZyESitn8WzsWOmu7YMmN+hVym3/zhOcUyLMfnvcgG5NvONXr6/12m/6Z3elmg61CK/8mQJXgGqso2H4+GRn2fgmAMD7g5eYj9bZVFnFPPAEMNLMv9p7gmH/+78lwJNiKJMxZRxP0+toq4PqJnDj/bS2SG0hXUGZK3JHivKtdh2HAGLTdsbfLrR/kR+EUJH2dyCqN0kqNd90maOhIBlMtD7OgBGVz4TfW3yXJKHRLd2qvlSRqz0xQ5XYNAoODM5IvZDT9D5cLqiRW5OnI3AoRTxNZNv8Q1dbPkUlYSbMPC8zN865HX6wQZ8MDHo9DLTFQGPXWZT68rUS/iOQ1PTW1jLZ+K3U9XkmEZymVjGzf7f1BniO19o99ZuVGB74PQ4IR3VXGipoYTT+rXu4Ng28iIfUVCd7EPCRuauMeiSlTB/GEUtLIkHSMbDjghJ5nOn60nCX7IdqsD/agFDX24rkaZ3FmJlwAYkJTnRjgdhlBpnzcaQJhAvL0t/fj4QBtUBfEGzBJxiPBGfJjIsrEFqphhMnz+73UfIiBZLPIHO95vNz5IUBWMZrQtx1xOz9NkpwltobasfxcEKMXZhokJ3WPFFVklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwnG+f2IAvr2YfeCLk46oDl/GfUU0BI/wIoNwsVya5spHQ0pODLBiif7bGwt/wC/fHw5Pzc0EiiDz9TLRtNxSKCg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "D34CFF0886FDB2475E4C12A89B962C2C450C3411C33CCA93034932112A98AD67", + "previousBlockHash": "02F0A6C6EC20CE1D08D0862785C5DE13A542698B94659A0800C8C81429F91F56", "noteCommitment": { "type": "Buffer", - "data": "base64:BpSptESJv3DREpSpOl0OWg/uz/i9N3KEDOSraMGUP0E=" + "data": "base64:Tg0sP6rIFKFCw19zxtKK9IJe8a83tvon3O5FtQ41VUk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:cyW5i0NdwUR8vXbgNf+VmAJBHsOysC28Yd+X+E4JOsk=" + "data": "base64:k6Levjzw76VRZCRFbBhEGxEY+rPQV307GPYjgwESUtU=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470831562, + "timestamp": 1671691606528, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -762,11 +762,11 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAdikyZJsVCHQ9t/dHINVT/RAd10eRhGVSjgIUXW+BgEWknyYYfOpYf7L5mVlqaxcKe5edUpLuk8f8c/QQcxzEqstM8TGvTx5/h1nDYkJ9C3+4O2//lRKexu2uU8S+gXukMmZ+7Vja0vkmpBEF/ZOT8Jc3dLc3qPaKBZLZV+KsGvYEcx8VLX7OBKgDRnyzOmr5N7DT5EDoJPJdJud8+odRdzfbX4QFILCjeb2VPtvBKvysrn+AUeM383N9Xdr+80O2L+1FDxbU6Hxsquf0KrzsVr4hODDfqaCaYaVho0HOfWZZxKd4OpkuQkIpLwMK/hvCyjTFXMFOfCzLnARXacqwFpmpOfCeSNf7kNuNpts6cgfTRbeNF3oxnrbedvLfcwFFIPFh+V6ECgJ0K11pOSbXGYuBuVRIRPV8EqayC3bwCPKDdG5bMcZVVP9mjCYBtx6+9+k1jOcgl/B4Mv9fqzJpnule5MB5mYa8lbcGSeMaTL1QgLaS7tu8RYLeQiCbXXy0+Y6UzLzFp4TRHkU+YOQdiUB1xh8y8LyV8Eyq4J1eYBvtF+AxZ900YwALS4Vf7l9IPHPCbYKPCl3QJY/f5pxEgvl0yj8Xw8HIBFsdGnjG/1pas4QCMGach0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCSTZQ9sITInY9U74ajlL9rGaav/JyK+TS5JQsmLNQUPyNhhqsrtD8mCrqiN+MAzAM8jyqQhP8RV0O8/u4/lKDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAY6Lh+3F8QcGPyh5kk2WOT7/A5Yw4vD9GgMeg1WoQSTi5GyIpm5d76z1wYf42stAIdupaw31TqLjB7IuhIYntDEtwq+PcFcIw2F5pX4ml9LauewmyZ6ZUKknaOalnDdqFG8ZDMTnKslGpIvIm+8vPaozJPftvxs7gOxn0iPVOmOoShMIwg/YJbRpc74UqPAw5mr6K2qnQAdd0V0E7emyjjsFv3F23mczG4iCqRTAUUYSBXioJhSp04bROVV8xCJJCqAv4u72swqlayhApBqwCf6fs+4O6dAqzvYYdqgvb0kAqAzJ7XtPsabCYgJ8DhPFkbbOy+XBzy2gHOyRRlJFrcV0fGniRIdTSBJPIuk2EeWR3baf4+qwLk0ciUfZASFYuFw4rTu2Dw8yx0wK3s094clxORWL/+aDwH4MI5JAf6w+qqfwai8dX8AO4z55XZ+2fJa3HCOYqULHZ6JUrRMQpWNoaIag9wAPg14EAJuBC/lRnWkpYDowLMe6PGgMaDJ+gigkDDGZuEAyiN9dRUl5XcFEU+IxJUe7tbOTYmVB8DOPBb+sA62wtCgaYXNeDT+itXBThvUX9JzC6vW343n2U58lrcXoZv0gEpNA7ej/cdJ2ggTVGgb8bWElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwxolsa3heezm5YBj8L/mZZAkZWiDIKeukljE3yHG3V1/Bg5H4z4ydQqL9Iquu8dC29ke/y6hJ908aGRImYbG+DA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] } @@ -778,15 +778,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:jYfeM/IAumQDCUCQ5aiDSQpYceSvcFmWgSH/RbAVfnA=" + "data": "base64:pyPCgZsNEv3ZL9U5M7Qo4GgNvhOIdzEyQXGEowgqP0c=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:QqJPZ45n/LSI5K6D6iVl/+8MSxFf3bJO8zin9Es74QE=" + "data": "base64:hv1AFNB00xnqK9A+EGs4Y+LkqkuNOwctCmYtPvJL2/Q=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470831951, + "timestamp": 1671691606955, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -794,7 +794,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAARaAPQgrft5IZCH+7eWFcBrudEHg8siVq+QsdneLK5bCNBCTuyoc+oSyfwhw63T54BaOBlYXXC92fuQ6QM+ARh0SeXNbdwnPvO6kIYKbB49quA9mpqW14Az8d31jRnyRcKpO3e8q86xNFDbffSWg9UreCa++d33cTggicYWJwzB8OKZ0Eb0vlG3Q3DkBtSr+8zcsDnT6wCOMv8eOTM5hbFuVvznP45cliQm94aQ4Uo0yGF6qXgeodiRQuq8C3ijR+sczrXJoWOgDWuST3y9wJVAw1Yta7pNLDdC2p+b96zBt3UXzIvlxKdAlRgGzUPtLtl373xHi+tNXA6gM/f8ASDdaRfuzIe2a0RuzpRy0Ur+GhWqxT6ULquUWjNFHnk9dO0O0MCdluXx+ZUu0FbEESx98WKKtdbfJUBPuhP57+pNF/sH7quyQXZ4yZhG+DVUNzm6ZhR6m8WE00IIoa3umqpPartcJhbKcMzvGHcCRgvndGmF/v0gyEJ2tqeeshjFrOOsv7jK42onJzc/Q8NUTwSt75g6ovHMNsEMC3/Ukl61H0FNtz17K55aeHqe9nd/2VuBv/MBWwtCNGGlXLdi7FiWBpz532oH+7ntPjeHt7BCtdcGCOLr6SPklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSQCTU5erC0Q5BJNmA2PjgJSWX+P4rA4V1M/xZ90M5vKo6HiPDen7SSAF+LK1MJxLFT/XNWsu187HGjIy82oYDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAJYjX2ZyxoRD58bGWB8ncrbdZgRS7tHk2NI/Pe11NjWiBrZQrU4UCqw1BQOUfmxwDebyDD6YzqCbWpfwmR5D9e5gtTO/jjXrYlC8ArEtuBQSgUyOWJcPjKvcq76z3A5iBPNYhkQrHfE0WpJ8pR/gyCdxvhWgZY9HKyiDy3WjChYQAcJz4npq4DW0fyf0CbawDw2dV9ghXunv1xySS8X6RWq5ls5nppho7ILNErvO5jLKFRDCnF40SMOgFIBnEPuW9GTsQWIQW37xGsaQ/EKilez6OOOEbvO1n5mo9CCbULrcVdyFGcdxa5UiydyRTzjXe6tN0l5BCv9E3wy9QRoV6O7s4ncCdUS69Z7EybmRtFngca3OiYOK82bSfIkpLgHtNZ0IXHuKjVdcZopjhMWDRGzDaH9ZoFigQHR/ZPqLYQYYFmPv/IR7sgy4sDjYf1qYfAvpVMShIg00kaoboLSBeZaxSRRl5Fqq7UuuMPbqJQm6PvgdWnAGPsMm3ncHAIxC0lLnKFE5poQE0D5z7PvVQUMwHtmjbwRmT3fthgE3Ptj+zeKutqpMEFoR5yz7ESNIjAOvVKx5tN4j3tZrPTjEFDfwT3zIAGfeon40+Bh9ITpsxbdbTNuBS4klyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw9/Cmxut6fQosZCxXWyG7qqFgMNdb1VKvLN/H15qD2skrfrxwMH3mnit4i3Gw8dM5XvAEwrcbL3p9pdbWFlaTBQ==" } ] } @@ -806,15 +806,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:AU7BwQGimq7MzoiVItqbmCDLbmIOk6dvJhv5+K2jJGM=" + "data": "base64:8dIuCPtxGi3mrZ4KzR8vVtvQgHDJIxKMYEXJnLLLDTg=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:rswRuzepUPf7niN159Kn2rhADKXbf/BKTGlJ2kPL55c=" + "data": "base64:nPFF+Q2XoMvwV8j2XmVNTpSExQaHXI2rkGG8qPmv6+A=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470832297, + "timestamp": 1671691607297, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -822,7 +822,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAa9nL7oQmW/HOaegb8LEigVVVYDPNwdgvAdPi9hHMjNmKG55JCJ3WwNMkCm0ob2F5+4GES8asffitiOtzYah5uhzF69kWl/MH0TzdnSBEZdmxVJjgrNvQnohi7Ex8eJHThVL9kIGGZsSd8R8TP2MPbaFN/5kmnpkgqIc+ddX3XyYCIuHFLvaiCLul302RrOFTkgS/eFvwKVDoC+uqbkINs8APBrZqXig1LBvC6RwVC42IHBeqcyzfdGmY3Kzcw/AtRmbZ+85G2jiyWFBCQAahmNe6gR7Q8zoJmgmA5JZJpYFyTAsi142iJVJ1lnpUQ25Q8Er7lNDva0oDIrvwAhaRGicyphdZWMRXn1OKUhbVtwghS82yq6nWuUn3cFb9NHxMLdRjqd7nYiErj/3VFNCeRbw47kq9pfmycdfdeM+t1w1CHcnxq/qIdkInkEb+fqKwfuL/Oki+XM0mJcnuGAVhnb5V/PEgBgKVmDzb/Y53NfrnEheAgICIWdk/aD6TkkDMrIphpAFSi7bIEgBRm9Lay58rIpfx90P/wIcdjs7gnVUtwQkTdpGbUanSCI92NtxwqlGvFd/BogtRnOPb7ztGt5yv+cjh3CfCv1ju41SoIN/kfE3dcJ9GM0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwaQ/VWrekHygW+hduPhYtmER8KUchj1utDi2RAxK6BG9YbD3qgloYFKySk2YLDOWY7x3Bc3uHE3cwFHcIkzDRDQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAD9YtZnAQCt9rqW0q4ngd3frS7n1+0a2F/qcMawaCrbSWPSdEogmBkv+RXs3szf4v1rPL03a0IxL8PXYOMJQp++aOKNzsRzCAefroxhZZOxyKbIVZlwMop07bTZv0z0KEZ7C2ZMdeo+vjCdUH7pPj6qJlVH0gyLY7R1Eq2yzidvcJNCxncQCuAwTTTO+Ah5SjsFGMvldZ0nQSnGfYHsXZeSKmigOn9bji59R2SVWasAmR9R2iCtg9clTul28aGQDl0fV6Mn/3+9gkR99zJFt8qz+K4LlyFx6s1QevEIbO4TFW8qfC/myBi/lXV6Zn93OwIX6deu3H0Og5Bfs6FWLgnOLo0Dpp/ZSVaLjLSdhppCx++EZFKeCud2q9yF3sY00See7coKUEJbyV0+1PgFsOnRLcIpkjsNx1mXDlLtrTTR6WyfA65R0wXmGL6lPHKqz3kntx9GZ4MRetm3nuxvJnn5T4BFbVhlWErgoLFUPmp8DIwprN+BTlPhvNXINtWrrm/opU9A+drGFm8B6MICUiZEQg1rRqHdsDb0Jjm7ydSPef/kthWaWkU6NW1NX+Jz+JtNoE4p4xde3kCYGYjmxVmA2RhyJ07VWbuheQmOw9ff8FlfWtMYSM70lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwQeZCheEpJPtI1XPPkjS84loLWpvjBuVtzR1zTD01UnNT+7m7HlcAS/sza1fcZpYVxn1y3ZAfI0SRuqd1b+WkAw==" } ] } @@ -834,15 +834,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:luUp0WOO9ufb50X5dYtQCUFcAU4ckCpo91MZ+H+F2lw=" + "data": "base64:4z4ug9HuPCIxJCXr0BoU6gye/2JRtcvj0PtgAN95sVc=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:qN86b5tlv8kN89rdZl4Lb/wXpKBFcPOEgPkAAskCYr0=" + "data": "base64:Vj5lwq0GeVWq6DIT4JceylwppS/mwF4d0wbIcbubLBE=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470832619, + "timestamp": 1671691607675, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -850,27 +850,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAF2wV+O7aaG0DsJMEF3zrVV0qvqNvTov0s1zkNBba3J2FbPyYU5EV2uS4iMKVFfBaTdqYl1Zsn6MGq742KztR6nVurEyk85VVvXONkPzmtXWFkO3jKoAeZ/N6NAhrhE9VHBVEVzNyg+QDOPbz3TfTXwzWemb44DdZuaLPlVu4qcEJKDeUD8CL9kUmfDf296RcexYR5Jcivxak36EgvH1ovPHUV0Et/LLJgsiYDW+dAQ2zZcDeH+EDYu0kmAO4uX0AleOXPFweGsnbLmZlVox68BIjMOsqbVwyAKJd9QS1AiS0/eVB+FxHeK5qTLnxghwvEZN8Rtq9z0wurkSv/0smwR7UCUhS9GBIXCvtCv7273n0GHBzajBaTJTozErPJ2VhF9Cy2+zpy9lwCxLWsjZihvpAiXeI2n7GwvvuhKO6zAprGfg8WmA58F//xho+yNDT5fF6MkTKrYqmwlGwiQEQsYmqc7mBKABXmp2aELvmC1kg9qUlmmNXXF78RnEmUNRLNXTogw0eapTWG8YzOy7K418TFFGTL59lagszxq/c4RaY6dSAdP4FDAEg0mDSgtro46VNeEZ2xJ7BjPTmyQx/avZHNu25RXNOM8KFFWweCsWHXMQQZrKm50lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwxTrF3hBVo9gz2dMY+bgB1cE5NLEpeMBDwO3vIa/S4adkCmhYrohX+Y39HulvZIomSmKFcdSRbnUGn1A7/lWbAw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA77As8Xv7MIiTWPIDEdiZHW9pmxBLnLHtnmb0Zq1/V4ermREDdYCapl96Y+4ajtlpn8m6LmYeekBowOuRxhtbi1J6g0Il0IEqAaPvkvRDY7CoBzzejm+KJ26LQCzLi3qqmyN6AdhCpD66xYdbqdKThpEJH04uQslNMMG38vFInZsIhXCK8F36TMUDRXYt7/sTUUKK4RQVc3wh/jTAOBMgS9uIDrlX74loRJr13zSy/GGkV9S4RLzZz9sCmuAcgt+HzNtFxUkQdbDxu6Lm2yc2VlMqRnCjUDvG0LmRCtMkhRV1T0vW6xNRRSvxeKostIAMy+Q6YXQWGgq+QP9mb/oxw2S/HBKOfipgGnL5ilmvWWwUpbH/l8LIQs/W2l4NMnogHsMG8fkQNNonUpW/1hsYgLaGQOpS4E516F+gZgFmGDPcmHdi191ViuUy2fSuTaPVwYQg4BRTgZqgpVaCNkMDzi2hg9c/KY+ellhWCth7NechIgCqmwH5BnvClcfdMUq4x9a8K/BKOTWltxk7qcpuiDwTtxTmQcc22uEQhe6VdVrmBuGZo6Ws0VGfl93t6Y2wP+2KNJ8jT5E51k8H9KhF6fHT3k3xFoO+BTpZ9aEyawllKw637qA+LElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwq3ZAVHeJC8OOMiF45bv7kiUG4vUbhENH6ETaKXb598r789jQ+Q+y0piWZK8OtlUYHrysNPNHPguEs/dcUqvYCQ==" } ] } ], "Blockchain rejects double spend transactions": [ { - "id": "1c8c4941-2ad7-4fc2-8262-a1be8ba50156", + "id": "bad309b7-9afa-4d23-aba2-77181c214b9f", "name": "accountA", - "spendingKey": "76163cc13f5ae11bc432bab17ffe09afc3b704b590f36c34221a658c9715b235", - "incomingViewKey": "94b24ea2bf284e8eda9284af39b7015378b239dfee7a23fea326816a18aef105", - "outgoingViewKey": "98a8e8ad87cc9ce0ac7a4e8050b923994aebd50455ddad12f6600b19526ea295", - "publicAddress": "5f6e6ee122d34db34f53229b7f57db7f23caa73da4614bb5fdc77b0829f13ece" + "spendingKey": "bb752a0165de85781ca49f4fc770eafea09fb9a810d98c7022b6448119a82429", + "incomingViewKey": "65ff9dd3f0069f985ec4b7f29cc0993994d3511ff1c55192db6284e750da4502", + "outgoingViewKey": "e317d1d22b7bc2ded088cab73ec9209ed87b02ee6d5dabffad9c9e2d4d0145b7", + "publicAddress": "5c691b5c19ce50464af6ae914c431f4548bfe1a1c0967f450ed8a7b981241194" }, { - "id": "7f30731b-6c5e-4b84-aecc-696149fa4737", + "id": "6b0d0c72-a7b2-4336-a167-be8815c68a3b", "name": "accountB", - "spendingKey": "f457001773dcfd29515897dfa16d998e7a6cd80119cba116418e7f9c168335bc", - "incomingViewKey": "3fe55c702f78baa1df4d5930c829bba24f9255dcbc2b1b37853a56bc414c3e00", - "outgoingViewKey": "d8687b853295d6850d58fc67e3d253758de0fa2a907fa1417e5cef8cb5536975", - "publicAddress": "7a6b45220fcb2b5d1aaf38451af5431b619aa23ad6cea94a4ba2d76482f6e69e" + "spendingKey": "d53b213fd0eaf184bea4d68889164ab750581c2bf35053aa7184e8f0fb816945", + "incomingViewKey": "4748f8c6339cdb7e7305a32102b21ddd62a0d602867218191c04e95577d9e605", + "outgoingViewKey": "5edd51bf95a0f8d67be83b31ec2401ebfbed76bcf60c35fcad5460044e354849", + "publicAddress": "5f255389d4d89c9bb6d8a450e91f913d97a2aeeec83f4b796c37daeae8a352c7" }, { "header": { @@ -878,15 +878,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:ZGdtdrdOkk3aszFlZVmYcWDvRLCY/aLAkC7QrOljoAQ=" + "data": "base64:Uh8W0xJh3Uxrb2ayWsd0rWJ6ZycNtObgWNn5XmNjShU=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:jos7jMCtRig4CQBw0Q4Xk3t2NvmyiXwBa0tUlAhw5xM=" + "data": "base64:Ldpe8sKuNHRSDNHHUWQ4Mk3nvTZyrGnBsCN+SqT+ssc=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470832961, + "timestamp": 1671691608044, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -894,29 +894,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAtqjWuQsIWc4QRLjRcZoj5xr96DN+qrsEYJP8ex9Tyc6QlCWT2sOjsR2Aq9LBLeEAymuhJ81p5N7krXHRgjMfR+qPxXbPtvIvQsF/zcZ09zWtS7xfzn+PwmLI31bE6O4V97zlc/x+mW/sozif1qdWG20TkOYvc236pNkyX9MGW0QTQOyH3nnQs9NgnMGFm0fF80iSPl/jf0GUSqgv/64cD8F2yKj8N8IISZQo2fUkD+eyvzSOzqCKx093tJuF2nymNpxeRAvcHdRGzkoRBA2HenL5gduf7HtFH/4m1YLev2MRVX0tFXhZap32HaQdS4tiKZDk/UxgX9E8VB8HljIGR1twh7RRwCWaMC6oy0MLc/HToYw5Dip45AcQEOhN4FZUHALn/WNpB+UCyxhSwf11wYTIlSEPkKw9keooKR+EWpROXUAHvwhStBQBIX8PEDyKf+pf7TJCvBrwq47hBCVNu1idZij6cxfFT/k4AorzOuRU5XT1HOFEuwZBC4Lan+Dxj7S9vHwbfyCiWyQrjWQMqNDfcKsWrMtVbCQPsd+5pcl+zjNAMSjaivVYwoR0wJsk02vH4lwfTNa76R5nbQ2nHALWyrl0uqXUcRXfii1S6VuPV/dGWbAilUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwy4FglgWboE5Qe7NHVzslzYZssl0qgqFNtXxTlaFDHcp2KyS8RxWtmWf4BwGd98nMCIvPXStjvQvAqz+aWRz7CA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcgjuZ115CPo3awX/6V5vTZyGhYbLr0BaL+sPpSYyOjO3DaeGQ02IT8GT0dRmZzt8WVw1KhtcmjVhAznVcEwc+W+ATvZMQnkDnonUBRwWns2p+JTh33lc3ZiA+Zq7IbISqZCctRWj0m9Fs57j22D8Bnaa2AJCqmLCc5qWeugKP0MJU1dkmjblnUwMwsXyq3PvdedSz3OgpwxUZn/mIWxOZszVx6w9AFvALZtf5VdJ8lmjHf0JyuOrEZXdnu5BCiVAe+IPGW3hz9h4zw5gRvTe0q6u6TdWASuDlutbTtMZzfA5umqIREwKOiWSqq8qR8i6s26WeeXGXv0wjlCwAKp0865kO3jDA6KjU7pRtrg/4vNznreDh5dCLwUTXny/UIBfd9huwWgk+J4QM6wuNCC8Q8mGwajN/zDQfVom9TaWPCxzOR8cgJCWVFpWpMQ2f8JyZcM5sJKPZab9tH9Sqj9GGwTaTHOn61wqOeo34BpG44ktFLQpLPaEEx01gFVbnoKW2BofHei6JLqz9PCPbVCmxcDJ7atkcqETkf2ZQd+JPy2aJ0LfHLZoizNkaWGd6wPdaON3v4/YDYtNDxkrJls6VvQyTCVWUnWKj+O813uXrV5NBLkQVfoknElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBDCGB2Etauhf6qfHPlfY5cTx7XFobMTmbWLszAcAyFHISV5FhJU1AQ/nIIV4juL1Z3uIPHLpWeGkK4NSThDkBw==" } ] }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArABtG0Zmy7fh9/yGmuW6q0309WTdaWgr8b1j9gIsDwWm2AjBocgb21UUf0tA3oJ0Yz8JlXrtUCCfVl3H1/jCA/GJUDglp/4QEr4J3eshkoy0vpNRxYrgNny2IHYoaaWFi7vFZUIiUaWHAhZSgeRa3AhDJ4QFmq0J9v8pnHfzgvsGjN5poe38QYzNaM5HNubSQkuFaQ6ISrBxXlgJ6d54xqC10UZRr8oE3DvWIteVGbS09cLlaTgZRat/i5m7aNdoAP9zZI3QQaEswl4phdSsTQmkhSB7r7YwNiYHwHOlZEKM3FyxZ17ZDv8t9W4Ugz60iuE4Fy6sjGHDmtQawNEVQ2RnbXa3TpJN2rMxZWVZmHFg70SwmP2iwJAu0KzpY6AEBAAAABII0DFAsdbOdtmHoJC4PpQrDsGH9islPakMnh0NZ3DfMD6QtDt8Ja6xeIVMMtfk4aLYK92vpg+4WwUbCgqPCFayl3Y2RUMfKxrqzNGk2HNJCFnDtZI6QRP5NPEGLT83AoNkj4fi9GbqY4gceRaoCSmTLNlSFMrjUK2hpdvQJmIlimxVoqzIHzZdvLNwf4Pwf7M7YZRhgcE2CMx2gy52qougC2N3mk3iTvuzUfrx6mhpNrryjVmPNMiDmT1BBkqi9AT9ZuC/wzN784expKRXVb/tiUQPHrNiZVjBK+cW6pvUXXDfes9KP87YUT5CFCCW3K9lgJAK5WBBJYjX3asMnn9Co1z9fAEuDzUN55Vig1LjG64maeK7lzVMqOaB7l+rw7utTyi4Mtonx9qWILdeSI4ex6cr86nDPEbCrmtKyJfzSGNpJLtZoL0LKq30jeKEj9OqtxBHp79E63fGWazFahK706KGccDMELkeNeeO9Bphy0wQ1t0p0AbfLN2vKzI+7ChlQMroBrv3UOZ/1ul2Ltsfu6o9vnb1WnBaVQwQ5YXETvqgR8yI1miH4Pn8hknBbBYHwYRBsQhkWOmvHL/rqohyOIpQcYT/bTlY6FptXed5RlmPWxbpV0xhOHeBU90OWGx5ZsDK5OFU9Pd88lf4LEsfkNEN7vPqNQc9e4jVKkBZUnRjFZGJR/yRmrWABsnMrtD4bFOI2dzpXUvzLsijqUnjp+Bphum9PxRB4uVzGyXjTXFe9AJhsO03K52Z640BL4Rc3IXbkTEFjiYE0R8kVKBR67iX89tXlYUksv0Pe6vuJADObucFMY+J8FZ9jJbkKBXqPgBVGC3xUXiydIU6amtgG0GvnFWL1jBmvPYwwaBmPJK0edNW3+OxEP4T4LlHXDuAyhjZO6dQzdkdos8IfM8ErDUOSx2TH8l5xn2uITxY9g+L3RbrnQkEwvrSwsTXuXUUisy7WttY9Nk9SwZasxFMgOf5AHVOUbnhl7RXZVk3Z5NmkzxlkFynJG6JdRdxKdKtigsi24GPdke8/mgr6IFkU2THL0GFRSfAGXplalzgL++D4M4TQWFtczR9G+sCjInN/aVsLP8gTfkcabs1GrtG3owU0x99wLbapWxVu9D4UIdwJYT5gYpXggWWmJ//7xGSJ39prHZxLBR6ZAyQwvtmcdBLMgooHKqcwbYavxCL8a6JwHUca6BSkXg+vnwQ/M4amJlWxAgapxhbu+JtBdfy9Jka+Za/YYg5KCyh1KjsewIQxk2WdBnE1Y8PwahGbnDTQhjn+QyNElHljNt54ZXxLgkjS0QQXMx0MFWimTZeygFVqaUK22qw55O+lJsRzKcWyDn0w/J7XKNSW7/NX8tGl3z0zKDABTp8R4AOtDnQL/S7uYpBTyPcI5x1YRJYETHMaNVQqrrrP8tJHA//D8k7BWvHDLJXzhCJSF7E3DoUuLDbMwzslEr/XeBmEkXKnPsvMs7I9DoKFj8SPyils/afhtEHFuSa7UNKI3CtFitBv7+BNcgE38Ll5aUDmzZPA7HbQwyZ/zMRb35CbFqeJ0syjEBNHD/byBCXQH64cmnZI72IWCbhYPJ6CHbL+Ny4CA==" + "data": "base64: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" }, { "header": { "sequence": 3, - "previousBlockHash": "53DF444D5BD9EDED5FEEB98AE1EEA640413F853ACDEE64B6667A27DD07D2EF4D", + "previousBlockHash": "6A4BAAB1CFDFBA8C1146170490E18482662AB882EA39670D149DDE30958D7CCA", "noteCommitment": { "type": "Buffer", - "data": "base64:oFb1qh6cDEFc5FK85pZXEH1tW7qQA5AvE1Btk8+vEyU=" + "data": "base64:98psowq6ifuDD1A3XZ7e8gT55aLSgZYEDrrDCB8CnG8=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:GHL3DRtZ0KNb32bazzf1I6fqyediYeFThNsKAZ9LkO8=" + "data": "base64:K3jM9SkRDWlfuVWQ28seez3w4Ais2eBDIfbDjiwRi84=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470834613, + "timestamp": 1671691609819, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -924,29 +924,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAqBS6dygTusmP6Aetrvht5dhtaA/ahfIyCAVYdiiMGkSriNd18TlimFhaVjNahoU1Bnmp6VkfyQ1ma+493uTQU4KfiPGA+pnbIEz9uOh0MxiN/F9L6+3oCqrppHJZ9B8buQhlmjjI7BaQrbuIlZ2cGhi/wAGUZFyWIkCFp7x9p/MUZX2w0UHZLvjs1LDvQ16PK3MgrzhEWNMBeyx6fAjnFMQeXqXUVeBuDFW7DjEqnYehQMdRPD6mTflB3DHhoHeJbuA61G/vLdj8E+3t7BYBVS08r0+KPN0WHoniNsN7DjRGhuKwzfalA4omSH1xU60lTSglwcstrynUB4nftxegysBR7zJ4DUnIqznkFhrjONVc1IqlspEjN75PetxEgd8kxbjjSauACCKeaEBHMXf0oFhOXHejq9qTm/RnH53iMTTNKt7HotwDSP6lqUdUTrfDMhMBWx+Zr5olDUJ2IVWXH4RBsHAJo5fHeoFKXoiH4tqhGetzWEmvJJ+PiJM+wr8WfOv97Foc1gUdBqW26Yzv8TOW8FsfT0zEtv1XthfX6ZGDx+sm9UyA7RiXkOPTShSWf8gilRb++i7o1NiRLDvElvyqahdVos7ELbeZwWeTKo/vKE2zKu3Is0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw6+gK8wcXWgLDNpRRvfgE4dRmkAlKMnWUy4o3GHNc4V4TcZ0Pw3+ejqwc1EL1zUykGVoImmlBTGhiWRR5Y4ONCQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAli5x0vJFIQpqNC/Fv0VkQv4458VKHnvE4iNC2xAt7tqzKB2Sd7McyaXVZYNqKdRjookIP030VGKfDasC/s3v4pnlC+NDVXIdBUQ67h8VxCaot6TfRpBnggIdBAfL1pQ6UF96MIxzoSiS8WabJDon8HuoRBW8nbTmrjYbQVRyB3cEIagpWQJOuJVsn+847zJY3CVcq5aSJ/SOkcze73wpC7Mak5Q/nQVE1TSixh/mw8Gha0Ee/r6LsBMUbC/7H0+WHs8WqPoXFTQtjhXnrYgBS3EFXhASpxMWgdisvQ3PgKWVlxtVHYDIgC6ObWvJDdIclSAW2WYmtLmvFVaItougqVq2sxqXIBtqa5ZunxQ6kowkboQM0LIHm7iPluOlwPErMoiJ5yzx3RCD6RAcrcNuutcTzPydvYymW/U8f/U2cxz+wcoVxqxowv8DxL1WWsEeyk8ENQ5eZYMJq+hPdLRDIh6qs7pP58DxJELx6bpI00p067xmjjMRP3i7+TQgBw7tO34Nr2Q+UrqvDB/1CbECcWzX/WUGWIhDMNyWavfEta7A2qikDFWtWGWpDg12dhepbzNRRzR2ir/95MBFcb79YXbmkLg3NloMu0ZZ2zEHckOTIDC+rhfB+klyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw6SRKICCCCrunJ6rRv6y9KWKsUQTxmlaGiZyXnyyI2ituCSzt8MYQVG/4ZHSAl6hp7CU5+qOagA2Oi2i3YNTrCQ==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "EC8928B39318FE36DB5539CE97CB10BFE9E93B641A0BB745E99872CFF44EE7A9", + "previousBlockHash": "6FB081B57F20DAFB02FE7B482C8FA4873B603E463646028938835C106662027B", "noteCommitment": { "type": "Buffer", - "data": "base64:moPBo40+n8R2qeq4HWMjvZVv55KN3IulwKZV5Q+CHlM=" + "data": "base64:xUq3YLqL5Ri+AIQIN+xGKQ2QOwYn0Bx/fGAF6CEMKDw=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:/LJsOjXqzH6ce4XOnjFT07GWbkJ6o1beAjsiEmLkn6k=" + "data": "base64:vGI7jeLHHJMtK3/qPBHGX5BJaGUJfgskteB8/ERj18c=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470834935, + "timestamp": 1671691610150, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 10, "work": "0" @@ -954,11 +954,11 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAJKOVF/tKqC9toMwbs4uZ2HvYO5YRl5Li94DmTrYdWgCiwyC8g9OD1hQBPqqACabGDP4JECYpk2gn+RUfCY0nWolzMOWghW0s3x7C/BoHOaW5ozcVOezFgKR87VfCRoA4zmFLtWT8WxuayVZbXprJrTYaEc9i+WrF6wyhyDBsoL8BqVgsgxMVgASLFjq6egUvRj415Tsu3UKXOmasePxlYpzwn0zmadt9KeEkLvzG7aeNlzdbIllG16yLB3vo20+DHTa/mbl+izmyVAAJW8STEjc9hzYZ2No1Sj3MAj0wqU+5LpUetovbX2GjT+U+o714ukafP8PZgZVv97Qmpsd4hEBuexqxNdJDwkQvoOjFrdvAZy5ccAPzgSJ+XkHVg4YhjYQUkOtDl/4axrBU/TO7A8bJpeBnOk3WlSUnJZKrxqaHE5/TIlhUIN5VhoCig0ARi9bnZdNY5Ioys8VIVv3u3m3QA4BeR32kARraS/iT4vvnkipmhqJF7aS140nHodPVEnwccAGWcmJSBsRaFouZKp4YxzHrk1nOFtt+dq8AC1NLoxuz/nr7SFiXyF4COwOcrtARlwXyO/xDf//VlUUbH3fGsxU8O6Duv8081VCW9xlrK0ziJGzUMklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJ1ym/mz0wetLgXoabGaXFmlfsPCddjkt3z0pCtY5aq33xUvybqQTY+ttHNS+4Ru3F3Sr4WsbMNE9t8pfh4U/Aw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAVL8qBxMRO2cjDN6M2E0LF8bJwk1dBLhSAn5ywpVfvSyosiSV2R6tmTdpFR6bmwc5pwyLCsUTPsxoIpnMYNlwAfCfWZmMIumj0Ak56zsZs6CCDYkcgBEvmY7NJhZ9B/iTBRwtVqmkNb/AJdj6t379t/uuu6L7OKxetEk3BeVoJb4AKtUAJSu/lORNy75lW9PaMaEH2+qvr77Ijsa32HLqwFCkSzPklpDkXPt8JkITOkCEdb1VkzYR50FoenTqfjtUXWLlkgkxSDy4Tfr0c6VDSJ7fW/C7B4Nrsuf6yUrxdyobrJNO8yrwBQy9nVbB/ECdbtlvF6AJtSq6kjDv4TdNafxCyJrDUQTWw+hsvtcnfVRn2vVUW9bBVZoRicKmDmQUkfKFJSNfQ5xrbSC+PCrN5vxnTdgfo4TCl8l0h2kr7mmuX6IiyyQnqVdr/UiL61opVpaNexyO4NSMbVQv/aJWnDI800KNT2YKu1zsm9qdAlxbhv/bLjQrbTBuHnCJDsnDsiBFR7EqEgasXphjq2SKaxeaOvKo6IH5ZtI3/B5USsu7riuBG2ROslyhVUImVukkNVI9xxl3a6lLcK7GjvPWuNpEyRdhFl1OQWCUJu0omM4ks2JgK9Z6w0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwkacSbV9oM4GsEjyxuFmI+SWnvL6uXyjlxklLukfRTDUVa1KT4R2CeRuJt8JPSVYqgVPo9H89dSeYisSktO7pAQ==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] } @@ -970,15 +970,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:pqGk5CptP32H4gwWKZzaHzdjFHUOeprcTygqZiIO70U=" + "data": "base64:oCrxpljeB4oRnduO9kxF+hFD1RoPT8PK4vO7DXraxkk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:yxAsse6fxkhYwQYvkKMS1KZ3PA9QGKg2DCCJDTt8f/U=" + "data": "base64:YGa8syJ9HXW9Q68Rx2fTpM/qgnaU8vDA5GPDXcjymqI=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470835312, + "timestamp": 1671691610560, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -986,25 +986,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAfV3hlAOrXeNJm4E4971sYKXI8ynImT0x7ILMSvZ/q2GuVdxuaHwMJFhR3g36pqNpwZlEXJOrGLmyrTpELQwfITfZtsw8dndqb59fmqa/dYmRiVgQvEgn0tOSD3mL1MP7zoztwc82pTz+rMib5vFqc659bwu566EuHo93nj5yO3gGFSxBpWwaU58qLH632G2Y/4Lo/51KV3r+NA99eOsQ40I37elxom7vTNvpNMkD+tiX0vM+77ASdmpPRb0IB9dBsKPeKYo8TqoXB047036i44kUVUL49gFt90Fzo4sH53daKaZ017hPEqeVfSmKxRTETJ5EZmv5tswlhANjnQSj05RSblitlXpy3XbLYRCrvL1H9an85QcUxoUs1lL7JpNk1/XQhrrm2Oqbf8Xs2wXRRs8RRjpFtxKfO2E2g86Ac8KcI8fsnMLB3zdm3+C6h1HwuN1vj67jFL0tiEYbNri1N+7nxCJaRYMTlZtiFf//ISOZmtEWuBwooWvJIP9OWnZjLBkrOEVXez+aCOAWl+1QttchjBT18BFofDh/VdyGA50Lj4nsiE1pYgwTLY+EwjEVJGPANFrzTHIS2wu9QncvFA2tXBqNeGlJZMiQyoNKALmEyN+44egbjklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwaKXA3SbUQdi7rHTodjknuW7Kn0IxzIQRmKnfW4KUhWu/1eIpGdrvUxd4j6jbxSAPmef+PuELSxcdhp7BaSxeDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAvzph5N0nIcu0maXkv7J2iPzJj9cBidMoOeKb8OWMH9eMhoPLhiVX1A91k8WS6DURbwUQ3qvQq3DYK1p15jMDdS/AHRZvpUECzN/TYaYtVLeDLssTsU3NrW3rSfTEZytfG+T8FUh/8MU9zKUcHuKrCBzRLPKkkvqMqgYrcTQefRgF2tPGgHDHBZEHhqx8e+ikbSREBx+fZ1Di9+cBtfr0Pb3zDJMQPzZOeFNosZtCytqxuFUuXhD66edyj0f6a2CPB8xFzDsgbXGxoY5TFtBWlS579JsVIYZlOCQ9DDu6b5kKUOVwffUBfW3Sz3wRggPxAeNfUB/NpZ4FiPL9Dcq+A1zShckczv944WdoOuzOBr0Q9Qr+h+Fn9gNDyPHG5l04x1VF6AsZh5SobbcXfwsJ626C1gtQcTH0ptKyE0cPnSRjb86qs5ETc1u9k7OlFGjXqNTCKf3+zqwr13GgNB5zIJ8SmZi0sadJVava34K0Eh1WgZyVnxLRRIpsHgE45oSJRVYScG59fttsunZyEsnPAoLgOuXs0edajI2KSgoPpMsqJV5OSCIAUsxZNo7jz/9jReKsUcm0mabDQs3zXLLavC2Smx2CL2Lpe3LRiZozYLOaAr+OedrpVElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJh4/dCqRfCSWh3nmSavVWDkL1aHMTd3LGfTMHki4w+K1NpuFvycSW+QdCnFHHASYY76GPFMPD7WWb7jYKaKnAQ==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "E890B7F574EEA60D2B04A72ADFB07F072767D50DA677CE7B8C7F58190DD95AC8", + "previousBlockHash": "3218A171CFD932E9999A42DFEE5C2910746206BE9C892CB275895176380C1C2F", "noteCommitment": { "type": "Buffer", - "data": "base64:/8lbY8ger16VmSbohso3u8EJtbYGA3SDDnMsXeNnS2k=" + "data": "base64:Pwj7NGJvIfQssFbQXBrR2fp5X8eJw9eRqqG5T4bJy0Y=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:eaEvORDZP4E7lkp7D0EJtx+bnN09x6tMxEXTBvqhuVU=" + "data": "base64:4m+kwvSfjSZ/OFj5Fmo+qIllZjUwt5+QRcUaX6aIv6Q=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470835633, + "timestamp": 1671691610869, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1012,25 +1012,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAPwl06i+c2qplRXLJFOzs4YSA+0dc+vGfuBtLCoOaQ2mkD6MJQF9TYPBO3bv1jm1DLW3PfiqfWGkFIuEAAtyfYrHkJTjInAYSTFmvv3hwAaeisI7CbsUlE9xp+Klo7w2v70v3L4wQILfYTxtKwh5Jqp8obL+Q92OUFCZ+Wvs0aEkEc2dpE4fVCrncKR88q948OTUbOMW6cHW+WfYFfxyoZDa1cVaz7mnqjYxoXHUxm6qMLEFQ+2YmwD2yD6/WAQ6oEvRYPfjLW6FiLaTp/T9fLXbB5QPziLkzqEVZlWs9mLy5NtN0H7YGuQuYl3mK424Km8V0fexIXUVhWxeHul14FwCZk2XRVKqSgFXKBOjA1mFFM3UDtLzw4diLXQ+KXvkJTREtI0GMV+7f8KfmrOs3NqhNWOzk/XOVN2d9EfYnBo+6sil+F3cpBpC7fl6ULAZacZpR4bHgNFxl08j8lVW0daoAvYWVxuYQ+1/5xGf3jdttSmZBZJMFV5mjKZzpLWaq6DKYC1O6VyAZjzAPneNsU6tgqmM8YgFhUwYCSiM4giY7yKj931u7S5BkkaoAniTU8c9AfBmg6xc6uXHAswUCB7SEnJyMg9tNrAvciN9ACyWLpEZwRLQfZ0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcr0uZ2kLdD02zDN0wXqJgmUrM8kwYkp15hu1a5y9DoaqpUHUt0XT0YZEyVtLwwxn32t/XYZ12V+Gk9zwh90fBw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAASuCgf/fDYF/snB0rnZY0sd25RkmpFQxCv3UZiRhumwK3luEbSf/kIA7HedC+5vOdkPMdiGo9VozLt00BdM7uS2Sq8h7yKfuU+F0yyhjhMriO90+ZhaxlxzqpJBnhAkoN4Xtj5jo43rIHMaJIKAAYDRYjEb95bwgxpDR+xCXm1X0MWqk027psXJxDhH30F9tqfHdVqq8/wINDQabbhtllHTeNDMQ4fDSDg4PqehlvZ4CIzKTJyFzMvaORwNXpqxyfQR7PWNYUhRlKBp34xF1GNSjea6zcUV6HQMdARzs0lzEaLbKK2KOPT3469UP/3YFkfkZi1OuYFm/jYE0YnhztaQrOvsAfRdpabu0I9/RR9Ea5Y/lJqlIJMWSrUTXRjJ9LyXic7pl2Gp+2FceesWlgRlfG39sUwTLnWrIOiSetZRZvZRU0PzBvqS4CXHlcsF2xVn51dwlk4gdjH17teX0ZWybTp6KqucT9/jaHf0UZznYVe/xtCqWb4WrzPOSctDSSJI4xdAjjEP75eH3+Gm0heivU17VAbUv8BlGl75gefhN4pIAKXBysewXq6vaHIBYiqCZO/2DlBajAu6hETjKWlyura96ytry+gmrOtcqj1/LxlsJ7WbqFBElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmlgKhaJX7px3ir+JMms5m7xcc9bH30CVC2ZJBpfhBo6hjO++8ENx7TDxYoQi6ptep8rMVNYr+xm/fnbgK8GFDA==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "CD9B046F75072422158C5514D73D09609DAB8E5B88759610EEF4918CF0A4E6C6", + "previousBlockHash": "89F203E03BED05D44EAD4B5BFE9D4BA0FF65C4CB77517B9BBCEC570917596ADD", "noteCommitment": { "type": "Buffer", - "data": "base64:ZchCjrv2H8uB9Ju74XHH7oLc8z3PiaABbBD/AJ+EvGo=" + "data": "base64:Zi151vFXiq1USHDKY+bFSXZM4BI9pz4DJPTi8g2xjQI=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:dfpZ3GhJyVHCjufz5peRn7g53dVOr+ZqhRxlNv58MU0=" + "data": "base64:B/JD+kltvsgcfcAkS11N8W9J9NyrhS409eP3bzAbzJk=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470835947, + "timestamp": 1671691611178, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -1038,25 +1038,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAQ0N0adX09sqSx0owhyfeuxgB3Tf2chQJIyLE/Ndr02eH7e9nPcUOBBFkBF7Vm15GJNjf5LBPY6i/+nqbp5L1X5KsC9dxkKmgn55uW+g735elfWiiE/JXKrT6Nu/DkWS5J6OAsrmPy/CalE1TSSIDPFsbKPUahF5/irARlfB5fncHyzgAPBBdLycFR5wHIEMheh88sAZG2xs+1X4WhlFdLZrjkIza8qlOJYU7slg3wJa02ewyOY7vxIHhwykJEokPoWBc1dPgPd/lEQDb3qrGa7qIlKciKQGmN7qmPUbhnybkK58Eb3a1ueHSFTT9ptfV1UlLK4HAZDWR1fc5irL94mu6NrEM1sylh4+b9C6txP6yJHmJNVzDT25mCSMuDXZz1WKe3HjvEebHk3LGezn9FEjnmndUllLAT9xyXrN+oCwgQHsG1al2Fy3pO0DwvaXxrSjyD5EmGX0Xr1c8+iGtDme8FZmzg69Rt3UeHaELmutJ648r7wBAxoGKJgcR75fEML9GGptZ5fzee04LGkGyKEUpSA4RfoqSnLMdeMe4TJ5OqBHFh8ajHkJuVD1FI95V77N0upkOY8lnHbNQwolZkJOgYYUlqdDoKtJcdKgIDyhikWiKS/gWy0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwr8hVAjbj1ZDsTuaqgsHjJjhgZpb04w4sFdSacNQiMDlHXMBlZZ/FjkUZcmRrT7IP+lRXgeWGIdpJU7IItjHHAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAyH369l3D+9hs5AnkhVKU2Y3za+pEpY5XOSLtsZQy8TG2SACuG0M985+yK0tjdNZvGFvZbhSh50kC/j77K5Pvau7tvGmS6gkTaJHjLCwEPLCU+mzU+RaUbjoav21AbVTu6C0bVo7DJFTJCmHIhYgIuPgzJPg59vfXGPou1WKkR2AG0C8Rv3qTaEiJCH2P6J+OWATHYLYnKrlHHjFfoboGubSpOTNWXri/i9xJg98nwcar8hFSEvB2SRJkuBdaPv4fTSALONmzzPoEvpROPPGnV/iB1Ot+JFpsUclgP6vEaBzUvBrOu2B0bK+S1MwX3f6AdH2BnmrMd4yK12KbeHyS12R0+1+kMnqK2RASilC0lzHmK5Le/BLmW2j/9QiP5UI0yXtshXrvmqRn0MVdX0ohI+hHWpBjhd/onvqgmv+efIe9NRs2mk/YFmDCitMVLm1+L356qK7z3aFFhtnjVSvU5LNZFhVoHrIkHB29pboH9z6gcaF1myOIdeNvAAhKGc3R8HyfRw637epsK+QB/5aBwSEuaRhyjTHc5Kq0oCg1C9VfuEAoNCXFGN76FtC2XaHbhXbSTSnoeLHiGJDdpSi0e6UDwpBfZwS5tj0vTcw1TsV3L6HmebzHFUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCeNLELho7ARMOHnJvCE+/2FSccaMOzkx0vjZI31onj+TV5swP1CFrDhfw5nikUPgJtjIeQX/lxkqJRT911qVCw==" } ] }, { "header": { "sequence": 5, - "previousBlockHash": "8A90A94D22D45416691E4C762F7ACC7003840051BBB7F133DB49F72C27412484", + "previousBlockHash": "C9C14025C44612A9B417A46D040C523A893E316EBF1070827EEDEE3F9B2994B0", "noteCommitment": { "type": "Buffer", - "data": "base64:2/ZZijoFK3kNwqyI1tKnIlmCF1qn1NkWFhWqWLtxTGE=" + "data": "base64:kIyurApCvlD087S2iyNZrr5KZb4R5toIKQHbN9Z5cG0=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:Ro0vOTvUFEi6QkUurBcWaM7ylehSYRBgODnzTGOcRTI=" + "data": "base64:9tixZxGHIqpgZWi4LbrawrfZrPab6rLCO12yT6dRuxE=" }, "target": "875726715553274711274586950997458160797358911132930209640137826778142618", "randomness": "0", - "timestamp": 1671470836250, + "timestamp": 1671691611495, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1064,25 +1064,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAU6TaV5zWwDBN1DzwxKIhGR54STSDhE2o8wklUCFE4kCsHxPQcLEQljD7/lNwGzIYex0/fNOcAQptulLiJhqee1ii4WixzUXmAeKp8b6cZaiK/O8ft96C3SbzADmSw4L3IDuRn45bAJlAqSi7rwY9YoHkMUMwuiNKfBfFQnKsbNUVwEHBRaVoNpbrhGe49Hnh6B7y05dZfU/kdPEFlGXqbsUibn/gDYUaeByrks1vhh20mIobi8ZL643Rw9hIeE+kvHGF/BiEZTMIoAB0i7n1wWycxs3sUvOpx41jnxtpodWRJDFOwpwRB9jx+uov7nVYxfOifp15u9k9++gTONhIUo6TqdmaVgy3fCo7GtQKQPsdOeV0ReIeZgR6pEi+h7xMOL2Ex24UmVI5uoVcowZkgJEpIBzQkGUhu2whLJ/B/L7opIEh8ZXiqGdmQrKsev0I1OM4nNYMThZtGJD7b99xzPoVp/I+ETS1VAhSdLfwCL0ZnnDPpAeaiQNj6lR18aZ3aI5Lgzg+jNs6YbQvBkJf7fSun5cdaHcVgtmmXSqE74cvUAD1vUj8nKE9jrrlwUW2Zv+brqHNHU1oBsM/lQdPbvyqyEMBYfPEHvUiC3sbZOLcLAHZobSR10lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwV3C+tmr61QU3zPzoyQgxC+rdZqTHu0Anns5NY2+guIqPcRcnDDeBogvpZOF+tYH0NwU1zF6MgmChL70ni5AWDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAz7zN/gUYG/Zb6AEUzQx/axwOc7jirkaXDuPheD35OQmkipQ7yZqkGjVNKPDSwCT/wtqeuB0ND7uggQ0MHudjCarP30eIlOA5G9LQGxdk/jOD1hYdlfXT3McyZPkSY0gfxp92iJzXRao/QPeGJvHB531t93V6LcTh3+yk1ljqpLUUQxJBlHk7+1s4x+l7OmXJDaq2azOxNoMHdjvRZRCKMoj/X3jKNhcrYw6BFCZ72m6gv0aFRziaLWjUOCnqcr6AnFSasAT5hOalM2gK3ochkBNu4tR41vT8z/ChwfAHG6pD4wE3VgegEL1N9rTdyEdUeNr0tigsz/gXDqvMj57dtcfq6TpZhxB42lcoQ4T0MJOBnEnEhjVcWpiBYDfc7H8dnJp03caSqxT6sfpW+yYqa6afdJNLkxC/UGVehwkZJEz58smARNk8B9a9KCMoDuHZscMvfSHUiMK36VlxCaT2wnVKjV+rjyOfZL2vQ3B+74+f+xvsANhFjTYKM3Rq9dB03XX9hj1uH0NsUQIW7Yy7pQxBJf1pCmct6xfjw0Jm/SVHAmZfdIKPPKm+NCBTM9MQl6m1Ax9PiaZJfZTBZGto9Atp09Nc5Aot7tWUWo/QrpigSozSOhtYbElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIfHysGhsTryDl1ItffnmTFKdrgYowoVMUJa8OKHyPGqPz7fD48ucOiuqQtGtxljLK9ScXZsbCR2JgVVgTcruAA==" } ] }, { "header": { "sequence": 6, - "previousBlockHash": "82C5BF601AC70ADAA84ABCC15010382C2793A145B329548A7E5A05B2C0EBFA17", + "previousBlockHash": "3A9CA90FCF52FFBFCD8945FA8CADF65A6BBDC9C4924B0217C289E9472141BF11", "noteCommitment": { "type": "Buffer", - "data": "base64:j7no1NnvTzdApJykALS1cgMJofwNyyL+1BTe+vp64yA=" + "data": "base64:/rqhkaSvjy8hRXEwn7WFLVKjqLpO9yZmVI5bYp9K8ws=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:NzlCkrmHBmSiZeuwziNWJPwZo2YXbN4KAG++fJlxdE0=" + "data": "base64:prepJBjKHNet4xtnyIQ8L0Z4U0E0Q+TpALYemrILCu4=" }, "target": "873190827380823143577845869093025366895436057143163037218399975928398962", "randomness": "0", - "timestamp": 1671470836547, + "timestamp": 1671691611810, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 8, "work": "0" @@ -1090,25 +1090,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAa0g96wWVcrz9QijSXofqVtQccddOKimLDdFU8aan+ZCClSFCvB+KVFEgx9uXzwjRptexi5qhHdrZxbjSsq1y1GsCRmeEjXFfbvfQx8byH2uBqf2+FU2v9cRi0bAkb96aPq4vkZBZVlSeR96xmLi7K4K+H+R7Ok8/BIj0IYTuhQoAunDZSsmTSFF3IGoYmbulqlIYXKQ594gOy6BK0ipbEKLA9eMM3ClQiYlDHZGXNlmGe0VAP1OqL4Nq26ajmlR6Mv1cK7f5FGu5qo9a2p5UgwOpbcRMld8xOgNDQ7BkZIjPeMnGkeV76QuW5L72K+nBecklR51UN0q2z9dykpZwkCqhHfJ0bBMAIGE8wUvg+h117lFyFgnMXw/GPoakP8QShwmhX5iSMQG1tPSL2LdwA6yyZ1Qv7Qzqwi1gu12Jp4yG2ZEYxZP6mTA8uID/nHlwQh3FDVlfTQKhyVarpt+BqZUA3SkIPMXQQWEhG0zoOhRUsGUAaIwP6oBZNNo30b0RwRDzvAiXMNk2zAsczybLqMWHlgvl9mc9MkAJDW15Mm6APILyN7xTW1Tjan60y/gwkRTOEKNTyBBWTMR/7T5+sCn3HN8DeXTU5MEQ4XlpxRts8azaxWkvhUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwENqEqK3dqnLyV8cbloWL4HRdrk7zgTMXHnc9vsTQBUqcYgbwp0gFMQckx62AqNu8WcV2mTru9i0TaJzuZbF5Bw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAlMdkym8QhpNFM10a/KCmj9HxXCXvt9KuNRl1fFwG+Jqw6CrWNjBk9Ky17+1I/9qbtsbx5uBQbeRAT3qxOr+YomU3odDCSMqWzXd5dxwdTbCQYER2ahKiZHFMC8Zl7mWobc+EbCLphXN0WwomSoeR3fHJFRQziRND0CQK681P5g0MUoR63ZnmsSK2Zadv6kO6Zh6qJmgDe5+MR2pxJ4r4J1gFQV4eXjY2tBVounyvjhiY1CsnYIGPpYQah/VlcH/aGuY9u2b9iW8OWarm45wbpGZmidJ0EBFHN/QDNk2PC+rf2SZ1eukA0rtOJBVNeOPa7TYecAvUdycb1hRAPj8n2ajwBPLVq8CvSXrR+cva72Vh5wXXO/MzoEpu5XO+qIRZEV5pcxCXVGpBaa8pRuB9Fm+60ua+MNadPCUckKYJPgZ0ae9BjD/Y9nJPp+HhzFNg1GR4nRlF3Dugtw1NkAtbvB3Ux6WRfprT843J2ybhay+UaDvbQ53aLFC8TFlxp7IlfJa1Bi5VYr6mlbPECts5TUcjKZNQza0lgr/5wJtCIElqrTFNZE7bUArPw0Kg9GIsYClm5eeNC0f5Hw07fneeMRVLjLACfdw45V2IA+z1n0HJC1VxcqSRXklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSsKUi7CKW1TVtf01/3oiooL5o0i9FF3yKcKSLYUnfgEp+K2yPeW1IbGMy3Ct4ySnzZEdzs8Xc5tAw8YZXlf2Ag==" } ] }, { - "id": "7bf5b45c-feb5-4289-afc0-51f9f19e6e09", + "id": "d254534e-fe43-4dbf-b515-ceb38ae5a9e5", "name": "accountA", - "spendingKey": "e468ca264e19bc98abdb99ebcc708437295a391fb8b99204603d4c9fd647b2db", - "incomingViewKey": "6cb0195a61e1b90393c9d33cbc0f52c45c5eeb5c9aebf5d29b2b17769707a203", - "outgoingViewKey": "c04c284b4834abdc289777f949832a2614b275f892bb6ec20a2c8d9d0b4bbc19", - "publicAddress": "185405370b96ba7c1fb61d5a9bf548b8c6111de77a48bf977aab1cfb9fa4580d" + "spendingKey": "ceb00931340ecabbcaa01e014650f5ae2cf6a1855a0a7f76f3129369babaacf9", + "incomingViewKey": "b26d12f51ad6443868c17274075cf9fa50abc74ba05a0668a3053627f865ae00", + "outgoingViewKey": "c6c1baa4c4e8431bb546f3d91cadb8ae48f16f1cbd3eb221f8e9fe429d1e8ebb", + "publicAddress": "7316862e59efd1506a54290a1b2b4c03f9d2c6d6e7104c14b318583600729098" }, { - "id": "7d06f955-33b0-408a-b48b-e695f4b3a868", + "id": "13c494d7-6101-4613-ac84-e11cae21a697", "name": "accountB", - "spendingKey": "74c451ad1d252cf0d25e0b765b9466c9a4cee41cd294066c57b6a74916f43052", - "incomingViewKey": "22edfd5c87cc21bd5efb8bdc718de812986311c11b89ab667fb0af01e33ab405", - "outgoingViewKey": "42652cfbb59ee1a4a7df1c60c588070416a8877ec55528d4d22dad45fd02ffa9", - "publicAddress": "6d8a73875c285980ab22eb510d14c3bd2b4da1b236a1d195433a99a8e2570a62" + "spendingKey": "78d11755e537b121902cfe510f89416a4e6f7560e4fcd9a9ada672cdf5e6e9d7", + "incomingViewKey": "3f5797f56d56c0b8c798ae12b0105b344e363f4ec800be6752fe8c3e52e52504", + "outgoingViewKey": "cfacc5b9b54c20578d1336e64bcae07dd2123a8b388680c2a31176c49d258cfd", + "publicAddress": "9c360e45ed615521320de830ac1bb53e44d0b9e0780cff9098e749a1dc93b0d8" }, { "header": { @@ -1116,15 +1116,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:H/mXEBVcxHCcd655gS//bwFvT68Ni3/jOhpZBuDdkSw=" + "data": "base64:Q0xIRcaiAFkuF/+THwtPrJnRxGxn9u+9EG0lDSvZGEs=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:bsi9T1VrdrhTQ4MIOsAUVejvMGJZn1KRd4PGLPMCMP4=" + "data": "base64:BAX+Rt9wsjVJoM8+rOu4KIDzt2+HZXhwrBf5IpL8Qv8=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470836842, + "timestamp": 1671691612104, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -1132,29 +1132,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA9wc/3SDv/MN1W8xFYbYni9o3ee93jjb0/q51dRInQUGByw7cTDKP72c6owo3aucImL3ioQuQSEpcAo+w5AbN9nbGhdh+amUeh6kutos2iLSCfSl32Cu3laTPJOD3dqWhTl7RsYnY11OBnJrZ/CT0DioX6T/tgwwbDiU9Ni7snSIHXNg5G0AKeGr45U8Plg7pWUhYATB+EE8/qBRplpYydoP0mTNuV0s3ZxegN0jFjXGXhn6PN2C7Uns3PIG5RG5PyAj+1mgzLbJAZ7Z2sEYG/e9VrmnLCdVf60kcQ1j6bUT7bm5snktO0btlGqNvnc2cKlmVySFHFpcpuVIGq4+LBBFhNJVSEggisvOMrRITaVZYPGps0nyQEQWCPEa5qQoDnrmtQ5StGs0RfBTySyvC3LPaVMWsFMUftqZkwqlvCme02oLB7FeqUVKmUTubSLX0y1/WteSWJUGlnm3ZPleyMtMRr/edJdZigfivC4RuDfHYMl8zN6amastOyErb0rPG7uf39pQRvRmWNSH/KlBdCNIbbw1wku6I6WvPJn2vPZTOyWAZ4jTdBpFrdV19lnRSujz6tU73SISpy/h4BruWAk/vqi36nR7EIAx0ljcsb19+LJuwMW0anklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwk5FO55WB0Siy8VNK3ijrLxEfXDWIEAIHk6XUbGU/9tz4d60bxvLaJcZ398nuXMG3de6MAvDVcwZgTOARmWy5DA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAeiCbLxe+8Oj30Jn2F+YHyGexIU/N3J/G6LaxFUgePEugB7/MalF6Dl6Sa/VKEy6129/WhXamXjW215FFFrwXvV3jeJAI3ctqdhCFFJXKidCndr+GqSKF2rZ8nBsNqNdrmPgxShZz5Sf8aw/w1A0MoBX5qhepT/c8jYiGBe6ESF4FpBa/TOpE0fQ3BbEauicBN7aw3SPBWSHwdylnFEgW4vpAuAZVqL2kVz139+zrP6+Zd+no7ap8XJLSXKJECvnWTP/ssMQI69+eiXlAiaYP+hMgz7dt9GYpgtXRXz8Qd9i/CCCix2Vu2sB7jd3yOOHqB+JWp9nbdNQpwRVPIaDnNM8TwfnpqpGpzOn9QgujJBb1OpT0R2Un0I1peKJ1MQoHw/uWrGdkgi2iPMr0MiTu9U+9MRw/yF3n5AXVU7KPTLlZjDolBPX5hb2TIibhKv5ag9zb81pjc+W4Opnvvt7sLezsXCgHsk/FlK2km3XGR49oj5jiIdbBJOmTz0vQV/neG+pyQRHp9V4GjdrqYWmGOn3YldteEYfkkABRibDYMS3CFY58HqUYV42s5aQyUN8Jk+H5ooCuLllcewNhEkRULgAoOrR4MFPrjVxWYn575uP2yJnykwvOPklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwai+KSDO9HC18ZcOjESvvxoMczBlmj5hslXBJtavX4WRGT+RUx8AL8dZYC4ZPxeyR9Sjf2RtGL1cJROrgZDqUCw==" } ] }, { "type": "Buffer", - "data": "base64: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" + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+Thbl5FVCW9w6E8jvffZZglLIFwdq71XJsfHapMmpuqDXloiLgKqEhbkFNoJCs0HszX2SFr9mkoZGKELQD+tA62j9MiLijFHGBjHr22loy+B92/nds7m0c6yPYw4WT2mbovRCxfz25A8hJ94v3IEUo2OoMTeEr1uxbd6C4mMTGcXfAFmPcCcsm6QIK7fzQZhQ7LRhuJkc0ChFOjQ2LETGJO8PKyPAPTQFGt1n6a9vm+33ROXYyYLPLwirAEsSsBHn/XkyjHcaSHlM1mj0JwvCoXIjUq96489eidxSLuDDWOK/xydk7FQOyBZwc8KBrZaiL/prk1RMvYk2hBRx+SRjkNMSEXGogBZLhf/kx8LT6yZ0cRsZ/bvvRBtJQ0r2RhLBAAAAL/e1giyiVRG4qxiSMs+E1rsa+Gho2r2KUyVwujC3DaXsqe9ppEw3d0+G+omweB+HGqC4Vv4QDwNxPWx7bvuAE9KlPByMZ1SMQWP0XKwXUpdi8uExYRSaN+LRUj9i7JyDoCvJwY5gzjAUNK0ouQjlwMIdUFa1TzhLELFQrYSAJNqHW/3GuHJNYLuUP3CX4CGbo6YhnYrLvHB0Q5/kDuJIPIb85v5per+3u234FtZGPYNrv2rvxQdA3bNtV9dIO7BJRkypU3EUX0LgG3T8x7L+3NC8JHS4mcJqxS9cmPqfljqm/NbPeihupsCTpKvjomJAq32hYmZCUryXbbl57getoBFM3Qa9kktRdvVD7jiGLlUhZmuCgD1tpyBSkLw427oqAmvGm/QXzhCGZ/4s3M+wmbp2v9CvHJbJy3lNOT7m7+BrWHj/hPYgR/1zrtTigp1thVF+LpU4hzQqdBFOa/xth0hAPKvl3MBmYZe6TyildlQFYJFjM5VqYVZJnukFOuwLV2Ay98AapiPwe6Tno4yPUDiefQWF2X6V5A4f14sVHqHL5Z88lL+GLi1Oa2WmQh0mOWfAQP79js7EH18Ufx0dtNposaElijs6jmzsGH/YMsM9M6BTPUWdI1T1i0sJhvfx3d/rFFbrvzX4QYG2lINfzp7bBVmimS+xcWdehg4HRkxRlP0OGhdIdl+LOtbKZGMlivBUaF5wiDtbzbDQKYDYs8vXzvOmMY69cdS+j7R7nR9JR1JZ3VFzmOYF4iy1SY8ATWof4lDHAlhJntw04Dtic6ZFVa1w1Is2ozf4X52OoD/Eepc9/8HvdGwnddjDrhdN++IiBdiXHcxKU6dULsy7B8/RVqQN4iS7Pw49ynYTBm8Np2puottmFmphTQn421CruttN+Eq+YBLAT+xm+YvO85ufy3ukR+6Z3CTUeJs7r/6Uxvzt14L98QBP3CDt1MtdRBNsI/cwfZi1IZNIB/2sqfs4bFsAzVRVO9Jlca6Ozmrw3cHXRmCbOywFW9j/JYOT8uB8m2Xd/upGL/dNJwpx1NuSPjQt10ppcPxAl2xeqe3Mn6ZBNYR+uQxvcKipJ2JjVRYI/QpvELjte5g8n2eCwCWuwlOqwsphvPDJxcoDDEv1HQxfC5rddx95rJEbDnYuV/lyDt898pRoZRkfKXzz6o0tRiEBr4KY5Oqs8bipnhUA2VqN3ac81r1Xn7fkcqJucg1vdYpnlNClY7xSQ214Pzl8euatcmCjJLpNztnT8d6muFTi8wMV8Bgpn7TvMkp3OALUgOZf6+IvZkPrQ0uuqHaprgzxJREbqtiIg2By+bgLJ75+puLuZsxbiEVjpnHW1bED6MkGgt6TzAyxeLIBLMdGRB8ew/gaq1nDS0dP0fGaW7Ypnu/6G2YAn6WVv1f0faECR6jTlcwfsxxidIR9bvL6AdHzlnCF/x0fXn8zEkOfFBvFtGGZrEJtkzcmL8pecokiVJkN7Uwi2Du/uenUHvSDQn5XOydm0t/BicgFeKFx71t4qNU3kHr+tK5tnRbaTjcJkRk5u2f7sXxf1cZFdBzScQ0vtDA+UPqHE7dd8iTUkVtVH+hVvzvJdDi9Lc7CQ==" }, { "header": { "sequence": 3, - "previousBlockHash": "ADA372350C642BDDB81957EA23F8468B46961EFCB440C6209C512073CE998513", + "previousBlockHash": "BDF1332A1B877C628FFC5757473583330D92E6C2EFB3E1536B706EFB741D86AA", "noteCommitment": { "type": "Buffer", - "data": "base64:1sPvQxxrYNs2kh6gaFkiGAiokxYFUknpIK4qlj+qKBI=" + "data": "base64:t15D1OcrUDEVYPhb7SHxnQHydotosP4ecdxnuUX/Tko=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:rdXLSdbs3pi9OJ6U97PVr7xsI1oisIIbdN3A7Qc3yCI=" + "data": "base64:9hu6kYL0W9GIvZ66RTF2I9PXgZmKDKEbBqDTdIFhpGs=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470838516, + "timestamp": 1671691613775, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1162,29 +1162,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAefCAebPmHePptiTlpvbeNEJI5s0YyrYgs4X/6jboDuSNlCzkES+txpkEvpAAQIzf66Q/B2RiyOu1svTEmUzjuHevg1dWuttm3p7mG+xql/GvwUgoY4MStzRYh7vLIvB6uylwEk3g/+L0p63hXEhZsVf3w6AvEqzvXE5B7mxS/RMWQb8w7dXEinBXkvqFXr7v1knMNosm+BXIOZGkS27911wEHiT65f6fFDOh9YtwFwyF/8uYcTWr/dNGLJjitfI0BkkjnuoidxD4uP+N4Z69MJsdoG5pdG7v7v8ZkDeuzhZIh1IdqlbydDrCKy0jn/qqgOc1c70R/niA8JfeW4iPqxGXakFvr6oW5dQGJzPeliIOdaH4GKUpaGwA0ClwVTlP+M9i/uzvN4KxoDIbkmwEE88SFyifYMpeZahDkGosTqF/EzdyGGSZ1JPW2KFDvD1x3ThUyqEnTsQfGEfW/vnP0Nw01kdm28TmUbvvuaQQXyEio3F2gRxqxiMA6bSNg9pAYBapqIzCWSAuixnqPGODY4wChlw112KtNHUI9j4t0a6CR6sxqYVMBOED4fG5AP1tbO4qay+r9KY3PdiXKxDR0L4m+ltrS+6PcNgy/gX0DP8WLIcU4LPyDUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwwRyHF//taH3IMTVD8hkRRti4yJ4j2gqfMZQ/OLlTSjfwk0OtojTj8vSebqMzxGwsYrA1hz2CBbO9wXQD3oLEAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA/gsKE2yfDqqIw1oQAw6rvcT7E9K8Udi3FM+HWRDgmjmzxRTJS9pDB8/mD4A03Sach5FLQYBZHONhmrFDf4Cx8x5rUjo+hD1yTR6DsKAn99GBBD/Ub9Wgh9Br6sh8+xoKUGTURh1P0XKINFVVFPDo6ihF4U1UrSWV2DjB+f1mAoIL05NGvNQKzmIn1Yx0dM9KgGDdeQoET16JhyPxubFsgEAlDccHKqNlCc8CySlE6t2ZOAjK2Yt3sYlo552je6JHsfIUNrjhnoBvC/k/RivjDg64YRSz8X7hXvff66oyHWDfDmyAf/9WcKGBfiOaxYKOo+tMBIxtL9/ilzxUecmfkx76A5E5dKwuPMqAWyMB6L23WMa3zMAJqLYzs7TBRfwD1t/IRn1pJl82F1PKsQpjP0gTkvQak/OeSkcKIEKc7YNLwLJK7p2Dlg1u1iT5Y0BwDcWotiLRqkA31NCdj2+u5tRaKeLVtqlxS5RC2Nqs86XvLyyzymFSUlIRDkO9PhtfuM7PR3DY6P+4Vh9uNj9FWpXjJqAv9ocLAjSyCCpXyFwSKDGSHrmBVRg4Ssoh6a408i/OBXUSvIHJmoP16BOdry5tyhlk62T4AvKsHIfMqDYyi1SsRXmn9klyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAweDP1Z16ELsyC6FXN6cAWahjUsp2HajRO3Nqhbvfs6QsBmSSTRPDROnhxJo+HVjOQ8+Iu6OE+zvK5+2Z+PHRwAQ==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "0CCDAB998C3DF25671A429246F886CCFE754896C92C64ECCB9320E56C7DD2AC5", + "previousBlockHash": "A2AFC17EB120A7E4D83A775F4D9C05377EA525E19BC6E7304A273FC7B5AD6C53", "noteCommitment": { "type": "Buffer", - "data": "base64:rMRm+9vJfWygtU84EpEtOEr4G8iwveXPuETpUTFpTw8=" + "data": "base64:RlNUgSS2rWQhfsFZBN27oCj2KVNJM5pb8iGosxuPPQA=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:CBWhhBJLpbHWHdStLna3lWDPb/ZEMuIix23ZuqK9Ptc=" + "data": "base64:32IYB3FdN16bVE8m+3JrLNuIps2Trztzruz0rwG+cTg=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470838826, + "timestamp": 1671691614100, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 10, "work": "0" @@ -1192,29 +1192,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA0vCy3ZAXJTGj33AwIplfNUK+qW112eT+KCba70DFrjasv5y1vq1afIIJqGt5IsYJg83s8Hi4J1e2Cwko0und6WCaoZ8aDBLR1XVHBlwy8C6MrXX77mraaoT4CA5wng+GU7DPxWq+ftz5dhvMgIx6fBN+k0ANQ8VDuAggJmm6jIcIJuA9NdG2FqaWVxEaFJWK4iLep+XGGEbsZt3pAz9SrC05K1S0yFZBCUvG1EJPChi0mYm9AGu9SPGzpS5mvEIFVVhWvWYwp4bK3lSuLYlLZTHeSUXhhM7WAQFsvNXGSBSjf4hBo6ymSKMP8YBGdhyEBx4Q4VUaWj92OoypULUMSOpEguZVnXkb3oiqCQTcaVzXRshtkbnYd7oscUbDGjUhCIjPPPQKJZXOrbaY8Bv+Kw5tz4aDx/Qh5mNW12PV0dVWtfRSm8iZdPLaoqUGo0Tf51Urj8JVjjlv0XzhgKUP5Gr3f87zrB3ha/MTNbMNRnV6k/IsKZI3jWI2murxi5a/bk5OBCUFy3lyz8rfgx13+HRbEl8fQTv8l+CyLJXfZxxC9eTEqo+nyymAqDkAhTl9GhCTpu62o29asnIY29jcWvwZLKiY9G2b+R/d9SyozkeIX7ZNje6rIUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwm/qlcMmWRdC1MI39JL/2C8sTxecA2peSST2+Hm8MSGgRS4PNpEY0tbfmO8nbK6cLpFSH1Cgq2PNE314YZjPHAw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAGGPn/MIwCuBKYJeJNt4D9XEvpuB/OtdIOy+nMaF2gGeNDUgHi1RKsCswyYbCDxIF0FHxtNJtSfrgSewn10e+fmBojVFuDE3SaiLX2j0dbo2UXVMwUK8t1Sq3Q5ElMOOfhzrj9Ln6NUt2WsstrJTiqDb7Yz6i6DSFGrWRJzBUdm4JK0zeyvyAnWZ+DxM1rsKaB+0elDYtrs1clUlYsu4No/0Tz6zVjIz6yYEhVvzQDamyWnJljS7q6sXvwRmbBmeDGFAFYX9kiv6fx4ppb2dHXrA9XGFyU1U+eUrC566kB6Y0xFxQMgTK41lE+M7gqZITd1Z3usqvLbfFf7dgEZTZK2QmjX97WDcImLMm2ie+BadZPbeYDbuUZTWcaa6ocfIqmhs0BGk8drknc4G4tSRr3Qhg/6nBtxSHXMdZx50j+GX2vKzNA4vaSfGaYKFjfG1LJGchJJFBE7rXwsy8WclerNbrHFig3f9IttnZU+1h5bsVq/Kolkvb3sUXyK5uRV58EEYGqK103VKfkOfIQj15qQnrwy7DB7C8OmA7khXw5aV8hLWFt55JI/kNzsE34a71zYLUBnD6kSJ5JNnwZHp8ZyKS/76at95hsH2IAQUrE9/jjsRpJJiOGElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwhJsAtxqlDUvPXmcPlAIuqhOftFaF8e48pqCuHm4/LeTxuC/kxrMHD3kec5kH3Gh3rdJpoUJWz+K8CaDfiHOZCA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 5, - "previousBlockHash": "66DB995E6E36140C42B8D2179B736AC0370037477584354E6A5042C27E15E145", + "previousBlockHash": "30DA2CFB81F8EDC707A6ADA9ADBACD15D823A7466F10A29A700AC591C5BED5E3", "noteCommitment": { "type": "Buffer", - "data": "base64:Ta+A5Q6iCvNEc801KLRcwzC0/PUEM6wk1aSUz50fuzc=" + "data": "base64:zt3ZA6rU087MaX3X+jyDnfeqsv+lsBsG/GVamaqC6yg=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:0HUpwz89OyxjgA2DNG/XS8MRjkhSu/7az1r+D4fXpig=" + "data": "base64:U9Dg0jSBegXAc9AC1t6W5shLAzu3U6UnW59NLRU13QY=" }, "target": "875726715553274711274586950997458160797358911132930209640137826778142618", "randomness": "0", - "timestamp": 1671470839138, + "timestamp": 1671691614425, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 11, "work": "0" @@ -1222,25 +1222,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAQc3r/NZLSoe56vUMTgegPogHvz8Rxqa/960zKasIv2Gn+/q2Suts5lebEIzwo1GwJ6lzh9mXhIKRuQhuvM4+jXDWRRfVVrG8SXl+owp0IxqItTV8jTwQxR7tIldhNrtVuK4LnDCCn6UGiFgJSNl7GDpQiHUicbWd5fis64pyczoQNJSfX/xp2NBwLLjkNQlFTQt9XE/ESn3EniXop+xztlsWH8n4c0eJF7A6qi45aMy3MVlWsEvXa4hwLTz37BNg9wo6aufY7fAZbrttfjJOsnrUqqVMfoQlU849sPaabpgy0Mcb2KZBEDemamwAJ5n8HwHqosq56v3qjKExUrTenhb9O59KENSO9KbctHyCm4JDCfinotv81N0okPF/u8AqFXMTxTNVgZGXO63iNfHWQv1vkwaK0LpNku7JzCKB88wFXo0kLrLjKbxsMh0vMuccW1DuL4foqJoRw3eWuevWu6hMVf6rY+y4UhqUV6mM5AydrdWfn4oZ0Ykp4xzcFG/RByFVj+z2pgm6rKjIuwVb9DipKrdOcwL7VT00i4qLx6u8aNJcfLhG/ZAhtMAtxr//qY3Lr69PMEHfEZT+BUMjTfI82bX0bFvdfWQ060dKRDuqComMfx4fkElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwWVkzIL/4i0QnU5JTE6Jct6rMVQoAMA1y2NrJlntMkCI1IlFvQhJkw0aIoIAANf7ZSKaacD5tjAc3kCdRpiVBCA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAANoXX9yavEBy8zt4WsRbZBK0NNogU+G14rcEgUEi8qcu2kaDSt+fjzOYM0L3frJa7KJXl4K67+MBXYz+HTP03otDPOYrZ6PeRh+E79NXH+oyM72zSFxul38tEVx9EGctFCNkaL4DuU6RSvYSwpTPdNb+YwHH4V+uzfAhrJ3puU8wJ2hvmRvwdChiCZndpDE7sn7/aou6g6p9pwMAu5dqhsRxYNQEVqexn8xAgPrXpqyShQnz5ZIJ9wwR+m/3eo9VrVcaysmUU6RgzEtX+8nYptEc4QhfWiFDLZQPKb59VIW4ALKL25X2hVfqc1gSySGzUo0jKziXkFL60la9q/qo2cftJoGoDqYozdu7yL6TAuHn+DnNv+maMoP4pVkqjzJhDkUv5ucpP0mOsW+FThrPpwGuS/mFBX4Vxt2eBXm7STPM7njS2QCYZIeJLbd4r44YKZx8/lUfwMAS1Vyf7htW16bJ9FWgUQB7461D9kmnbvO4YHo/5JGD/p7w9zRsalNkCQNmSZ39FYfb2tpaqflKcUJYYb9W/Rudjuf10mwTj2+Dnt7pS7766DSbxQ24H5heJAFo3s56YmYfyCF1/Xa16ampaSJXreb6HgKVaMKyCm6LwmhRHs4oTqklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwdheeE9wIs3FGDAlCXYDhoKAJdCkP8f5F+qha3UMGDWlBid52lYRR6vdTToMeikB279PGU60sZ4eodgZhh+wUDA==" } ] }, { "header": { "sequence": 6, - "previousBlockHash": "F0FF8509F345B95141DCC466C4BB065A26A1E581E1E5CB320D50B86A2134AAE0", + "previousBlockHash": "0CFBDD4F5926EB2D0480490B55DF582E28EB04BE7BCEC7DF0F7112EDEBD8C909", "noteCommitment": { "type": "Buffer", - "data": "base64:N6pXHFpAFz+w+SG69A+jlH1fN1q5oCpT6ebIqOIALTc=" + "data": "base64:cis/b13Mrjhucd3O9eu4G0DiVZAFKH2bsjT/EeMXABo=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:qhWSY7a0XkQlYGHEbEkluyyOSiQRL6k/bZvQGz1jyMU=" + "data": "base64:lW2DppYH5wTIYd9TJ0nAAlQwTWq5fE1eDbYefBwsZ/8=" }, "target": "873190827380823143577845869093025366895436057143163037218399975928398962", "randomness": "0", - "timestamp": 1671470839449, + "timestamp": 1671691614732, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 12, "work": "0" @@ -1248,19 +1248,23 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA4wXjnjc9PG9BsgNAjvLekiDu02AdCBfF6ilAQX+6LxGi2CDedVe+pFyOJ1WNmtksyul89wzuweCk/CTspWh1R12d6lSL9Xz7CH4BR8vLD5umxeU/d7dADbdElrz6qZPtAeeMcm75dB9DlxQcirTl91nRFRFLp3mx27yXj6LtzLUL9nc1XiS7Tgty5hWXQqc/pDJkXkSV5TtV7VH0bM6nWDhgSbF+hkI43lsDZXQfIDWhOOIjW/mzwFwtts66Ne/nBhZi3XDnOjhBTdieFomFS6wjjya+Xdc3roHMs+KKTliu+w2l1AgUlcP+pxcPX4TXhZAKIncxqACj2A8EU8J9Pv9aNP1iJB+pWKi1bwcePp8UO4rT+O8a6ac9dKYEPXhMVVlxXxyMggCZOSSOAivBfS8Ox2zBxBwCBR6hqVgqOVnaVxyIaxsPvzDazvLh5fcox6P0ULkh+x5ZRDdNyk0zH7CqTvHAF18k7D11MjccqjPsH8s0KhiLmv+0Ot0NAV2GiA1yjjj3/A4RtFSQyTuypLXUFSb8gV4GUAjac4vGux5+dlYJ/hQNUDIoKe44hQfc2QD7RvOUvFy6058jvgq3N+tXtrHn9MjKxCBlOihwfZtKZLCRCLf4sElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNsMmRJapRJEwjNdDfDH2Ber4ZsrFZ3fnEvEYny1/LwuZSltMZFt5mjgUN/SpuTgng9xi1FdX9hiGUwz7JrCpDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAASHsK+wsdnS8YHejTpb3Y0xqc8+JLUofLHFrbHQFQRy2Al5CEF9He4qQF2frleJqqXygcwVJMkcrp99BBIwRRkatZTlO5EHdFUwZaVEaeDDWgU5oiP74JV5RVMujVI5Rr6+cdNXFdq2QvxBTyoT0brzE4YB/0ZMU5DPA5PrlovGIBNtemaDbqVBMSP+y9jP7TaC4L9Mr6IPJHULwWQsAqv5mP8vXX7H6wvnAmv5GdVNGqgJY+2yuhzQxeoVAVIfUEClFpdi3QqlvQwtQMX3mScKVOJw7I9CYdV569Tf2nOGGIpgIazwV9RzCSZLJCbvJ1U4d8W8DJEsEH2QGNFuRf1zoGx4QXDY29q+VmCly0Aab4aZuppgYCPk/pMWkf6PIk/p2+E6sisbk+Ruj/qEeDkcL/5qaz+9PApVAJGQ/iLTPPK/uIagP2vPz4V9hiPV6cC3Og26wvySNwAN+HOrUEsZl40qUtg+YwVpDfoq4JP8ZIstBd28194c4pDYNTAxB+GBUpg7RlJNrU0GzGkUZMs5Gvu5FxdRYejEVlVuGqPD6vDD1wbpt09iohZuLjXP43E7x0/xUAHyL1xX4zA67z7dXDBIl60/x8DwaiK4ymR8ei7U9gfo4w/0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYi4SHyA2AKZxmk6cCHJGryBc07lksgtKCR6wwWrQJzSWBMmusUvJqknIB7dYMTG4WBeir0MDwYm6EPlTXnKvAA==" } ] } ], "Blockchain asset updates with a mint description upserts an asset to the database": [ { - "id": "e8c36789-f005-471d-bf62-10d772cb3a54", + "id": "9200bfbb-e153-4c72-b8b8-48470d4c18fd", "name": "test", - "spendingKey": "41525ba37ba70f2bd471709af764048fc74bf26975f085e2e43c76267a2b5912", - "incomingViewKey": "803c7bc0df61bc109480492a244aa02b9007abbdb02f93fd583ae89f061aa400", - "outgoingViewKey": "77954a8f5378cd1e697022799e9a64af3ad9333f73884befc3171e0fcb3fef47", - "publicAddress": "47f0751f7d80174830da60597dac7b7a48d72a2701886a2742ce1f5fcdd34dee" + "spendingKey": "cbe773853386a1b5d98656f1a139a49683553da56e2a42d977eef14251ccedc2", + "incomingViewKey": "00b7a89f587a545f08c201a390e5e169311ad075c33f7199f2acfb4bd699b605", + "outgoingViewKey": "136d24812b98ad9c1e05b6c4440144ed578937c037c37d57801aba55bcca424f", + "publicAddress": "f3fd1c77f55b1af24ecc9151fc639b4d82a1fb90cffbe8a9dbce1e33ccd7df6c" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu6P3g0PnroaT3pNxlKP0QvVyMZ3xuKa7iJ5z3j6sUfOsPf4LTm4h/MWNUKEHpmZBClU5aOBGvGFgPEMx2b1yZMznXlm2GZfSyj/SwNP9c1iXgmp3TxX4UFmh8xyB7qwH4Rzeo6X/hivYQT480d3W/o7LDUiS6uu6GhR80MJnUJoPsRCy3nNJtTfc6Yszf72OAe0wX8E2h4/D3cvpEuoemV88nx9UMXeAWCH4ERU0M/Kz/zG2jfILpu9GyvTtb4wzTaE6xROszwbUcHSJT8GOFCw1QQ2Fng5pxfofW385Tf+tniD7eo3CItrgY0VbuTz4/kZYHUYUFUteI/F32CxRX4J7HQAILK43zTcKyZv4cELax/PKVCZMR+Ql283Wke8TLSJF/y43+ocW7ObODJR/ikqr5pbKtVm81/bUACVRXe1AWwMwkeeXDnS1tGnbKNz1/PUDgqn2SJKkfj9y4502NN1MpJBW8IYOVyPEhZxcsCFaz13TVenH0iXrUiYLipOzDqtYyenDMqfZW6y1PNs0T5cK16bJIN0jGTKeWTy0nMVKA/37HJU1P6l2qPOoNw4QDlfuiZr17AxbzqwziQLW6H9IZFavjBPkQj5OdJfeE1L78mGO9nTuo78zYaF0eBaAkWQIW61Jput1N2rGzVQSIbGcE6jpdRv8/qZF64PJwl8nq3AmBG6pHgmXkLzdja8ZVOaQ5UmjRH6sFjxKvRRlz50aYXvJwVokpS5eQRkPbJyDUrPMd/dYlnmFo0PS0EIyiY55rnsm7GviKSLAiKXQzufD1AVigNoSjiLOrF2mwoChJH2K/Q1iXhvenmB1B+akSSv5Ef0wnab/J+rDE6Pa0H0HAladFVGYBXV2Zca2aa4ZoQjIiLjmsYR906zFFwvowtPaVpyglbD0jQH2E0ultS6AclNxNlxfj9uKd30Hm39aicEvd0B7UQeHG3pEhbccloju7vwg8ucXQZmBsRWN50mjoG/mSgaM8/0cd/VbGvJOzJFR/GObTYKh+5DP++ip284eM8zX32xtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAAcrh+DdlCQWKknfZrmQqFLlrQ5+kSvGtUdMz5PgFQxJ3c3HWBGeQZS9K7CiVsUSStwFs8LNE6G5GmktRy2w9FGSOX1zHUZ6mG+1hZZIZooc9pmEN7xjgj9k/+G3uYR7AOi6WrgNjx+RvsbA8qlvGkEU61IDZSw//bg8+T+Vrp/j0N1NCCD7mqt9gx1PqFkzfGqWJyyoayWD89yB14gCr8J" }, { "header": { @@ -1268,15 +1272,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:xcPuQ5zTLzKQDsxewRfZJQCgvmF93TBn9pkFUphXcF8=" + "data": "base64:mu1ipDH8ntiWm5YKiFgLZB4lJjmMgi44ZgliVvFnkg4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:W1KyHnrIx/Yd5MALALqFPHzhaHMtVmAVZjYhEGHe3b0=" + "data": "base64:o18Qw9NJFX/UsBVk6RVc/epcLkPt/+zgncTKesygV+4=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470840435, + "timestamp": 1671691615740, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1284,23 +1288,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA4nSN5JpRgN4aViARA4HttYTnzFRAjOSMx7NAC49yPYyY5D5PDXeddUdycv2kfTTZ7vXTfxYJf+tjE6ipZhtx+OIdutdWj0T+vRCJDb3AIi+m0wHEvgilHbLKJ43o2Qv98GvqAyvp3FxjVIwO5IBbgkGofw+KxW3crEuEi+JfLdoSv6zLb8kFRqYs4wQwVNCWjkMfJOozmky5Kiazc2/EyJSHGFvhZqLlKFEECpfDTOejYSsSFRcBjgIDH9QF1cBjGZDbv9+66zYFLSAS4jCwG6wOldq81ElWDXqYRx0PHonw6aDaO/kNeGKjAO8HziEnPwi1c9+ivi37aKu5CZdiN6Rdp2SAwKUmfVevzwMO0LaZ/lf4DZ9OX6nDcwvlBYtfVlPR2l5xI8XqPQxUzuDr4b0T9R8yjFQNRER6gJumpKLWSSGXsDIZa6INJw/3znorzrqJSo7kuqyESHPyyOESob4TCtLugiGsDYzL2QecN1s0tqc7nIDr1bEm93nkJyVuSqPxeaeLWx2m7QcxlejWkDfAHx0l5Ol3ygXuq5a+e9bHUvOBVc//bqSNzZGRlYT344nnNOB1A4nIBZoYkwGmc4/u8UODU2a88y7Ll436sIMetQ0udUekdElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwQMghhLhQQ/Iz1N3hGx5/qeulpXVIUzza5w6UeMobk8SlzrMqUBJAfxhZTIL5XXLJlaVUMc0FLBSfUE/g68YDAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAn+3ny6TdTk4B2UW5vzXk+mp2l2kWcPNMR4vfRBwSrKincJCWglPaQln26ORWJSLRoVKZ3+Eg5AEFiKZjZA1w196xEvJM1uIag9YY+K4xYJqMoSmFbdD6Tge98W38f/duhEJ2n8ijHdux4ibswX6wILMfuESHe3at2WsWtwp9w0APLKt1/jroKWHh/KVpB/ZRF3BCzYsn07EUZU9wJjoE0LfsYUwAPTDWvJALjNJH+IGDaMuQRmexFZTpz3VKapKHr3matEDYnxJyt+lj1FQY9+IK5BUSLAFN8NF/wZCeKr5pFOUHXKAh2lRyWE1rdN8u+AlxAXjrUjKA9W894YULqoA9h36xP0ClIcT0SjOnB5dlW5RB2+BN/nHLzhoLEVtFUYpC8M31PojnjhMhwA47tpRmVI/kg5x4y37S/X6k68PI9e2wuJrk8tBXQ08sUxIvRiEe0nvgVBYUMgTiY9SfBElXlR6MDy9D/O5CKhMF/L/gio91OoDjH1JFM0BpY7pPM7ZTnKhFRH+rR0qfYEOh3jT8IqJ1zpOGVpYbVgx1oDFsNTjVFwdExcKmX9d2iV/CQ2Mwah1Zzwwpj0AtFBRAo84wD2rnd39nW9rt0gJa9DVZ6Su0RNqWdUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwe/l94r5ujwVkvyngikX+PxCOeV/kmPcTjXl/oHNXVii7kKQYXTLkFoIrrrot915lFhiYmL6+frwLPygKgk7WCg==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkLpGIIFAUYp6JhU0fIbwqm7jCsAbsvGEgLsFGeJY6COtge5PtqghkHkjODdiarhAAw6hkpCaDGqJH+z3ZgVueGG/Q+ZOUuJ6qjQnEkcVsC3bS1PdTqjNEQyLrA4c9upiTdUYwixJgxbJta7+QzUg/Z1T5TgCeCsiiNXybKinL0SXYnIutZemUo89GhHJwo9mYXJtjbZXNswUZdQMPC1HkIZQliZCauebIqKjkivrQ2MrphJ40AQpxU4uW7SmziBCzKfU2Wl7e8I37bPWjLiJiC2ljYjs24m6kjkGEhjtp451Zy8k+lnxUwMU5JYEFj1wyJf9EWLinPXbV8uCWYIaPHqv19qdd8v+zCVwt/drMowyvFgg8iEjoStsV7GmxhidxwOTYDItGP1nLIi0+WDsU65DGQb5ZfjTxIXxdPwLdhxcfzXIwA79sGrOy2vjRzBMyJBm4PN5t4+lvVBhoMzHEWTqOSoBjxgmhiAjbuxDxv5uiMlxP1qFDpab1mORzYgy9Ep0YwEc6QWV0f90OPnrIlTsgbFz3nhMgx8flfcTjMCOtwGjgzY2StWdUjTJFesVvZuoIqeV/zybCKlyYR3NeMhNQqq7jT0GkapR+6cYL4ImBRAbzYcwiaHFTi0DrDsNXVeU040dqbPc3n2kpu/9jyB/p31xjc/1d9pKVzg8CpEy1byDNcQXwd3E5hyuwKpia4rXsO6jvm/A1YrZGpb3dwGwl1/PqjIrtQ453Cwu1s70K9KO66l2IOUmzioc2+NLlMF4VrCiqSlX/d2I57fgct1SQDhQT6xgYlW40kpaD5qfYPbiOr54Pc3W42vRJ8WhZJ7lLuSsFQoRWrw8NTpUxYmCN8pZEvzDLlivIAMgLnbe/06RQchOWcIyGzt7jpacKmxbe/3vY3+FCuPBKp6xV/ytqtvmDVni4k55yCxePDb+1VenNbKAcN64AhRzYM0rb1nUMTCHGONJUfD87rjMtnl1u+X/r+/R/B1H32AF0gw2mBZfax7ekjXKicBiGonQs4fX83TTe5taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAACM1opNVZd3XnKmmtcKYatYnNqFV5z3Ct4Lv2/9wLE3KksXQhttHPuDMkthROrFc6ywW8kLPmw36sjw4g5wcOEL6hv/5b68jpT5rtNRttIhpGPKUUO8Jjyt8RAd6rluTAzNr6gWIJ0oF8PskU7pQW+AhMlxTfg7WwOJABMg2sT46YjvYmo+4zGYKg2PZWmlZlXYuizhMtQATt6WIqZCQAoK" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu6P3g0PnroaT3pNxlKP0QvVyMZ3xuKa7iJ5z3j6sUfOsPf4LTm4h/MWNUKEHpmZBClU5aOBGvGFgPEMx2b1yZMznXlm2GZfSyj/SwNP9c1iXgmp3TxX4UFmh8xyB7qwH4Rzeo6X/hivYQT480d3W/o7LDUiS6uu6GhR80MJnUJoPsRCy3nNJtTfc6Yszf72OAe0wX8E2h4/D3cvpEuoemV88nx9UMXeAWCH4ERU0M/Kz/zG2jfILpu9GyvTtb4wzTaE6xROszwbUcHSJT8GOFCw1QQ2Fng5pxfofW385Tf+tniD7eo3CItrgY0VbuTz4/kZYHUYUFUteI/F32CxRX4J7HQAILK43zTcKyZv4cELax/PKVCZMR+Ql283Wke8TLSJF/y43+ocW7ObODJR/ikqr5pbKtVm81/bUACVRXe1AWwMwkeeXDnS1tGnbKNz1/PUDgqn2SJKkfj9y4502NN1MpJBW8IYOVyPEhZxcsCFaz13TVenH0iXrUiYLipOzDqtYyenDMqfZW6y1PNs0T5cK16bJIN0jGTKeWTy0nMVKA/37HJU1P6l2qPOoNw4QDlfuiZr17AxbzqwziQLW6H9IZFavjBPkQj5OdJfeE1L78mGO9nTuo78zYaF0eBaAkWQIW61Jput1N2rGzVQSIbGcE6jpdRv8/qZF64PJwl8nq3AmBG6pHgmXkLzdja8ZVOaQ5UmjRH6sFjxKvRRlz50aYXvJwVokpS5eQRkPbJyDUrPMd/dYlnmFo0PS0EIyiY55rnsm7GviKSLAiKXQzufD1AVigNoSjiLOrF2mwoChJH2K/Q1iXhvenmB1B+akSSv5Ef0wnab/J+rDE6Pa0H0HAladFVGYBXV2Zca2aa4ZoQjIiLjmsYR906zFFwvowtPaVpyglbD0jQH2E0ultS6AclNxNlxfj9uKd30Hm39aicEvd0B7UQeHG3pEhbccloju7vwg8ucXQZmBsRWN50mjoG/mSgaM8/0cd/VbGvJOzJFR/GObTYKh+5DP++ip284eM8zX32xtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAAcrh+DdlCQWKknfZrmQqFLlrQ5+kSvGtUdMz5PgFQxJ3c3HWBGeQZS9K7CiVsUSStwFs8LNE6G5GmktRy2w9FGSOX1zHUZ6mG+1hZZIZooc9pmEN7xjgj9k/+G3uYR7AOi6WrgNjx+RvsbA8qlvGkEU61IDZSw//bg8+T+Vrp/j0N1NCCD7mqt9gx1PqFkzfGqWJyyoayWD89yB14gCr8J" } ] } ], "Blockchain asset updates with a burn description decrements the asset supply from the database": [ { - "id": "5a982c38-969c-4b44-9e5d-ca706b976724", + "id": "598071b2-77b3-4ebf-9449-c604006b5ac2", "name": "test", - "spendingKey": "8f361e40ab17fae522f2082827a40083d97eb702b3787cc49bfa37bf563b54b5", - "incomingViewKey": "7065c65aced3e46a6810c71a645661b69d7a83f03027a506e855b427dbbc7403", - "outgoingViewKey": "6aa8fae9e824c4dd9dc2d40fa15ec564600920803fda945bd1671084b878cb3d", - "publicAddress": "1c8932d82231b1e2f5b85c975dd6ce51b5f654b26a46dc0705bd92cd4a9c03d1" + "spendingKey": "9e16ae7260d792f833ae31f01935105e22f610865818f600b3849883790d0058", + "incomingViewKey": "3d3483fa72e9c573aa119dc86a4d0a908e3575a58509ba895d7917fd27a9dc06", + "outgoingViewKey": "707bbd1d0a1a28604cb6f28a23255250c04b4a7a9fc98432725846bce7ac35d4", + "publicAddress": "8e224cd40cb3099d3b168470e9ed4f8b6147bac5bf17c2ed5cd0dd6a4a976a97" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6khunK9u5a4qvO1TDp6Y0kqUSY7P+V/ZpCug1HItFwmCQpTXok2h1FVmJDHjXloJflLaclXqVlXLhnGzU0uvA2+NGrWbh085kXD0692Nb9upzEgVaDac3yQSt81Osh4K83Lc1MD/v0fH3fDdMmWmreAafbBhuEkntEq1inYYV8oFPfALKecy46laoyAGwTnFtCA+IUZc4LCA8FTxGBKd4AT6fVk3I/i7KJsn1r7HQbGthUKa6BK6NSurtlRlxA8HedTHm+xm54YQFvZOS9nqXgt6YpWbRxrP6bbYKNUoyE4bfCW2KdhGMcVc2n+BTndpx4ECKGgwiCt07JLkd+9/6t4Np0BN3o/1peYLdRWm7hc7nWtYgAIyaE04ZmGyF0YDEVtl2vL6S7WK4L0TEyXPZeebNy4+HiV0bWIooHXUggr4oHz6aMu3THNbVyIBozSc9GbZidGbPeuKRRBDLTYKZknsdqDO4ZVlYOyVl6ZatomLhxZc5kyTbmuw3GCqEokErsrQzMCx/qMCDvFjLw3+qT9UdDmnRkA1gM6nCy3u8OQuGSKksCG7I9GzAJXKKpxjYldJxSgVegGBB1JCPQhdZRnxwqVSGjOZyOGQjafAbrCfSyoQisVmbDdErrB4Rd5NJeNhcoBzxYZMQ384KB9NyqORKVenhNDgrQtgDjtrm6rP5LkgOfmLOTI/bfLzLIbxJi0LzTZaNJdC6ykFX6rNSJta9Tv7onYMor963bJq/S72GJKfxGu8YWSyBWmQ7u74veUrAY4qPK1rczqIIpytA53U1A++gwuphTPEFIUt6kGOIko56syZrQVKx6IkZ4ZbaGlkIod/LOCzn6ekhD2aYbxARWvq8frJFn3kGRcwxrGRPdHOLBtEgGp2xYhBtPVHJWZmEq5FJcbW5c5h6glaV1NtMWpitSMXtkfPndN64Ue+KJFC8/JfvvWbVzPfOBgV5d8OTXjOTwMM9T/VkudkVZOwi16a1mY6jiJM1AyzCZ07FoRw6e1Pi2FHusW/F8LtXNDdakqXapdtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAA3HLVo2Gv1WvFEKuRfHYDP+tdARCNq2xE5Zm6dBOAAHPgAIL8IfUpQuvXSsei6f7ymaQUXXnjzj3WacJeB5mUIa2I35N7nGe4E3k9Q3UPki34a1umv9JYIK9d1i+UvVwmjciZNt2bD3mWb1dRkZcw3mU/Squ0VhfMmmxVpwjapoO/hvopIjpvEyIRGi8tT1BvGN15o13ULinsAWFPFYrsA" }, { "header": { @@ -1308,15 +1316,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:xuxdHGwUdAw5Dcxj6bT+7DyRmSf3ZLb22Ft3EV87+0U=" + "data": "base64:1HYKDPNvpINYTpzTm8rjPSQNpi7NZhormAqsCPBNoB4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:H/brBI9kODdB2bEGs0Meu6E9HLnNB3pDRjM3alCdIU8=" + "data": "base64:Veer7zs/6Kd8INDnfOLExX19AVhh49c5auDkj27eYlc=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470841345, + "timestamp": 1671691616655, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1324,29 +1332,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAor5zeeI/e5/cSg21HGj+sA2gEb0YstcrOMKAsSpB7m+iPY7x/aDlLwMXE1fobSHHTmmab2MY03RaxOpHGQCUyNMCObyfOb8tiCwdbVssvL+BdG/WGY5dFXkjS/ZhwYwx8yorqjpPjWiru4g3voryzKJCnlFsQ+bXqE6R+xGN71QCIepPmPD0/imjp5es4SqBd4mHL8jwRP9BEKzGmu8qEsYgXA436a53utFxAG46Uquq5cyRJcL4ZMt/XIHB+jRjUsSeg3FqsBF8OYl26gFk8vgyn4jGVVtL0hjbe8LNYY/tlwSuxAuSsuHiiWdC3MaWSipCHsTDVZz26EZeySHEJwels0KQvPt9lmLfV2JLCFP9t/W0gzFFTTs9o81ZM5wLNn3pSOdtASPJ0eqapKZRTlhieWLx25WutadRhjAB+sk/BtfTTalDSZAm2+j7EbE+S9FbK9mD0KbAFIVDZv1S1CqSvJy4DPYY3j6sZSDhuRh4QheQ4Lvg+eByYDae9Hnc+SwTnQgmgVIpqkMSlpJEE3JnDA9oC7D13itnM2ArRDfJyrsPsRnzUofhcVi1CaSaVASWqPXOIN2ORnRyhTX9jib1k+xZTNiSl8whtF6i6hvQdsizW/wUAUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwj+gItr/P+42E6NANxX7G4Tyhos63SCHaauBIvFKuiXKVeEJommc2SkUal13a5s+Ch2vd5TnAaNigZ6wSAH9qAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAsUtQsvGpBOwx5pNJ6jkMR6xnmQ+qTyfh/+OqCeo5OEuTDy88i8NlTA8bXtplfho+jwglwfrEUL15hGtNQulrjQXGdtVskQU3jomOgy2dEpCXpvOHjRCuuLDdk78oIXYAZVJVi1q3UdG5sG3FLh/ploBN7egjVRZ9rLYqOHawdloGc5rvC6LGP3mHiIP2BTIUZfc/MCmVzelTGnFPr+pUvxiP/MLwShiPLhsqEXdE15Gr9euKxoYDIQPa7vR4KKZxyvQqqY6Qr8I3iVWYl6drxo5Dqgqg8rVNrQCh2W533ppZ4nux4uOeSvzCEpEYdszydzrQyWBu3/2eZcYC3mSejihqVvLIN/Ro167RgtwknjqFJVGTTtI1gdhVdEvadoYMlZR3JDRXkQmy54ylLtz2ZocZ4lP6KCCJ7T8vd4lg3Au3l0Wa9m6PCk8EGs8+a/a8tMkZ2yW3pZHARVevpuzP7+OW+FnxUz8wgfu0Bj9eu/429AtJe8LKSryC+J4/uIsjr92g3yXxVCMmarGqi/m5m3AkUkgKg42O4WcM+/VsewjKNkxNNKQGGjJzhx6EN++wt2XtfMpUdYlVOdY/2YVcWAW5HHa6operKJ9gDbcFdCQ665+ZgZ0Xgklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwimiPPVqJng1FZdw5bNbvXZzd0gxr2oaJTGR92YFbWm7wCDkZ4dowX2XFqF8MFSt1RFgdbueciate74AMdp6hBw==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzyxH+s2wNh16jOqAe8U8ZxfbYUmg93Jke8etCZMCSFetGZaKlCNkiKaO/4RYWSUrJiS3td2XoaF/+rfcKfNSL3jaQGPKT3KJnybyxAcA2q+Ky+eGmp679vfB4sybPSQDsDEO4uKZpApXYI02l7DjbyOXnVEa+yXyBRXMdiwKbrwYn3FjmS9zZnNbWapsq6dXyghD1KkpsIMWxaA5s73R8S4A4UoelUdv7GOKR68wJIKZ/d/uaY/cattMYv5cbjAnOPtZug/Bhb2lTCwfdoXuxFqyg1vEitmmIBl6iHaTYg+OBMdcSE7C9b1ofP/OLBv0fCpE2avz0NdY4zf41kLRasd9g+bI4tzkH44aROjtbE+SJ2DgayiLLq6ywHsxAk83cnWxkig4N7UZ9js5gA5mOh8frOhYDsWAjJwn517FeY+QyuUVRhVHGMc8D5UPlfWQ39pE9uT0mtnoFKvZqFT6PxZJLP9gWi8tSUyVf7rQu/2j1w0N/ANp3L+BKKr5v+fK+ET317Bae1m1QjmbxKN4dGRjl4t9hp5BfuF06vAhZKSeziBmnh6vwmH6S/CCX/e+cNXaVkeQcN7+4DP/C82JSgd5Ka6MDWLRYlVxT7gIY75GruHDFD7mOqA/tPPwmABQMfhc1MxPwJsU8P0SgmGpPs7hjeYghl9VhrJDwQV3FQZb5CupAM9iwpimFkgMuLRKYj194c3H8m6lHAPsy3MYBsCWFXj7uNG/lQafKkW/jcR6IlsU7co7cdQ/CzevMz0c5GsPQNz0ZDOrvJKa4v8z5sRSi4V3y4QipWGPoklk7gDhdKqVryZWcHCXMLoc0sbhJt9zgfAHBwLextM3vPgydX2zTsZCsfJIA2XP4oPoozScg26LuIOeGeKG+PCZ6BVJif3UsaegIqqKF/NFzOfvkNWwFNRuczF6jPtr3Jh3y9cdl+ew+n6Dtj9ABAFR8q2RgfOWyJgrF/7IOWXZK17Q6R6aDuVCQSZdHIky2CIxseL1uFyXXdbOUbX2VLJqRtwHBb2SzUqcA9FtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAACfPdnqoSKbRxNN3RrnxjHekHtoJTktHimBbgUQcpoYPy48V0e7Jrc4IndSPm0+8KBZf3B3RvYnBkm6lw63RERYo71Tr3GI5ycL5XErWdXoMBCQs3KvPuY9oHF2eKn+AY2vb9Iofwl4ffBmJf84ZQwrOz1pDvH+2EkTOmMHL5X1J3Ne9NiwtUcawUYwExvT0EBg+Ckv6os/1atk+Y86hUL" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6khunK9u5a4qvO1TDp6Y0kqUSY7P+V/ZpCug1HItFwmCQpTXok2h1FVmJDHjXloJflLaclXqVlXLhnGzU0uvA2+NGrWbh085kXD0692Nb9upzEgVaDac3yQSt81Osh4K83Lc1MD/v0fH3fDdMmWmreAafbBhuEkntEq1inYYV8oFPfALKecy46laoyAGwTnFtCA+IUZc4LCA8FTxGBKd4AT6fVk3I/i7KJsn1r7HQbGthUKa6BK6NSurtlRlxA8HedTHm+xm54YQFvZOS9nqXgt6YpWbRxrP6bbYKNUoyE4bfCW2KdhGMcVc2n+BTndpx4ECKGgwiCt07JLkd+9/6t4Np0BN3o/1peYLdRWm7hc7nWtYgAIyaE04ZmGyF0YDEVtl2vL6S7WK4L0TEyXPZeebNy4+HiV0bWIooHXUggr4oHz6aMu3THNbVyIBozSc9GbZidGbPeuKRRBDLTYKZknsdqDO4ZVlYOyVl6ZatomLhxZc5kyTbmuw3GCqEokErsrQzMCx/qMCDvFjLw3+qT9UdDmnRkA1gM6nCy3u8OQuGSKksCG7I9GzAJXKKpxjYldJxSgVegGBB1JCPQhdZRnxwqVSGjOZyOGQjafAbrCfSyoQisVmbDdErrB4Rd5NJeNhcoBzxYZMQ384KB9NyqORKVenhNDgrQtgDjtrm6rP5LkgOfmLOTI/bfLzLIbxJi0LzTZaNJdC6ykFX6rNSJta9Tv7onYMor963bJq/S72GJKfxGu8YWSyBWmQ7u74veUrAY4qPK1rczqIIpytA53U1A++gwuphTPEFIUt6kGOIko56syZrQVKx6IkZ4ZbaGlkIod/LOCzn6ekhD2aYbxARWvq8frJFn3kGRcwxrGRPdHOLBtEgGp2xYhBtPVHJWZmEq5FJcbW5c5h6glaV1NtMWpitSMXtkfPndN64Ue+KJFC8/JfvvWbVzPfOBgV5d8OTXjOTwMM9T/VkudkVZOwi16a1mY6jiJM1AyzCZ07FoRw6e1Pi2FHusW/F8LtXNDdakqXapdtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAA3HLVo2Gv1WvFEKuRfHYDP+tdARCNq2xE5Zm6dBOAAHPgAIL8IfUpQuvXSsei6f7ymaQUXXnjzj3WacJeB5mUIa2I35N7nGe4E3k9Q3UPki34a1umv9JYIK9d1i+UvVwmjciZNt2bD3mWb1dRkZcw3mU/Squ0VhfMmmxVpwjapoO/hvopIjpvEyIRGi8tT1BvGN15o13ULinsAWFPFYrsA" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "4C8BD016170F76014AB4B41C2C5927A37C18E4A4ED9D76D3F4D4301591AA994C", + "previousBlockHash": "1E5DAE3F5B2211DE02025CBA6E111FDDD53930950CAA10F5283D97109B7E4B69", "noteCommitment": { "type": "Buffer", - "data": "base64:5nZbgz+GlqE0M+U+H8avXP1sP1GJPOQ5QwSYqh0jJQ4=" + "data": "base64:MUjc11Zfs8mM7wparE5QQj5MaH3i9nq7RoX9FkS0fjI=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:tX9OXfk0IJS5vrTX1Xymakf/lggA+iPjL1aJ/Mr0vLA=" + "data": "base64:ecQp80iL9pTgtLo/KmDEmat3UQKPbjmdMDUfraW3RC8=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470842734, + "timestamp": 1671691618133, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1354,23 +1362,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1iHOQg51Z+frQxmLz+0fhnF/1S7DhxJITCFhP8d5MtyyGshzmpjM8pb6x34IJeLlyFAvRTOGDfSvtWPWBwBFl7VTk3/wDG0pYw2q0wWRAauB+UrE4skYkCRoyR60AGKN6fcaebhBKniR4wFOLtazMG6sVjNPtdQ+goBozV9XPB8ZkekZUffHHIEfTGLs22yXypv2G/QPUvO77/UGR+QSzGCbPSvveQBHOampAoZ8xc6sHdjvpKlu8t0V/NeM/lRxXEyknRmpB7AJn9wjdV3QHRDDPzfzRj7ipb00Pt+xFbEB/vZtSULww6tflKp8rX8fqViInfurb5AmvWljVNcf5vIWbSY2AG7eKXSMeNdaYMFLLFBX5S7fBlpfbszcq9kHCc18SzjlCE6FTQGJ4LP4Nx+EpYzvtDfv0LFE/3KuD5jvx9ig86/L5DZreuyEZZMHwEui50l/GyaLKcMoaerakNfmkEPMjk7TRksEg81Fv/sdaW5KhSxq+8W4KGmPdMESadbKG61yaA9rJtG6z/Aga4tLqvsY02fv8aDSEFUtBQ6JV8P1mwPtMypO7C0BwvwBb0P+dY2CcYV8B9g2Iae/CNQZ13JuwFwp11D3NeWup4+/LLa3BbjJ4Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMMi68kzakBifHOQHg8baXOXXbX2xT2uvcWa2sjp8JCr8k6NbS5lU+uAbw1cZnyK0BZJ9fT11D0oiO0kWyKMCBQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAALZ3vB9daXiOoVTSvhwlrrWinDPcrBudnee6nxseF6ba3QQqO0xVIo/FTSQZcEv9/hzjQ4LE3bBBEx6RLz53TEAkI1lbxNCcCi0hx5hC1LwyOv8ypWi3GPo6dRM3T/0dE2v9JB6iiq8J0sWlF5KJwiDsjOGzqDyTgpYU5sWojZsIZWyUoe579Wuy19M1Rn7EUaQb27xq9oJoUYqdM1IFNg3i+1NbxxfCk+KL1SEHV0uKVcl+RnilLx7uQvkIaW6UHgpmD6gWjcidMT+jjjdGhMq74C7YEVNIKBCXg93P0qKIqp++REwZIDghffELpU3Yyl0ngUbBgW/qV6/x3ZJKLNMUSu/oF/tSRs37X3D4bf3hDZV87ip5TWCef/aQS0+sKm7xP6EIILeKWMGyWmVMYgTFoWx25q6CpQhcaiLm088jyZUuliFNPHl2kIyi6zFXTQlT8vquDyMqpkE+RoCpXk1F0CjBADSw81X2dnkYKPXFZNRKhmNqjkvZYCnaxMyJhCnBXAu7m01kjmigczp3stjrqCg8WSw0SoCZqQxkzrO5d2kHeo0hCU5zzjzDIErReGZFJeAlDxd3OBz1iQL9nz3YW48LhRqQNkUO2gdMSJxn36KFawLOOfklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwt2HqvUDZZNtd6Cgwm35oqSCjwKiNbHZJLqNqvVIOHCoOvCIBHqxcAOX/wBsU3DeVD2Ye26YBq6D/g0YOrgXYAw==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAADMdDH1myYP7yMgTt2iz44Tz1T9ee8lK2MDBCzU+xB56sSGmf1vajZ0bvR33j/FPh4gLQEOa62mmT5nqdXzl1FlzNri8OTd8/TkbkXF/UFeyo4RwfEpqpcym1et/WFHv19dqp1L6xJ6ZFq+AvPk18AuwL+QI1L9Tnp4+zI7G+g9UUm71XTyacgTFxpduFP/yDSKBLqhv8zGn6iXVxPBy5NLAqNU9qaFSxal04GH8rPWClMHiARQYYJtRVvcxgWC/+JBCoItheC+FLdtI/wh5Ip7HRw8kB9dCnhgrH3EVoWNxUtg841wFHm5rYKcjOsc5SB29xWccXGQepmHYoleGNP8bsXRxsFHQMOQ3MY+m0/uw8kZkn92S29thbdxFfO/tFBQAAAEddyRPljwJvxFz9n0ZsCzzHuZ2tSUDeH1z27ZvQH7gkeue6+5QcJgmPSIw9Y0RKSNATlx/zqOcuUvXThzOYrgCAfmgKhe90UwmmVgE+es4LO8H8j+FBmonikBY/7DI+ALCd/WN1w/p3pntj3p/pMMY8QHTV+tjLpFxpAvN4zxm+fWKVXK5tPcn6+OWcqMitRrUTeUporOcB/kyGUX+TtGSbYpvouiS4Ni890aUQfLRcNaObnBiYXDpTpXKint8TnhQyRJm+gmlQtqpT1Fduvu31ojJCusEGYGD09wHo6boAYvOW9qj/3rAwEQf9/KILpo/pU+cj5IIqZdUsGDCWs0i2mzViCE9+9xS3x4BlqmoT9OStZSNutj2pZRsXqzgd21EIXy3mFkBK54/0M/LmEv41fIl8qCpGxXB8CU24MVxYpEky52LzUeoI6RQu8v0VqPZBjbSRnGhJ9/iJtODfw0T4MDvR/hlc96z8RxBGZxoz4eW5v1NE3w6XiCAXxJ8fC2/Zptcis11+YeaaI8k3HEZBcyBYb+ns9vWmHNsfAVyY+LGBLYR4Oeo+zrhnzMmVL1TrazNGrrWmSAxlZYAybzaRMxu0Y4fGxCvW7d47ooXzrdkXLA/1hxMx0WEeQrWXujxWzNiTIDOiV0mAbqxpwHA/ftnzVxOquMxUvpQ+IxQzEAWrRl6t8zfOq9Kpv5Q/P6iwssfeXM7NopUuT1SzD3ugy6CVDPDhdlvspKgSZmtMT/GvvmmDHFxjtqmP0n7uCLAOUO5IgeEHRltLSOIF9XoBufLxVU/T/8KCezbRsqpAlmmat5Lv5lp5RjSjx+o22FPcnvX1iYhLa0g0eUS+23jFfUXKoUuRRQMAAAAAAAAAmvakv4gO5kWvLpOgij3BFTZxOCfSuZd0U35UylTh4OEWTncliq5bg5NY2ZvW4Q0s8gmbo3enAdE89Ur8+cjFCg==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAh9mM/hnz8qBOR4JM7rIkdQkPntfy3EuB5GRg/UzQVg6OYjhSuGS2aI0rNIGEY3IltxbzHiR2Yf1E9oxKVwdK0QdtGCQUyYmCRV0E+izMmLKuIBZzjgVYy/ftAR9QikU2ABPr0c8oIsge10vnXIZAYWtsyNLs/j+LDm9SW3tpq/oLplOVXDQoYVV1xYsxHuLbZAHp25OQPxMy7qEAy1+eXGbrPZh42gtYsPwx+QfPsc2nl6bYQFKv9s8GFNpsU+UmG1H+UBTh41lMjLHGZStaTOCAdN05YHavAR8yCfvKS8SRBVc03nn0ZtHCoCyuBGLcUneHIzsCIOgFWHMkoT0xMdR2Cgzzb6SDWE6c05vK4z0kDaYuzWYaK5gKrAjwTaAeBQAAACR1Gz73oPC/LQqzZkheJYaU+DqWO2SBCH1746xfW/3ZbwpqAt4w3egxBDhkR744TjzTwkarI4g+Xjn3+W49wBJNPh7/Vmzcxt8xrVouQbw9BT2Muv+i4ODRNGR1yewWDItZBhyVS4grdUxxBQeBTZK39AY9JkqqYwT+y3lUnOBYTaS80EYlBcwTmLR0f3MopLOlCTlNoKSdNLlq5TyX5ddc14jJujjY0K2/q/HZ7I23k3p6FWzBGhoq/rJ+mutd2AYKNT0CFZLFtzkXUDgqiYYDZFSgyQeF+szKla+73S4TjuNMKaPtJrsGxIQEbYTXYo0+21EnovvNojPfigPkKstI5J4HQjlD7HYauwTavbzDw57t4UfGNUwuiOFPf5tusRB26k7kJhpKZTkyn8yia9HP8+N/XbqBGw5O4dC9BVjWvelOV8e0mlwTG1cGh32WnnrPnPGM4ovxrWGlspp3ljA2NtB36V1yvYH0BFuZd26PlTymLubHngrdidWfIEngsBoMMnNiVEe8SC+/HHECL6I1wp0/JLGNuDDJISKFGR8S8nkOa8gTGFfATi2ZmcokxJ6NcRH+bDOe80oXVa+NwZmHiBcj4hobBCuCjNN8se07jewRz4Z2ZOMcia3+VvURw7FDGjRyMgOmTuLeTbi7td246b6slsGZBGxoosapDh4As/SgpY72Eprr+I2W+IB6KxJC5n2b0wovO7xUrAZsBGDg2PXEoZiri680oF3Z/28kyO5k7Qx9SPJFCcXHEVw6cLVJ5WwdVgn86T3y7h2zjesisvf9f8SqxnPN+lGpBQ7ycYuywZzrKbiOCkUbPlY2L9v2JgGynXgN7wcmEHnpvyCtiUqPxaCjGQMAAAAAAAAAbMPQgbnHBalL14gAmsoKERy2NLr0gyzBd+bOr6xkOCOME6IGUAFHb1R0qcBrqwBvtU7kEy14Gvb9fNSH0FHDDA==" } ] } ], "Blockchain asset updates with a subsequent mint should keep the same created transaction hash and increase the supply": [ { - "id": "93a130a6-4aac-4596-82dc-e9d5219f1ac6", + "id": "8a916717-a195-467a-8da2-aa89af5b55fe", "name": "test", - "spendingKey": "7e8f503ae83c219c6c06423c8c98382f971d69339150a79d4adb0d85566e66a9", - "incomingViewKey": "933f6b40e9ca89656fb1557d63ec0278b1ae1c5f5c6d125f33aee9e672b65404", - "outgoingViewKey": "910094059cdee930d487b0ad6755f1bbd4d9e39b7402c6f8f972b292d3aefe7a", - "publicAddress": "c66ab2b2e77133fc8b8d1334e4e0bb0e608982d9757be7090ef669fb37714e0b" + "spendingKey": "3ccaada4decc8af4d0ae7c1c260f27b76b556ea36daa89cd941e9a513b3e9329", + "incomingViewKey": "248b7204a92136d609c040b41e3c642b9c4a9d68a7a275447855e4490af59d03", + "outgoingViewKey": "67dface9719f6d1e0e06e80433d59ca9ba117cea752b3dabb8ad66dad5458382", + "publicAddress": "5305a44ac453278d75d4d5fe10a15ac9ddb75cf6a30b50ce65c4fa8b6b09e419" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/Mp6kIUNUdbgWFW9R7rua0E4Mvumhtlr2Dkc3NtjEiXmOlawoUJ7zfxUrzC5yk49t0/IYBZClFj10QUt6P6pmjc+CfXhw/5cAULpSgU6wWw087TDRs341nAINOnp7yykvb4JmJ0v3BVdIMseX2/G7d4RCk5VuQC3ABOiC1Vmp8EAm8uJY9FvhUhJTAx4mu9JBF4IsND+3crAm4RiEf/fraybbuUj+9Pz8n7ELWc6pGniIWiZBZuL48RRbGThJ7qrus3zIcJ941/ScRc3DuwVo7gebtLmWNWlm3eqqPI9XMM7n3ysGxpxozaK7BkJ4ZtG5z2RFKEls3EzmSUY6j5EClwRYkG6fKkgQHkeSaVXEWOhrliQIAXrc0SEXRVgyk37QQum8LrgKrlaGw3vuQ2EPd9lStU0fmEhRVGe3wX/OvZlLvZJg+q55lyNu81jdVpubgyPqeXnSCbeDayVS/qpoyX9/qy2i0wDVtp4S3QBJDYx1AERi7KUmONIU0rW3MmoEOzBBJdjI7Yd07IDAuIibzKW5o/qMUgWJXuPZgoaPQcYtfQYxyegSC8siuSeOuyWsg9Re5HgMHGMObOK9OBFpf33oLxxD4Cg4quIPoH4fsYCVJuU5u8aKFc+NFiPGv1l1oODJpDweEh89Lq5YSXBSGMxYyOI9GtQT9yEcoG+3NuRKRJWKzmqzYHzx4XGEzGoj/TxUaCuvERKEVBP5rqyqUXLUnzRsVahvTDE8rphYBXCUNiI9JC/MI8EodwpCbRZVBhRBbhAQ/xcR+zd0r7Q6GWk99IkzbLoeJgy6p/7cUKstASPhin3uSNwgt0PGlAR74yaQJZ2eyMfh1WkmSyuwVzkpUu37p+ErUb/OMIsDypj9cTN1mgUSDWNX2J6sgJSm25kJwjoEk8Ec9PBdfBwLTq4FeaGhjvspFAPfLe0Ws2kNv9RuScwq5/vOqhs1Z0tt5dVm/F8aehuMWL/osEUvxwCrfz58IoUwWkSsRTJ4111NX+EKFayd23XPajC1DOZcT6i2sJ5BltaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAAccKIGH7TmvDhWrXiAOspH2YG29aJ1bf/QuU2syLMqTEkBh8L04LdYZPNatbbw63HlsA2vP6JhA5I0iRrsUP6OYwEQxj4pojHAusrcDp57Bgy+q+4MMHlDJfB1r6qIQgDjm4nP+4WMOhOyd/HWyjx2Gj7er9RyjQmJtKf9tmhKyedPaSjjbLbmP9ojx1GK//j/8B2w9Vv0U2OiG6Q2dUMJ" }, { "header": { @@ -1378,15 +1390,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:wNxco2WqqO1JwzDi28GxPjZySPyE4f2Xhat6urom+yM=" + "data": "base64:U6xsHDbPJFfvmHsdpI6Gy6NJ8bC/D+ZqtaGe1rlnjhk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:CirGIGXAE4QJr1GhAoylr2uF+CLAFZA4qnMWpAANU8Q=" + "data": "base64:1gG33xSjukSrn/xKzM8FrLT0pV+zJ1/W4s5Rx4kYcEY=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470843735, + "timestamp": 1671691619050, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1394,29 +1406,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAn0Y8aQvUVgpKrMSsuOsCJy73p5KPK3M9Rlx3XEtSjiSj43m9sl19dF5nOVXKHQGazeGyhuKBlh5qEAPEp5p5OZUeM6LryWJlqYyFqIfyagO3NaIwrJoqFkPM2KkwQVts7iyV3B15/W1rqrEzhKL6auNHu9RPnsTFoomXvoYezVgHVO3lTYTHP3N/YHWQe1DdZ+txfjvRHXGLVfR5gDHUupfb+J3qS/Y88rQvAIJvtoWg4/CLFj42/qyGGCmjLhofaAjm8GfidnZvxLCbrfuXw/7WdE93wKYHUPapiQMm4LF6qXOt99y20SwCBMgUMg/Q0aSv5vlNek6RpWo0/pVfmtUNnDkw0gyT4fuDI/SxgFPEtsbNbQ4QbVa94viv5d4cz2/SWUIDPppW+eggkFXVZtu+TTzhFw+BE1B7WjcS1CvkHsqN/PKIlyaJD0Bfi+rYe3zCWUzCYEObGdP+bghjvOyWwb62aHTm3AQny9OYsdHE72t0ihQtY0CHV/XCbxEFq8bZo0waIE6Gfg4DESWZKYoedRIT2EhSBOioaoFqwLwp5m+2Daz0h7Q8zRNibGlrB5itq2+NEtkFDnKKvBqil88lSTaKZ/FJGhfCEZiRHm6lUIwyUX4rzUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSoHdYnt2TWjIf9ibr/kzC2yE22hnC9HI0qzdHr/GzporEZX1rkbKP2ECHXwRFsd2RKoxDM/vbzfl84Lxj1yWDQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA7xqNnpNOUxGORhtX7vqi6d7czS6/RuJzUdeDStjr6tijoSDhriyXx2BUjXDU4MB0+awu6oSfQ35ngYLtZwbNLC1n5bezojyMheK28Er1N3GOWdDbqdGIpYNw+2IVxWDnCFVvfroPmi77ngEvHPTSQ4nbAsNvu6nZKLIXjEJpZzMKXNTkyMS/KoJ0lcOairUvktqM2sQ7BUAcUf5CFqFr2CA7wQMjDTYdPIwLkZOBgV+WopzdIhau/KyEo2Pt3n/9zuw8F+arOcjbfzEAo4VqDsOt73aL8NFiAuJu2KEqamHv9z3iQoLzw9NuastoQqanmFIhZ30Cr72Dq7T6kCiJu3e/wzMZzW6nbBF3Fnra2zEZVqSzFljsJBTQ7SdXVwxFARLYuWq/RgUoJXMyp3mJrA2q3L9uGt+QLx19Hsxi3QZeHtq2wWG9gAna0SuBcskSIUq5vr9iTigofC/hXfWO6Df5A77oCKk8O1yi3K+9/kqgZT59OjnC+2Iy3W0sNb7dyJz59E7Ted4BPYCjhTV/MBz+kQXNqkkccG/zwuChvEVKpJ1kFVc5cs30O3np7zfYC9Evchaar/I9vQFg/Gnf584pRObM86mwmm+6zlj2wM02YDZ8AjzpHklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw7Svca/yOBKlWsPa34VXpNYo+5OT7ewcKKAdx6RD0nYkHkYzCkFl0gEdKrKxSwuvCAMh8TVWmT9y1BHtvjd4UDg==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApMsIp6dd6ecDRZciq10g01E4PKkjb7R1gl1iFbrbvVyUBEu3XaX/EKq2/xelMHjA687/5yWNGtuEgtrf4oSBRJ4zcDzGsgnsn788qhyKlqmkm667jvp45X7vqM+RVDit0zEBkbbK1fVEILGYWOWOGmTLahW3zqIlTSEvvYdmcIEAO0SCg4e9cCNgRCcconQOYXKgSdvZXwk4wRoABH4hwIvxX/8vPtnOrZXw2UwFd4KRWaG+Vpu1aK8GFR0hjPEwypABO90NLNac8gL9auAh7JM3elrtmEO586JeSSQW932LwOqe63gpBChA5IQAR37GYNmLfcu+H+tzdaK6PVbzKpUEroOIydeCTSbxIkunO0x2bGdWD3Dbtxrcw2sDOrQxh1wbC2a0oIf87kLYbuuY/axd0mnYEwSRfnRePJR6zcK2vvElG9eR13WbWdYu6WZyf8D1Uv7DoZj5B4sGuzx6m9PMzT+iQ1Ab0PDMN5YsDhuJ334fx2LMdbk3WuY9i9ZqGSEjtLmPqEdWa2VS0e7W/YUcG438B+na24kebIFHXGJI8YX1aOsER28je/UESmjXrdGAOjJmgZYjt/dG3+/9rca2IjcDo4En55iS7rjypmZXfkHhRdANknO3ezrLc/fO8uJkmasIj9V3oTuJC6u8oqgALK7uXKAoqxBQzQconVz0uQ6LwaDmKpqHW1tZEK9UlqQ3RzMUz89ObMnF5zjgfP0UD2Uy3v0NgPP6ODV+cX5E89KSe3/QP02HBTli++dfdNSVSYVY4ZTZnMtlToPk291r1ctJeiSWj4xCCpiEVHTJ1XQxLXSkfnH0VAaNqosyfYUcfveMqyaxovk6n3xmXy6OVnw3ayrYE1ry1GKcv0xGh6MoL0HQ12cNwLNZCiT2XalF96r2eyjTv8cPyC/fbXRr8CRJMyXutl5/eS+q7aVX6jRtdL337nYdaMlfTFyPYQ71AbS3tb7usK0ZTfnHEA5tON22EmrCxmqysudxM/yLjRM05OC7DmCJgtl1e+cJDvZp+zdxTgttaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAB8Y4recvEa53r5W+pYV+ltBZoUAl4vm9FkiVXcI1xYGl4/qTA8BcTDkmAw9A61OGKl4RLvi2FZwWREmpxGCqSVQ438Wm7vCEyoI7hFL7hgCUWJHOa1CG1ZL8q6nKiMngMWMg9LnUTv88nu6OHwh49I3oXzQKPzw9zXDOZg7AqyrBVt/xXKkIjDLgPth0dH43pW4v9Z4S41uWGLoKI/sNYD" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/Mp6kIUNUdbgWFW9R7rua0E4Mvumhtlr2Dkc3NtjEiXmOlawoUJ7zfxUrzC5yk49t0/IYBZClFj10QUt6P6pmjc+CfXhw/5cAULpSgU6wWw087TDRs341nAINOnp7yykvb4JmJ0v3BVdIMseX2/G7d4RCk5VuQC3ABOiC1Vmp8EAm8uJY9FvhUhJTAx4mu9JBF4IsND+3crAm4RiEf/fraybbuUj+9Pz8n7ELWc6pGniIWiZBZuL48RRbGThJ7qrus3zIcJ941/ScRc3DuwVo7gebtLmWNWlm3eqqPI9XMM7n3ysGxpxozaK7BkJ4ZtG5z2RFKEls3EzmSUY6j5EClwRYkG6fKkgQHkeSaVXEWOhrliQIAXrc0SEXRVgyk37QQum8LrgKrlaGw3vuQ2EPd9lStU0fmEhRVGe3wX/OvZlLvZJg+q55lyNu81jdVpubgyPqeXnSCbeDayVS/qpoyX9/qy2i0wDVtp4S3QBJDYx1AERi7KUmONIU0rW3MmoEOzBBJdjI7Yd07IDAuIibzKW5o/qMUgWJXuPZgoaPQcYtfQYxyegSC8siuSeOuyWsg9Re5HgMHGMObOK9OBFpf33oLxxD4Cg4quIPoH4fsYCVJuU5u8aKFc+NFiPGv1l1oODJpDweEh89Lq5YSXBSGMxYyOI9GtQT9yEcoG+3NuRKRJWKzmqzYHzx4XGEzGoj/TxUaCuvERKEVBP5rqyqUXLUnzRsVahvTDE8rphYBXCUNiI9JC/MI8EodwpCbRZVBhRBbhAQ/xcR+zd0r7Q6GWk99IkzbLoeJgy6p/7cUKstASPhin3uSNwgt0PGlAR74yaQJZ2eyMfh1WkmSyuwVzkpUu37p+ErUb/OMIsDypj9cTN1mgUSDWNX2J6sgJSm25kJwjoEk8Ec9PBdfBwLTq4FeaGhjvspFAPfLe0Ws2kNv9RuScwq5/vOqhs1Z0tt5dVm/F8aehuMWL/osEUvxwCrfz58IoUwWkSsRTJ4111NX+EKFayd23XPajC1DOZcT6i2sJ5BltaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAAccKIGH7TmvDhWrXiAOspH2YG29aJ1bf/QuU2syLMqTEkBh8L04LdYZPNatbbw63HlsA2vP6JhA5I0iRrsUP6OYwEQxj4pojHAusrcDp57Bgy+q+4MMHlDJfB1r6qIQgDjm4nP+4WMOhOyd/HWyjx2Gj7er9RyjQmJtKf9tmhKyedPaSjjbLbmP9ojx1GK//j/8B2w9Vv0U2OiG6Q2dUMJ" } ] }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoHfiVPmOQZrHioBCl4XhslgpMDsJhJaDCCeX4ApT4haRFrOp7M3yHKfIr6/cxsHBj7kDAJ+709A2uQiCA/09Z5Z15M30A7GViOmyTO1BuyazNiuTLIBrNxkbJVW4gtzWE4oxn42jRmj8Gr2kT0NQABpVOIH2Y6fwCaGyFbnwEIoRPkCoHKJtK5HwtnEK0yjsr+iFFDPIPoRPqjuKjetwyhk0dzxbICVAkW3eON8TR8m5GSOcDyoG5moBcxlsThHfso2ICPaT0IEQEIhvM4t3MrKdRpuOjJN317qQkHld6zPrBY2A3AXOpWQiZbB67Igafs3hbX1qCniBvjiVFQ8KB4mv8YftGAXyBEl67gGg4t3skvBO6nNEWtQWZLgtFX1iTYbZIY7B/lsZTO6YaehRG5KaTYU2InKWqQPD8w93/ZRJELCFrQ2hVB+zRDZ0oiWWKDvk0tKEIxxjGItu2yXX7QknaxqNTYDPfLNnFTj42Pb0tYkjEgjkhIe9dlKQevweRhqlX2/7zw3M7OZhKPjFaKnbJUJzNpmdRG0t0GCXOFGhx92SbdkWZTEZtivECVIzqfacCHbn8dIqpDi8kziAirKAQ2PNASLTzr9oZ/S4GYbxN1IR5waXToApbUwVxq/bf34fJscIZC9SFYZVIp7V/C+R5xUh4bN+EpZxEjHk/s66C6OzdHgzaEGZ6f8d+ePOkX7bXSEURlFDmCcu7YTVNwEjlb1e9jWflAyJAnt5h7iCly2OJZuh4aZzSq34PJve4gAbZvoVwsvV7t/bbtebfT2tsmh/GnJJuRLe6lap6VlwrXJrpQfk7kBNiMvb3EgHEI2f31uHBiuw1DDEo1H5hdu5D+n5BZe4ALD9rdqPZASxeSQ1IoWwf3xNdvnwiFvgbDCJtlWagKeNCY1iVQiGLmHQrhxkrEBpjiCovvFq4uveotI6zskNuSj7bMlgGUHgFqvNj23XnixoTVdY1oCJNRccXlP1M+GIUwWkSsRTJ4111NX+EKFayd23XPajC1DOZcT6i2sJ5BltaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAAAAAAAABjeLxuNwKjR9BTHaOdJlGt4pRQaFtIovBFG2x9MGiCQXNxcOijshpq8NXjXrI2zZVoBsG3k2bX2LFGNrmfHQOJZJH6ousbnX/PICO5002623D/pvZvVbcOtYNfRYFZJgVYbBoC892o6aPLGbfCy8PJql2lM1WmYrwPC+UPh5bWFfQzBvprg6mRG6z55/vZGj8xQyWkh1XK4gWfqJx/cl8F" + }, { "header": { "sequence": 3, - "previousBlockHash": "578A6655547D83393164C327EA19B715165237F5C6D02FA18ECE5894507194B8", + "previousBlockHash": "0515912F837CBF54ABCECCED0B464B6E70943E24D34DABC163E5CB49AC1A94B4", "noteCommitment": { "type": "Buffer", - "data": "base64:8Z12F/JIq7skgOnwSY3q4sajNNFWoYVjDb/9yKdTBSA=" + "data": "base64:SvyZiFIJx5FYvN0EIOW0KLca//mulDhv6tVr1uo2IBM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:qm4f1Byq1rdSX/Qrwgge0owJIwg0Imcqde8Vgygmac8=" + "data": "base64:8cHI6oPoOQjiHIjNQYOIYTgcRlWyxi85TeotuWg1Uj4=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470844577, + "timestamp": 1671691619901, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1424,23 +1440,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA4Kvtr5YtKVHppMe7q4djSw0HVoxuWivfumzM2dC0ftyIKopVAUe8SBbrj2Zf2H+AarW28vBje5NEIUr6kY8c6sqEIoOzoTGhSy9dXS6ufv+OgwThiQYTbS0WUeu4PkmgRdOoiZfenWBneZIeZzBqOEG4yp1NRzeNXsB61kQDuUAZ3QrU0fCKT+X4vu0LAACIZMqnZbT00Q9wKIoJwCYhMH1vbYUX9lyVYlWmWL5UQsm3iq/+wYNsfk1hpSkH/rothY+cLUiCMmaze4HpgNd0kwJUR60NUQjBxutFmGxDql4+maUA9bQqrg2a1y9+BnZDuDmVdnoTZ5xHth9022+KwwAk+LxiuFmtGIs1D7gQDXodSjVQHgkTplUlkF0cP6RZhkJrWS5mhLEU7DwMP9coFw0uB+pC6mxgUPsFaK8uI1w+4GFBWCfyrCKL74S+W8+1Lnn73vgbK/qVPFbbnGjtAyhofwYc/V/9GPEamqb5ZDx34BC+pYtRn+WnG79Yd9cp+2BfwCdl6i6uQynC4XQNHzefib9UgShy12/lHGE8plRf/8j9aGHr1VflOcvQeJ2TczGCs6Etw5e05f2omZnw0gg5wd6ZxhsryFzdO2LV6ynpazeD1Mkfc0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmElKWHpe8AOrBxcXbEWXIxQ1Ur4NcOrpEWAW6ua5mttrivMA//ZhxGaKYLGEphf6VK3JRNT9MnQnfs0/71grDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAi6qEjOksVQiwjw6ydzJ2l/R8ruiTTOPOpUDA0jrnZmO5MxYbpf/Lm1OGGNwjuPrVC4h5nVy2UhsPrlSZwrcUsO0OIfqujPt5bqEBuLKrysqFjxcU+nxANQr4Smuc8KO2qEEDdi97QkJbvMHGmvazW31I+PmbDAxrSjHns99G8osINIXSCr/VBGbrduHzyUfh1IIg6NSru7jDR2by9VXzzzugwbZhd7f5PDtlFcQaCkmgGkacXiCTqQh7NASEIcZzKim6a6MXL3fbckUSWhD6aKkcP1CBf41PRGzmxGKbVJKe8B+xPVUfJiI6iRQMMJUUUgyqgN6EAzGMa2B3AnXJDfP7Qr9OdkqHWCgqqartYKCYTDLKUgdKjwzzFJ2p58NyXMkIDE2lcOTK72373EXPWb/fR+hIAEf5SfB5Y7jneMN6XzOoSFWmq/R62xCaSvKhqfJ+rPglgbU927wW9DADd3Vx/f8l9mD4RR/qL5GHpdjptbX4+jYvJPMuNCon1shVysIwipl9Kjfp9MmYQPq8HkbuVQ3bnKKzJSkpoXm1xHSz/Oh4Jv9SElnNIPLRV1kkLU21qE7GVcohZS/N3DIPIckfjZPyBgp5Gz/wnRX+4U447xFsvPPPPElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwKbWPkIwyC6KPbFzvT8pgjy2iFuKWJ1R+wtA6wAIKsNCoEf80W1EbGm+ktm/Rkd5PvHUWIZ4jeB3qD7biDy4BCA==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmFBo/uzLB7WpRMsA5v9Yx/ptuVEwF6pW66nhiTSoMymFOL4A7y7iqlMS2aLQMS/OAfrxi++gRCxqJIy8xI5rGoyMA/R+4eQ/FbiJWRmlnhiVtxb1EjXoPs2UuIAkF0+A4nfZW3doFnL8Vq5dLZVs/NQMu7bSOurV5aYe2Dlg89IX6rnsgRTyz3afmIe5vrCBDuYJuKfdvB0OGbgojGcY6eUnk2Gr8dl9wUDjMIoGcICCdamoSn5AxFdULOmkDSouGmNtr0D1OYbJGPkvUqBwLmUOcK/6tyTZZkjwI9EpPbrjNkfzA+vlvW3ElErt4tvdAS9Oc2ijbmm0m+KpCykKps0bIs8qVoUciqzhY5ZiKbvuNt4iY+mUYKEmRaS/bztRhVRljSwP/6EP60llRSKG9vJVDC12UIKECoWFA43AYYfOnKPKBra5IjFqDDtzmEAQUb3Aw+9cpP4viUL6/+AqPcXTPHdzefOfB4E6DipHwughVNOhp/rCHtAa6uOYZiH3ofAFUPUj98ajTqd28A1lWnv6CX8gF+ftKPzQsP0VtCA8ohXamgsNdgGECfAAcphH57e/7hcW6x52QnF8CFxlwjxKx+CmXiAy6EWsYZ+5ngcVF9poUSB/CHojxcZ2hpCBLY3AxO+Ow4BLkE9JY5UhFZYk+bpqsHnsxCGFAquBGtRgeL/y3FDRq/0oNnifFOy9ya8OhEcH3awLNIauMuAcQv/saGhsAVFFpTfb/513gnI/B+a9IaBWnTbglD5otZUGmeRtTdd2R90Lw6N23Ql8vMj6VzCoPIBihVa0oFjnDyZgnOXfiPLuX3fSwohyhBU6sG9xbtc/tG3+J1GfDueLGbevDBaIGnrEBMo9N+yyrsO8cI8W7Mb5UUIOtFvtF/oFYNp0icctVEU6ZgTIlDtE/muZEY8Wop6ukG1Rf/G9ixbacNpK8w3v/DRUOOzwIcRkCf4X1m0D5v+1LhlhMdE/S9+L4UnupRwNxmqysudxM/yLjRM05OC7DmCJgtl1e+cJDvZp+zdxTgttaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAAAAAAAACbM/vjvwhgtCGUzUinOxp6AMlyLaUFRBGXN8KwZCllv8jmIl2G0RvoaTi0Mc6fY5asZ0V4EfbOS2TEMBzqcBLbY/zHfT6S7tNIh39O1duiizzB0pukwrPphmocyRddDQ6Hzd8KITe0FlAziwFGJu7o2t9P/ZGvsPF69LvlgkS7VRJvdvkPewMzLD3G4i2+xBtxhlDvuLJD+S3QXVP7hWQO" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoHfiVPmOQZrHioBCl4XhslgpMDsJhJaDCCeX4ApT4haRFrOp7M3yHKfIr6/cxsHBj7kDAJ+709A2uQiCA/09Z5Z15M30A7GViOmyTO1BuyazNiuTLIBrNxkbJVW4gtzWE4oxn42jRmj8Gr2kT0NQABpVOIH2Y6fwCaGyFbnwEIoRPkCoHKJtK5HwtnEK0yjsr+iFFDPIPoRPqjuKjetwyhk0dzxbICVAkW3eON8TR8m5GSOcDyoG5moBcxlsThHfso2ICPaT0IEQEIhvM4t3MrKdRpuOjJN317qQkHld6zPrBY2A3AXOpWQiZbB67Igafs3hbX1qCniBvjiVFQ8KB4mv8YftGAXyBEl67gGg4t3skvBO6nNEWtQWZLgtFX1iTYbZIY7B/lsZTO6YaehRG5KaTYU2InKWqQPD8w93/ZRJELCFrQ2hVB+zRDZ0oiWWKDvk0tKEIxxjGItu2yXX7QknaxqNTYDPfLNnFTj42Pb0tYkjEgjkhIe9dlKQevweRhqlX2/7zw3M7OZhKPjFaKnbJUJzNpmdRG0t0GCXOFGhx92SbdkWZTEZtivECVIzqfacCHbn8dIqpDi8kziAirKAQ2PNASLTzr9oZ/S4GYbxN1IR5waXToApbUwVxq/bf34fJscIZC9SFYZVIp7V/C+R5xUh4bN+EpZxEjHk/s66C6OzdHgzaEGZ6f8d+ePOkX7bXSEURlFDmCcu7YTVNwEjlb1e9jWflAyJAnt5h7iCly2OJZuh4aZzSq34PJve4gAbZvoVwsvV7t/bbtebfT2tsmh/GnJJuRLe6lap6VlwrXJrpQfk7kBNiMvb3EgHEI2f31uHBiuw1DDEo1H5hdu5D+n5BZe4ALD9rdqPZASxeSQ1IoWwf3xNdvnwiFvgbDCJtlWagKeNCY1iVQiGLmHQrhxkrEBpjiCovvFq4uveotI6zskNuSj7bMlgGUHgFqvNj23XnixoTVdY1oCJNRccXlP1M+GIUwWkSsRTJ4111NX+EKFayd23XPajC1DOZcT6i2sJ5BltaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAAAAAAAABjeLxuNwKjR9BTHaOdJlGt4pRQaFtIovBFG2x9MGiCQXNxcOijshpq8NXjXrI2zZVoBsG3k2bX2LFGNrmfHQOJZJH6ousbnX/PICO5002623D/pvZvVbcOtYNfRYFZJgVYbBoC892o6aPLGbfCy8PJql2lM1WmYrwPC+UPh5bWFfQzBvprg6mRG6z55/vZGj8xQyWkh1XK4gWfqJx/cl8F" } ] } ], "Blockchain asset updates when the first mint gets rolled back should delete the asset": [ { - "id": "cb7666e8-906f-4536-b78b-40a8df88176f", + "id": "46b13e94-4355-4138-a6ac-d8901212c5e4", "name": "test", - "spendingKey": "86ac4a7def2cfb6ab787126b75d9c9b738d612fcf3a4ddabc525e741dce8d721", - "incomingViewKey": "7706afca37536d546a727f4df5a1da5e15906bb2c2cb2b4532ad7258b856ad05", - "outgoingViewKey": "fffd88542f3c61fbc9722671f3d942933044488189c5a04b8b5acc50137acf1a", - "publicAddress": "61e536f9bfd0a54f525776743b6f7a30b8b5f883359c1a67f40d215b2e99d702" + "spendingKey": "69f37858093fc4a1d4cfe0b07837989623b7156fc81513a1252cc1bbb53e129e", + "incomingViewKey": "0b597bcda6ffe2edd0c37307afd51f22349e0ec7c57d0a509fab37f961ada903", + "outgoingViewKey": "212b03b6dcc64a1d170db7480bb25ae65f4d3ce07196da33a1dc0493b8f85192", + "publicAddress": "d9af0bea135f35b41e64e6f5654841e963f2f459507ee2a6fb83041661da7a73" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFLGr8aoqjYcyGs3NHn22gUpf31es5eIRKXbYieiVW72wSBNSMU2M5+RoS8UuarVIbs+gufs5L9+40FPE+gu+jhUtgpBve740VU1snc2vhhKTTFT0ADi/OPAiB/PBmZRCy7tN0d8faz2/G7nHpIOPMzTWsF7dnDVdOOw/O7p+y6cD/H2vzqFBhM0TFrM6XqLZsi+U7c+FdpOKf9sUB7uEdnAEeHm1XMRTRxj5sFbLvu+yR+m0GZkHQmeKlgWjZ+cskWNNiRKe1A/8I/ogjwTznCZRjFvZo4A52l5FkFRYh0Q9uJzx6qvzi3SCkrRVqrX62JFZJTa5sKnJQ7Opsctvoqnp7WKveOnxP0kCkj7NdsazungUrQbBt7hU++oqUQxZelU64vGKtEgfZvZlfz4vTVKASSvqknOFoAbbM8S3noB80FYI4vuTyiEmlc7gB40s1TJCizXdmo6xeb0yn/DehL8aLOD9jB2ukVm4h/J+prXSmZrk/kY+FiuyeQndp43IjT8N0sjHBtQg/Fouqi4/wI5MlV3BIpcIaVKjY/Y0AxYEW+Jl7E2nmSCd6gszM9tC0fUNrdojWyn1YPGuWwBZs4mkFq1DYZ1cP3GvInCUfN7xHcMoVps5Z4ESvOv8mQT9+G6yvYjYkQgqp31gbs0jr+qV5+rhZfgzyPut4u5JFDooyr86rad0wRB8G5tI+WfNb8INc6gYnAfDHeIvB/j70maqxqQTAvDqoR5tJ1j99cNGLcuSu0g/AguWz7W4O+mGvHSuOaAJRss39gnrAE4r5NMfZQbcH+V/pC/mRJXd2d0hcr/C14+NGiGtSkt/wgcvkVQVP+HQ7XEDHb3u6oij+LVH8nKEtCGsDcixhJ4yCWVyfgxbYTOig3+EW46HEeA5+7ayvWCqo0L0J6RHFObdgj2Am60L6lxwsrqDLIjlHqqPFhgVlLS3Q7c3xQwSBQQK3GY+JAWBV0ReceX1lMFp8tLVmJkTuRfF2a8L6hNfNbQeZOb1ZUhB6WPy9FlQfuKm+4MEFmHaenNtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAABuKCzw2b7k65UgFfSrqrexi6sU20kGYsMpf4/eLRkbUnWhugwqhv8bBRUdc96Za7nY4y2o+8EH3j5ZgIM+hYEGZnqahEhsK3Svur4katHy7Vu4Zsuiif6ofQZg6bbVsgVWfF9IiQD22WVg9K6DRBJtpclE/d32C2aT7d0/Qnw3xhIvz7ydrMXWuKts2TSRC+z3NjUrqcMorFchwHeyP6wJ" }, { "header": { @@ -1448,15 +1468,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:bxSkHz5DgS1PkdrTThBZ4sTxrXZHhDk+jB8XX2KBxhM=" + "data": "base64:NXU/S/PwbcpPlT/qrGBkf77wjq3dpnVBDYh7RNTfjyg=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:AOYm3zuMPShoq0lhgkbbLUlrW7ywK7mqitAEQ0wqTeY=" + "data": "base64:daLcqzjbGlsersI+Vg43ZIhqyTri4l7GwFwkVpEtagE=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470845500, + "timestamp": 1671691620847, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1464,23 +1484,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA4GIJBb/8kNWDnRIiVKCu0hj9SnAi2jnWwVDibUNmzueD+Lu6TVzRFZlwU2Hg3XmcH3LchZN5mEDXH9vPSbP4z/OuqEuDjae/HUCb1+8X45+QtVa0MbeO3UrIpJMUam54ZTmQRtD2V6In/1u0R3VmsFVuuFuQ7ER4dU5uwb11TW0NipT0SiGkXCoHnWi6EHrk/BG0oFeagms3idi+d+CBgJ0SSFkUvBkyfrQ3TlT7AFuZhvcFDa7qKdQTtTRSSkwcxkOEVyYWeS98w3baMLHCgX9AmJqKezCFbuE/xigmf1icEfpspTFjJ8Yt1db2fPK2vLCaDDttThLSyFjXDjlQD4lDCHRC8adTB29brMcZ3dVtdqZKPGacAJh+PFQJrjEv5FKHRG6e4a3VC4cNQ/iTwU9+dehuhhdVt5na6jGTx7qGEXNDqxa8P7O2ZLvpaKqBcSAYOQZRrDhAKOEar8QLAKZ2cqLvtth6iQZWXPRD/eOJ2YXwAA/92g5FBKc/0u4aPVlIck1pXq6GF0lWxAUZ7O3tgQJceC3mXhpqDrv7DMGojmYuvTLCF6rIGmIYoa3EKHlKyTL5VdMaRuavbpfLsgZTbNQcXyIhInANWLqONDY59gBSaiepp0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw7ufRbPMF8QwYxJ+YDXJcqQvY97P3thmSMBEhyZrLHZzCiQItVO4y9D6f5L2hcQNy1k9NRZZB+yz+jYa+Hhx6BQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAvjr6/GoIJhNRz69DWIYs6F4D1ZXaKOj/Ezr6plI1OUijtwebzfb0SJ3uzImT3sgxl1M5+1AYF3R9ERL1QgmkHuEU9dY1v6I30QlK3LoSnVWEwjDuAdqu4St7T5UB58UqcmVALnpKrUcMRanZSRWiza6DUIIPPeTllvTkbNYKuN4L6RIkjVRJQkC/HEdV3+b6nqfQR4/Zhx5q2hQ2XSCpEZFQ6H61cRVUO25VIeWGHl2Y2MpQt9CO7eyN9WFwixAy6YUeDZwE8cmzCRi3vaoC26HztVVXmMFcItgF4+VxibXczT0jisqg5NHwN+iPSL3FZQ4QyRUWWeCR9/eO04jvlkfW0VKS/J6bkemdXSoghgw3I8ZB4tYcSOvmfmeUDy4iVvHx211L0c7s59Lps3xDWfBVjSjgnCUc1c9NUZUKmagVwtFsQOPf2aq9TMEaIR+Mv7M6NVh381p6tDlC1dlx3xioVzBfhdwwCS9/KxkKkW9Z3/ufezIPRYtRwCY+Z6XEMdI9cPgG32ddEgSR0iLsvcbabaMVpY4pRu7RPQC/GfJbExIW4iWVdx3x7w2cRa6IkiXk48z3Yzbl06s+bZJMrqHizV7wBK+EIb9go8Pobzgn/0zyYsTto0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw17WE/+TVczzYnESLvQHH19eAbp+18AihglnESiC/O8l8J9ATi0alSexGUbF0OYpq+gPekwpITp2Nuyhqi+hrAw==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnAFxz+fnWchEqLwZ7QL10XCKasJ0PjjB+09AlJVEcduv8+DIECe5bZj7DURXpOMBw6nuWqXqPegFS79OR0oamNlCZXwqT85ZVBB5UmyQoJuIvSpM0OXzlUxG12HuEsI1++Ef2FLbVW0Dd3y4WXeRGw/kVQpHXf74Tkv7+tZ4kRsAEtevM1KyqL4CmhSccSLTgN3XT5kn8hCiWbkveGDx78AK2qkh+IRAPzvfOCffcsCwEk54IlysyH4Gg29w1j4SsWry95lCGywiNDYAVkyJvVdbEUSPjB3GXw/FQ2rxJjWbabchU9ZnTkY6RQR+t8hb6NraAyf9Aoox82M64ZmIY62wdGHGE6nzLpSIhvedHDrK76kbusVoYea4bPOd5Z1uTCS44/3Vw126SHYod3s5ox9rCfI0yitpW769POWWpFJ2igrBhcg9qXwmqDxIf+mZTEN42nOjDCfzKvVH+RxFuGcNiVe3HbnT38SA97dMd71RR670F3Nn+oqWD31eHP0GOnrvB+Po8Dm7h/+pKe1m8lHYA92YE3WnE2RaytHupMBt/lcvAQqAM5trWpdwVdisT5FC2Wfj+LZVniKL1PKaK5g8cpz3Raj4/YSpr4FcfZgT+BTgYEVIJriC0z/75GoTPZ3w0BN+joy+97Ca1S50oZCipuZCQwyzAPSFsYxZiqMOwMUFfrwlT2v+iIasl0at2LgZssGgUbBBErRid3+vKcYww8pCwDg5jmZerq8X/hYaCOIJak+TN3y87fBtOvMd2sgWeD9YFuYjlH+oUvKVVVugcVaVgk4hs1b/r6SOmIjKAqXjwpt8YBvnHul24mo/CKC/jDmfgPTlv3XI1dh4eIdjG8ZpjBTTA/50otKe3+EtPp8olHoCqaIDqN07C3XgtYKliYLa1zsNtFzLHDx+9VtQbGaKj+kpglkGMJbnPZKe/y40sUvfcTXAM1jRMYl1Rz/ppPaVrvg5ANmkmXO5r6krsVnGJFpNYeU2+b/QpU9SV3Z0O296MLi1+IM1nBpn9A0hWy6Z1wJtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCgAAAAAAAAAXmrz97TzhOadNWjjTNbqZ0gMxoCLhXERsGoGtEjNaPKlbGCdca2oYKIJtsm/LM9rHG0cZ2oqsJOUwCOb2g5xbePsZ5giFyn6t2W5HpQjo5kkR4pZdPJCVh+7X2J2o4wR9UiPmRmRWvXl30H7kh3CTCuwP6oUg1uInbGukz9/J5AI8ew+pXE5JJIwCwg8rY5I4gVVdw9xsTlScIRGueD8B" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFLGr8aoqjYcyGs3NHn22gUpf31es5eIRKXbYieiVW72wSBNSMU2M5+RoS8UuarVIbs+gufs5L9+40FPE+gu+jhUtgpBve740VU1snc2vhhKTTFT0ADi/OPAiB/PBmZRCy7tN0d8faz2/G7nHpIOPMzTWsF7dnDVdOOw/O7p+y6cD/H2vzqFBhM0TFrM6XqLZsi+U7c+FdpOKf9sUB7uEdnAEeHm1XMRTRxj5sFbLvu+yR+m0GZkHQmeKlgWjZ+cskWNNiRKe1A/8I/ogjwTznCZRjFvZo4A52l5FkFRYh0Q9uJzx6qvzi3SCkrRVqrX62JFZJTa5sKnJQ7Opsctvoqnp7WKveOnxP0kCkj7NdsazungUrQbBt7hU++oqUQxZelU64vGKtEgfZvZlfz4vTVKASSvqknOFoAbbM8S3noB80FYI4vuTyiEmlc7gB40s1TJCizXdmo6xeb0yn/DehL8aLOD9jB2ukVm4h/J+prXSmZrk/kY+FiuyeQndp43IjT8N0sjHBtQg/Fouqi4/wI5MlV3BIpcIaVKjY/Y0AxYEW+Jl7E2nmSCd6gszM9tC0fUNrdojWyn1YPGuWwBZs4mkFq1DYZ1cP3GvInCUfN7xHcMoVps5Z4ESvOv8mQT9+G6yvYjYkQgqp31gbs0jr+qV5+rhZfgzyPut4u5JFDooyr86rad0wRB8G5tI+WfNb8INc6gYnAfDHeIvB/j70maqxqQTAvDqoR5tJ1j99cNGLcuSu0g/AguWz7W4O+mGvHSuOaAJRss39gnrAE4r5NMfZQbcH+V/pC/mRJXd2d0hcr/C14+NGiGtSkt/wgcvkVQVP+HQ7XEDHb3u6oij+LVH8nKEtCGsDcixhJ4yCWVyfgxbYTOig3+EW46HEeA5+7ayvWCqo0L0J6RHFObdgj2Am60L6lxwsrqDLIjlHqqPFhgVlLS3Q7c3xQwSBQQK3GY+JAWBV0ReceX1lMFp8tLVmJkTuRfF2a8L6hNfNbQeZOb1ZUhB6WPy9FlQfuKm+4MEFmHaenNtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAABuKCzw2b7k65UgFfSrqrexi6sU20kGYsMpf4/eLRkbUnWhugwqhv8bBRUdc96Za7nY4y2o+8EH3j5ZgIM+hYEGZnqahEhsK3Svur4katHy7Vu4Zsuiif6ofQZg6bbVsgVWfF9IiQD22WVg9K6DRBJtpclE/d32C2aT7d0/Qnw3xhIvz7ydrMXWuKts2TSRC+z3NjUrqcMorFchwHeyP6wJ" } ] } ], "Blockchain asset updates when a subsequent mint gets rolled back should decrement the supply": [ { - "id": "91b95311-2744-4cc3-92c9-cba3cb682b39", + "id": "880461dd-9751-481f-aa41-fc47b0cbeee2", "name": "test", - "spendingKey": "a03cf41e96cde2e708512496866514b4bcd345cd5b18cf65364d3713d8599f21", - "incomingViewKey": "c35ef3b0148115ea40091cb356bffed7b0ed9916bd26dd3b75bc5af52ceac804", - "outgoingViewKey": "ff1455dc128df336c2d31d29a17ba44e6e2cf151a587a65f49c150bee7b59fb7", - "publicAddress": "ef8d7b8c1ab27225a9954667dadf801bb38c4224b6160cc0f255b837a1255d3a" + "spendingKey": "7e120ea5d5a4c01b71fe451c3da624f7cebfe31682e34abd8f2d069650ea2895", + "incomingViewKey": "fc9365825177c5b711df27acab0ab893ca6eeea8355e3ddf6f1a4f89a481ff06", + "outgoingViewKey": "709f6b49d32535460a6bfcc94dad4c87cc1d4d95d81a2c55e831c078801fa4ed", + "publicAddress": "aacbf162b34e2f78d3b67d645a31119cdb009add7dd4eb366f5aceeed42399ab" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwxkbynh/CvYA8VxyOJtK3fDCxmvOEJnrMRqBARrvfui2SynLaq5OPcQEk6UXpZ+4tu3GUAhRgVjJ//9TSKTCAWkCA22omJ63lfEaTxOKV6WzWmtLUFwddTzW4kiORkCzCrNbaGU9gaysL347L9XuH677nFhluMS5LgwhB/Bmar0XoJH8vdijDJOGiOfTB/P49U9ylYDGqPjgsRuvrEXCMyoqIIX9tEONGcfYElmPuNaVPp3nRkowfbTOFLLsxcoZAEjFKfNmtJoxBGwA5iCK49/WmWsFeRBWSjwVG69JWJQ9tmwjIcHacbaqT0HHArw/C3og8/rQ1ACFpDR7rWSsAdHKR0cy9SnQpGeStejWVIeWLZeLVHt0UqrsgIMdLyw+Yj5lHqEsqZQmOR3sBhLBsXsTgMaZNQeEtvvRKUvLT0s2Kh5AAwm5mXiJ2yLanUBJkOjedJe+g2L+0/6Z3c6nmvliwb1JeMo4c+H79Tg6E/jRKqXJWFChlPJnHrBOTMAqGAtekg7R7h5jZ2z6zfgStQT+bleyKM3fnkP4hEtzbNcnAzBY9ZdlliKrU8hzNej0BVKrYNNVzmJzqERwhvhOQbF5bvcsBWBE8WykKQdrerbcDHLIQBap3AUrQD/8XY0w/mBdMwfivexxjPtB0FlXn2lQyG0fY5Qkw+qFiVIyoGIq4H6FDuMX4+0hlG3/nsjkZTJG9wqBh4aksgnBwPDK3k7eh47+q776pRliaNzVh4wRhqdbr68YWV6AzAnMWUEq5KMvQCxDn4O+tvw9FrD6O6W+LbjHwoTWlePXiwH5ng5GhWBRg1hhjUZj4UHARakDYBMo608w/qFDJoISx8jPId0kU/WFM7WQF74TJ91q+7b1UXUopldTShFM93dZaDnphTwMMAzAepJD9XUiwNnqVH5riTPKxu7mhaTdB1WqGZBGYHDxN85peBURye6j+LC4Qv7U2T3rJBo+PqhyqbotB+eZ7npPGygKqsvxYrNOL3jTtn1kWjERnNsAmt191Os2b1rO7tQjmattaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAD8R2HDqi4RvJ0CLJfH16BeQq3kYtkziv1Q2GXCsaK6S9p/xRGFkcCPR3m8ilDyr6OzEdXBKKw4wcfE3cN3T0SSMR4wDcAwh2WtT8hylkrwYMZiHL3CkoQ2bVIi4vhjcQxpboOGlgp1IQ2aMJHarYHKNrWyCN9l4joCj8E9uo1dyUag4LX0hCXc8MYsbWJxmI2qO+usUBJSk0jq6t+6sFEE" }, { "header": { @@ -1488,15 +1512,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:e3Ubwwt71Rjxpd8rZunISUOiJ6yEd8hlbZSV/194vRA=" + "data": "base64:/wXPPTQqL0OCnbYAns/6DI4sd+J+bnD2T6oAmCaL9A4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:FNkdNZNjPd50yyz+l7cdfYVrq1DyCHgTmDJzZPqOgp0=" + "data": "base64:bd5m3kXk1ac0HCQUIvOWX/Owj/H7FdMz4oYn2te8KIE=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470846426, + "timestamp": 1671691621757, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1504,29 +1528,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAPyuEuPktHHp6PQDvt70byXoCBRQ4W1FEeX8msdzo4oeoaHSe8Lp08334GgBBG2PWyLUTIYurCHvDoQSztBvFuYCt1EcWaJx+ejcmPQAgIn6JcfEqyoYBLzSfFj0yJyd44YA4cggfnYvp2QN7a0sxIlG7FRMgPSJo/GWKL569hf0VjfXkqajWetF5Q+HNclMxIB1mT4AUJDVPKOL2Kmx31aMUAXcQ5TjgTIXbDd9An8+IPyJpRmQsu/mXynFMSbdjy+HbegaSJvc1GQ2/9J22EI9zmRByHB5cec/NB3SWHgp0W0PQSuvpJIx89cOvHN4PiYuUpbd9RmUjInJh5e231QxZiPtwoPNZQtkXoCE0SexQviTz0rNdt8OJ/qIMBuYtlFfk/mlasfo9W6ujavngUHqNGchJiqcJZJqL6wMowRYNYyqlINvLIFaX7gvPSbEXTzarnrX5M1cbt/l2qKgTBtyKCmwKHJ28zZmEul/yHGjZrjlEqkrqPavpWNLlbxOvIy61Yli393rviWj2S52NdmpNeLOqsplVfh5o2slUJ1V3CE332VjDPEmkLszL0EWbL8dmsKBHE4x7HEMtivH5aXCR8kUO8NW4/hW+9DNuU507bzOf7kn6qElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcrqK9Wc74vA+VDo/JdX/dNknn2jgiIDanI9Mcx8CEVYL3hMyxaqlWe1PvdHtmgoNE2KDxOEvbepmFFhCDAj5BQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAZCD1bznog5YSOUvebI0VBi1ZdjDG92V3sen1JOfIQaG5M6x7+rqxS+GX7/zltlFAHSfZuGQSDCZ/nyB20dRyfOgbyfXNAjh1hBP8ZM3bfcild4iDcEyDAzWht6Pq5inogKjyEdoCC13sBonX+9AWwsf5n/oAXheIxpSkqhixWGYEdEEM1dJMchaxUMKYELhS2DDlp0moEczXnJnSfiwozbHvmudAA8gp2pE1LW32ZO6PIvvLG6tjEURITKKw6+XqTS5CY7y36hQcQC0TDyi8wcoogrEOLYPsrqy7CR9RxSXkdXNDqeGYH6SnvAGUn/3YfQ84UzIvWjEseTHsuFUaxtpluh6fEl58qkXqY5X64xFMMFCy7cCwtmBZKoj7zaEr/2dAqypSsl2zZ4Bq0Fj2eg2s5Dts2KX0vBIrdl35iSns6cwwvKtzkJB3QAaIVVGVnhhsQLC/iPznBlELxdc2f5KF/MZmz+5yCT1afUBBZB4jar7gx2/rXBOJO6bX0zqzUnjCGIeSwE39Kd4wRRgfESuFi1lSLZltfj8mluXIRhY2fpL+9SAwQl17doWGm3nFgVX0Q3KN+FmYuKCr7SFQIyaKzlFegAXta2eauAj1XHKySjz7cF2O+0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmlomrTgu9MbfZvkTHcg00WAIe4GrKAL/wFpPvF2yxY8obghqYb1dVTMpoXwxIE3gmmRTZ/e/8Z7QavAcqaBGCw==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2PG1TKbGSHGa95a+oozc685UHsLWuQ3lCqFIbS3t+6ux2+/OxUnD7CbF9Ezes5+qZUUCAt98RqicXblkL1RgJovm/m1vi4ijIyWeOs8k0rGND/GcUbhe+oeoiP/1Kl/rHuxtIya9Hazwb9zhBKtPwu8GhOCWzdJp66s3o+shHAYI6H0h3wfV2czSq/h65ORZbYu6DDzXOlzIAtBywceZk4kUb8l0JnkYVSlJk1qyqqqChMzMpmUpmh0kPpeA4IjbczMvOpPB+aKsxwbdgwkEgFLwiBtMsNr371NEl5iUbAgb5gHCcY8LGP8kxgpnZSVzerLvDRA6825zyu7tNjR+KUVIfkGR4WyS55Bu+bcmmj2ZTWLarxYgzqjfqvt2QGobGLaBXNRPHOOcLuWYtxByMdbZTIl1Uq1AJFqpftM3wyvo2vjjRjvTHRcW4Fokwjjb+v3nOv1GT4uUhU/v+oTzrmPju41bUEO/rzmoLZNe8n87PwH6PoXfdWi55Ria/0CDo4SuEWjkmq2cl6qFgrJWxwmfQRAw96Nnzjp+0MNaZieC/wts/zl4IxrvGtFRInXOmf0pGwA4+8JVzlMiXvsxMjmGCvWmV3SGQzzlMVGP8ZOMoQnZUPj2zEjmP6HU5FvsWQ3oJXYOqL0NlRFOIO/Sw+mo8Spng3LZIb+5gDSgu45GsOoT9YppgU64zN4b12LFkCW2A4rkyNVSIu8aI3+7kUsEK8+X3kMCroYP4/hfbZuQocEr+UQn1vdB8BsWSAbvnx4icCIURC881Lk7rYYlhYRxrhafT5YcgSEaZpkqmNkdyPDhwSjyyHmqojGO5VAaoITDY7Q+CB/DklE37qySIqQxBkDgQWVEE4ZTy7PKhm2gFqBcriWzQsQh9TWmcpeKX7TC28Ktj2TSRgS/M0TW672YiTkFWgF5s+wB8cGAJLlD7OC1PLAzZA3ZwxV5jt1gRIIIIwTKL8L4yN9ol4owkNXjadHBXc7g7417jBqyciWplUZn2t+AG7OMQiS2FgzA8lW4N6ElXTptaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAENHe3fNBRSQ6hWQUPZtPgbl9XVrvXCPlOTzqVYk7OxtHakzttI61XTgVvZAf+5zRDWXZIERTljO5AWIk8Z1GFQd0nk9C8M50Wx9cHC+qRwgxYTyi4ryNjL4TR/QcuwALoa6r+4vY4rq6EGVQzXnW8t1WNEw8I0dtZfSAy6SA3t3ic3nQX4tW0BrLwO6ph3o00v0h7MTMOx01DzJaaN+UN" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwxkbynh/CvYA8VxyOJtK3fDCxmvOEJnrMRqBARrvfui2SynLaq5OPcQEk6UXpZ+4tu3GUAhRgVjJ//9TSKTCAWkCA22omJ63lfEaTxOKV6WzWmtLUFwddTzW4kiORkCzCrNbaGU9gaysL347L9XuH677nFhluMS5LgwhB/Bmar0XoJH8vdijDJOGiOfTB/P49U9ylYDGqPjgsRuvrEXCMyoqIIX9tEONGcfYElmPuNaVPp3nRkowfbTOFLLsxcoZAEjFKfNmtJoxBGwA5iCK49/WmWsFeRBWSjwVG69JWJQ9tmwjIcHacbaqT0HHArw/C3og8/rQ1ACFpDR7rWSsAdHKR0cy9SnQpGeStejWVIeWLZeLVHt0UqrsgIMdLyw+Yj5lHqEsqZQmOR3sBhLBsXsTgMaZNQeEtvvRKUvLT0s2Kh5AAwm5mXiJ2yLanUBJkOjedJe+g2L+0/6Z3c6nmvliwb1JeMo4c+H79Tg6E/jRKqXJWFChlPJnHrBOTMAqGAtekg7R7h5jZ2z6zfgStQT+bleyKM3fnkP4hEtzbNcnAzBY9ZdlliKrU8hzNej0BVKrYNNVzmJzqERwhvhOQbF5bvcsBWBE8WykKQdrerbcDHLIQBap3AUrQD/8XY0w/mBdMwfivexxjPtB0FlXn2lQyG0fY5Qkw+qFiVIyoGIq4H6FDuMX4+0hlG3/nsjkZTJG9wqBh4aksgnBwPDK3k7eh47+q776pRliaNzVh4wRhqdbr68YWV6AzAnMWUEq5KMvQCxDn4O+tvw9FrD6O6W+LbjHwoTWlePXiwH5ng5GhWBRg1hhjUZj4UHARakDYBMo608w/qFDJoISx8jPId0kU/WFM7WQF74TJ91q+7b1UXUopldTShFM93dZaDnphTwMMAzAepJD9XUiwNnqVH5riTPKxu7mhaTdB1WqGZBGYHDxN85peBURye6j+LC4Qv7U2T3rJBo+PqhyqbotB+eZ7npPGygKqsvxYrNOL3jTtn1kWjERnNsAmt191Os2b1rO7tQjmattaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAD8R2HDqi4RvJ0CLJfH16BeQq3kYtkziv1Q2GXCsaK6S9p/xRGFkcCPR3m8ilDyr6OzEdXBKKw4wcfE3cN3T0SSMR4wDcAwh2WtT8hylkrwYMZiHL3CkoQ2bVIi4vhjcQxpboOGlgp1IQ2aMJHarYHKNrWyCN9l4joCj8E9uo1dyUag4LX0hCXc8MYsbWJxmI2qO+usUBJSk0jq6t+6sFEE" } ] }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf6MOWeKjaxTBMF7U2GaPDJZTlD67XCGLKuT9ybzY1eH+Fetmk4C6JW6IgXZlQYGXgjUiD4uqSHJ994GVLalaodKVhUBECPIeGyczLa3XhqNy2n/FRUl2IB1piW53ssvO40Lo65LqyeNLSl46gvk1cHELChamlZ5XVLiKCuzgMMLHsCCJtttfIoUYfpbojW0NSePy3wXY7jHavmd6TtAfVFRLUdjYdc9W/85CxWz/luyT9tzSV56UYPMJmnnsRd/d9tVTA5Vm0vqbVcc7Inq+rcDuDrHGPFnoRI5ub44huTfezgL3AxJcVTlA/6ANq9T9V9QCGxLhN2Tk0+Pu3uEOfJUJxpIluDmiDeVjggttDOVybYwOvJyaYsViy4HaA0dJZ9ci+hGLr4By+7VgCHNStc062xfnYBh5v+fqGL0vdW1rnPR45sowLc34rRiOlyrTNzEcvhAaHG2bAkA6RVGceoteDx9Ms2P1tarbuL1rblICWI48D+U0ctNFEBxn2cS6aQ8XaKs0rj5hGRiSttxXQoKnuTzVgDKRtwNkrnCaBfG82vtnQQrbPKqaxu7lbrTfKzEabXfYbcBOeE3ocS9MaohonbG38ZhrnmoF7kuussl4w4Y5m5Q8gtIP7hG5Vr2B0nuCu9nS3PBaJJ58LsZaW5pz3t7sjrbG5VIVV0rYZwqUV4eVX7UktvePmCPbeR/SQGluZz5URE7HP0An3Rs0SHb3Q3OLMnmr59oa6g99Sv8dvKNvznLi0ehKC3hN2nKBXy6OJB3D1UmA+1LV4X9rEK/29csT/q4qyNQdVV7CUTIB+qvfNgUhc7tyksgPHAnBiIT1QVgzhMsGsYCfbU/KpmPXG26BDlsCZUCZArtKNb3rlXgI9RsjcSmiRzMFYEk5B6N9YWRyDGSxNtVq0zsqhpCM9QPqIyvsvOoHTaC+vRIwMKuczOHPmFnKu4K6KdmW3H4Z1l1aAJ6fy9N+9AzGt2h2Ebd/YPjqsvxYrNOL3jTtn1kWjERnNsAmt191Os2b1rO7tQjmattaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABaTzx+rWcxfcXHnFHcWMG7VoWReuYy5QwUaRW08xXTl4Wutr3fnDcaZ7Ae8QVYgJHHKVM2fYDq1QcnLr4J5/JKZv1eVwJkP5F8aNWKDRShEFZM7rBJNZGasthn4YVA8AY4YHd3FlR+erdxA13UzFvp5Wb4Nj6GxHP+V2xW4yQTNmEuzmJCRuhwIIVxiLTf3+pRFnbCLzAMdKiAGWTSTRYK" + }, { "header": { "sequence": 3, - "previousBlockHash": "962F71DD8273B1A80B7F3D82C76D3E3DF657D05076C9B2241516DFA40CFB43F7", + "previousBlockHash": "EF08E95DDCE6FB2119F305EE34D00913CEF3B0D5C45E979538C3CFBA82D54B93", "noteCommitment": { "type": "Buffer", - "data": "base64:vkCDj3OQ80q9ZsrPLNDNF55yVtiSVCe/BzyxzOjAYzM=" + "data": "base64:1/hGgHhMUHWk4q1MF20GpVGNfR4uD2PAHhnQOCkLhjw=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:dFcBV4jcTzCFjfiBMWMVHbIgnHlHx5QzEjgvgLijNFU=" + "data": "base64:vbnVkSyILkzNukQhCFDuzsOboGeuKMVIEonbEJnZaj4=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470847241, + "timestamp": 1671691622604, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1534,23 +1562,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAahR75gLDxXIQl5WV30gZNu+2GvW1nm6pvL8+ILJfeRyUNq1zDE7yROqBkJBscz/N5tG0mwrqhV+z8CKuuJWmizrrcjlb3rKN8cN2X7pZzMORO4El6ucHWeAUVziOI1kSZyCw/LviA74jzZn+dslW1sQAvu1itF21rskG2QPpGKMWP+yKmbfWbhKjXJ1tKi1jB2uVOUXnDImoBuEAWJTWvnHjG3pZxwo9WbckbghssRaHYrzwSRFaJ2ePeE9Zh41DL6htlF6QVJ0Xik4OOC5tIs6mwScJy9Q1MvOUsWg0o0vGwTrmiszij9vJPUN1+K35DfIS5LShjEj93jP4CqZ3ZBxBeeeg7imKbnrf3geuxdSkdDQKju7HllLsBFiIrn4ZuEHDFdBUzVtfHXOZF7zUV7K/A1dIRzoXFARPFQZsdQHyXtE+3n9GaR71AUXdzKKHq5F97Uk1WmSR6I/rQZx0i1JtDofKpbgcdbrICtJlTKfq6jT5iYi9JuHTZCMUYmt3snBdQ/br3pIjbcQa2LolPOf/Lm7twAxutURt0t+4VjLp0s9U6bZD94V+ONZT33qvQeB3JJoIBpOMPpyC3DjEiwn5KTEvdIAguTuDpu01NaXPralSTME7DElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwjwCwfqMqTfdOVUeA5cfdPDzkgV1dkBdFakKpmGju3znUQtlMeUBDmDnmhaM1ktX/vYXJZ/Z+yxLZgSD5NnpqDQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA3JtiWZAXcByNYg/om4J+F+5liG3XXtQBb4hXz0pHjqWKbEIAztACN1WlcWFE4lUxA61YHUquZW5JvBqYrQrQAo+yKXv3oxyRxKvStIvSL5WRjMqyk6V8bXkG06T0FVBqYbMj91ZqTKZWOR6boF6Cn+7X/NrqY7jQwOFrTAntUxsWeooj+xPRTZSBGdsy2ZmVVu0zdRZGE8U/6Ic4iAz4QjAZ1o1W6YuF+ettRdwmtWSVyughXoa4iiXFu7LIuI5MPa2DBQw/256cSSsZEm0nhb+RbeVGcIPzkwgAPFbc/0yUegE3gzFFymaGHcgj2WD1/UutGyp97Znp3CL6ZaobG1P6B0ORhWfeRlmBH1rkQjz0GlnVz/r4TPpNJlnHL11fU+EOK/eygsR/U9WjbxaL4MDeK4NOB89k2fNa1vj4LeIA3HoWofkKKny+dbvwGtdFfa7UvwixYzF+/EmfNiSYw+glOmwZYTZkwGIDSlwGORo8B8cpnm2RofA+MO3OH1i6cpELYF16e+OpcOifjSGO7DDa4bw6fdSd49aiiAul6X8G1ljPj2ytegGP+jnQuif1ZNrxgI4KMKMjBiWkW2uwCDRUxnGciOfsDMq2eFKWLlNxleoOHdKglklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwvEnj173bCtVQSr15qqTzD4bqRgNwSJUCcomLIDCncOa1HfAet46NNqz7f3hHGLUbcor9HGMKwHMmDI+6Xps8Ag==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwfd9kNlaUso1EnC8LThlKfE5tSthmW+Mr202KN89p6lWD4OePQdNkS27ilQ2vNdjUsTmroFG3p+M8YOZwW8QGPc6JkoiCUWagekPDEwEGKHE9Lg1MLPlFA+2Gqccb6nZaBhve7fh9JExNyMEEv+3AASwkPcOkuWNb3JON4UP7QGpUgeyspWfcUzZvXib9/O0BqGezcmbgVXHo4+EqO+IkMg/GccCToK6HBdc9CC53+OGrGqIRCZPxYIDJSwIu2otE56znQDhnUowb1JZC2MAyFIrIX4GGj+MDZ3lywIKu0OikpvFnH+TqcFz1xdPX14z/P/a9WJWaSpcRxwA2frXefIoFnxPTkijwb8+LvOZXRG7M2enTV/nyeKLHrdU6VONRYzKSv++OPP6P+IZ9V40FRjToV0fWmSKm6KsiA+0Y4L4YeYhL5yvTvAn45vBlvzdKwLknWgKuoG+IgNx+S9nX3KDxSP43FH5Eh35w+n7Ox0mJIJThC5mVqDq0V3rXJktj18NFLmRdDqQegnLjYoQHkaACHY7sjEai0eErK5IKPz9ydJcH9JoBjepBHFGGS8/8r2ZXOaxKvBOYexPl6Vngq6CMh3OuGHxHm0aFVgxIFpJdtXsvkPN8WSMdy/j6Qk3//tXXoyd1gjU6CWGcnLxkjztLEVHFMPChKSkRGss+1Hxec1Y5y8rrcJbncH4byf+rbikysxDM8tf8c8yamG1mHU9JJxaZbwqk8kq+oFEnfws8kIWXoyXMc9z0jq9gdIyKk3xLMFMxDjcDve5Vm7TllqbKJD7mESgtzx+hU8EmoFZZSkFu1P7QzXLVu0hfWhA6+dSNd8dYoDbMCzRPKbMxU2ZUptRzO9GNMNNiAimlbpf5jFT75wCiJWuk9Z3Q8U+5LwIjsigACDtkLV8+iIBh2sqig3T1++gQZuAjEfFeQ9RFNA+E6zZC/O2aCIb7clgqGRT8OVBSzyQ0q4YpL0rqkoxXEUHOIT7417jBqyciWplUZn2t+AG7OMQiS2FgzA8lW4N6ElXTptaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA+HK9NeCXoUjpcOYonHS/3jVsCwmIftADLRrZqdabGqNvP3PwhWqod38XEdEz4MOavfVC35CFigDdD03sEz19wqg19QNXCPX3ACV8uH1AKi0Zmw/LheY/Fjf1nr6nPeARiAzpy6OZDgBB5u8398H0YyMs7XcdiOmVUyNqkvgm1Amet4cA2haJ42vAP5j3ZEFIRG18GesrUpXjAoGB1kb0L" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf6MOWeKjaxTBMF7U2GaPDJZTlD67XCGLKuT9ybzY1eH+Fetmk4C6JW6IgXZlQYGXgjUiD4uqSHJ994GVLalaodKVhUBECPIeGyczLa3XhqNy2n/FRUl2IB1piW53ssvO40Lo65LqyeNLSl46gvk1cHELChamlZ5XVLiKCuzgMMLHsCCJtttfIoUYfpbojW0NSePy3wXY7jHavmd6TtAfVFRLUdjYdc9W/85CxWz/luyT9tzSV56UYPMJmnnsRd/d9tVTA5Vm0vqbVcc7Inq+rcDuDrHGPFnoRI5ub44huTfezgL3AxJcVTlA/6ANq9T9V9QCGxLhN2Tk0+Pu3uEOfJUJxpIluDmiDeVjggttDOVybYwOvJyaYsViy4HaA0dJZ9ci+hGLr4By+7VgCHNStc062xfnYBh5v+fqGL0vdW1rnPR45sowLc34rRiOlyrTNzEcvhAaHG2bAkA6RVGceoteDx9Ms2P1tarbuL1rblICWI48D+U0ctNFEBxn2cS6aQ8XaKs0rj5hGRiSttxXQoKnuTzVgDKRtwNkrnCaBfG82vtnQQrbPKqaxu7lbrTfKzEabXfYbcBOeE3ocS9MaohonbG38ZhrnmoF7kuussl4w4Y5m5Q8gtIP7hG5Vr2B0nuCu9nS3PBaJJ58LsZaW5pz3t7sjrbG5VIVV0rYZwqUV4eVX7UktvePmCPbeR/SQGluZz5URE7HP0An3Rs0SHb3Q3OLMnmr59oa6g99Sv8dvKNvznLi0ehKC3hN2nKBXy6OJB3D1UmA+1LV4X9rEK/29csT/q4qyNQdVV7CUTIB+qvfNgUhc7tyksgPHAnBiIT1QVgzhMsGsYCfbU/KpmPXG26BDlsCZUCZArtKNb3rlXgI9RsjcSmiRzMFYEk5B6N9YWRyDGSxNtVq0zsqhpCM9QPqIyvsvOoHTaC+vRIwMKuczOHPmFnKu4K6KdmW3H4Z1l1aAJ6fy9N+9AzGt2h2Ebd/YPjqsvxYrNOL3jTtn1kWjERnNsAmt191Os2b1rO7tQjmattaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABaTzx+rWcxfcXHnFHcWMG7VoWReuYy5QwUaRW08xXTl4Wutr3fnDcaZ7Ae8QVYgJHHKVM2fYDq1QcnLr4J5/JKZv1eVwJkP5F8aNWKDRShEFZM7rBJNZGasthn4YVA8AY4YHd3FlR+erdxA13UzFvp5Wb4Nj6GxHP+V2xW4yQTNmEuzmJCRuhwIIVxiLTf3+pRFnbCLzAMdKiAGWTSTRYK" } ] } ], "Blockchain asset updates when a burn gets rolled back should increase the supply": [ { - "id": "2b73423c-4be1-44c8-8ccd-6096cedbe6dc", + "id": "12447b3b-cd53-425a-a12e-b45d51f2bcc7", "name": "test", - "spendingKey": "7d70004347f728ebe4030557c11dfa6923e52b6941fb9bde6440234fdc53c008", - "incomingViewKey": "7e7b790acf5e06f3f0c5a922e52de469259b9fa960935572788a9d5d34b21207", - "outgoingViewKey": "12f2aee7c06a26525dc7e0d400b45ceafbde3da05dbad3ab9c38d6eed5081036", - "publicAddress": "3aed5a6e42ed07f6ba061829b908cd9f791be5b152d30c0ab6cb380e71661d0a" + "spendingKey": "050ebcc4e83291f11af929caead343c5a74bc5928b10c0e0e262bb81f1ae85b8", + "incomingViewKey": "c086e2b36e82f1740bdad6a36c44c01ad820f3fbe33e8d1a74cf10963e76d605", + "outgoingViewKey": "ebdaba140f64063e35ae103fbc34b0207fcbd1688d174dd967028c3ef74bbc54", + "publicAddress": "488e9ebaa756e15d2beb74a65f15fd51744339bc22798a8f4e898c82f2670422" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFf+CPiGT+/QGEuDKT0W3PlsxPjmWXAS6V/DT/Mm7VOOCSx+RgOLiVtIso/oFhqwU4BIN7XzQlCwlLGiql7gQA3svAZnF5jh73Ak49E6gIbqITzwk1orylJIvPTpmzhBPCh+Hk22rtzE+dzOj77B9JxqKELvY+zMhLEFM+niMjSkWwCYwxZMXtJOQIz1iLx3bVGbUjMUt8AEqqW8eAg/1Tvgi75vp5aNVSzNIiAdNrG+qmHHuxqwGAr4GHS99JvIlMdL+9IPtqgJ94PJDesytxrUS24kB/n5lo4H+43p1nxrfUWJgVRfqImIffQTvCIDfN3O3WbaV8nUVEvm9DW2qorW8YCWUYMiXL6AfIqMEbzXQul/WfTLOqqMuLPoKUZ9Z3DAjsomgY5UgvyoOV115K8EFihubS/5Qz60bneEqrsrqbOfQNKx9Y+rxHsAb4tTnA76x0Nvdu/aHoc0AB1MNGmh9A24UnMhSCYzgnnvp/EyRLUdPz8uJCryQooHT9aAaVDsMyNzD1bJ7mqqlAoKM6IznMoBlcXNbC6apb7kibulwGkSzTNmq6yUaBwVhDxrTo0etXRIAklXis3ubRccF3XLFM79v+cBC24qVEV/x/nKFMvzyrCRNFikJYVlChbFt2/Whf2I4ZA/IfWyf/kZ7PEVO4DtxRvc9DbrzpiMGWA1C6ZdSmA8E7CbjjyT33lUkOHXebgdm9iZTdk90FsKrYr+wInPSPHlCpLOd2ryDY4PP3Z9EX3R50Q/xgP615gtD/EAKZhruk9Zuk3fcloiyz9XhDj4TakSkuKnZvMDYP6ttttEf1xHnjno3tP6n5f81EerPSd96hXHtpUFES886ZGVNg7Aik3TiCufYngXcSqWBkdSRz5NiUOcOqe+7paYksma376MtJgrUihs6Qwk8gcbkEeba49bZo/WZz0tVLeBmPzMm71YN5sTjbzswVEUUSX5bxFc0kt+0ChK81y/K3Mj7KAET59McSI6euqdW4V0r63SmXxX9UXRDObwieYqPTomMgvJnBCJtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAADMkCD4QF3klIzAczx5kdXESc4t0fHpjVubhDJ21ALpRNNjmLySE2swX2tREsoPlADK16qsrJIbOGdEBXvTj4DOti0STKM/MP17Agw2kMYH2eGinDQyDEEaZyitV/CgMwLFxxCd+Dxe8mCXOMXn5Tcv10+Rb7zOeQqceaqqYrB7FZ3v7CGVYiZZk3YpfJm9sYHMUwXns57RgL4OvV8P85QE" }, { "header": { @@ -1558,15 +1590,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:yc6SX8NjspiP1m1u2RgK6ogCNM3qOflYvvFBsZp0nmM=" + "data": "base64:SwJt0Udvz7gdc4WDc/jeQaZZsVDxZZkve1XljrDkQ0g=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:FxbBR1EBG4wRSLpDq1cxASvKfLeq3Fe+zPBdn/jAdk0=" + "data": "base64:Uyh6I4Gp5/GPf1Ym+tSfLr0rNqFmnfWM+i7hdWjfqfo=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470848167, + "timestamp": 1671691623519, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1574,29 +1606,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1D7+/KZrjB/pa+ch3ukML/5O/rbv4obkzrcmX58jVRK4iSHgXacn8xX34jl9isX9G9sO7wtc9d3itT39hVthyULbDBm3iEDotx4kCqt71n+F4m6Q3R3AnKAnvfcA+d72A8Yy7AL15tiHOlWP2LHv9pm1Q6X3TWYstJOcX2TmjUcVGAYJrdfZ7Iy/NRDli+lV9eCja80nrhNAJlawdQ8sl6t/MZx/FQImN4DkMaI/bueLkGUIpjbaRl2ZXAg+A9wcX1AcE69/zHCszwkQABWJMOcAlBEVPD6otgQPF0h5nGuBdtGP3PwLnoyJ6jPLzc6vn8kxN/F6zMhlja5jDmO4i45FLjJ2p2LaUcbKZZt9nUfa5BmY3O8X3Hd6C5AuA1IxqcX1p4YDe7qR71/kfZk6fzyYX6AkgW9R7q0PbEQIs1t16bLcIDCaJ/NSWifrzMUimlyT+0UZ20w7TLNXZRJka9DubtbnE5iB2XSRKRZAUvNZWNEXmakZHQQ2mGD+4Jt8rKfM8PmI1Z8l1wHFJAR8k6XGayJe9AT8PZ6WsVSXSqAALj9SXmATVvxBjPBS9NHVYsKFCjVK3RZtqycQjfEZGGqwbxGBu4Nvr6RWRR36zj2F9oK/vGunbElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIoX9491BBxlyyJpJoOfenuGJb3rx0KaJ0LUYGJaSCoVHfIXvVorsPL5TvQ48BsnAFY5zuKR6C11h8iHxgJYADg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAedn0C3bDAr3RTq1rcGwfR88CDxERkPViCydxup1RFQK4S/uE6EBg36xlnIX/Vbs7TjLZLJuL98drAUWiy/zbVRd9NAzPVklaX15Ij9ZhPDeGEmP0fm6PNOc5pDFbD4iLFuVq+CKaOd6Kam/Frr5nHRSji1fpHjaBWewi03kvcy8CUO5XuRyrPB6Tc0bJQ2Ra4Q97TIP6ng+bJbUH+NI22/NFrD5x75naRPS7QopDFS6j5dsxfQ52rDBRrnSX2v/Ap5hIzqCKeS96xOMikeEC1W2PnH9id2teE5OIQsoIDeiaa7Ol76LOXWTrUX61kreK2BljBVoZHeTLis1ZAaHuwtS2xVYvpfq8Rqq4cDlIliVEx6+fZ3Fz/fVHEWLRB/g/cI8QV3KTPmwvfjGU519u9GKPiQm5N+cA53BY9CITzy2fpdKHJJYbwE0Bv0CvMWN5Ad2fR+idciCZfKLcL3+VArQAlNA+1yLdGZAYySw5440sQdaVj1VOlDTGUN7+NJTXPaByeXA8dS0ucCoujJH/2j5Crh8lc+rb+ybaETkJcyAeoSK89500XKRaqBut2I4PEodhQhu6F2A7twUmNNdmnLlZx4hATqdzmG2HcQdYEflGmu+Ax0touUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwp9nBQs+Mgp81UNqcceJEEu+Z5XoHjiGsZZ1E+qk4OAANdhwt9mR3IL2kaWMptMZY5lAtuWYhcMdZe7wqSiwlAQ==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUPH3n3lE25Fvdo7CvT4ohJVktNIHhS4DveLpBg3bvWS5pgp0hV1Wbel5LrYBrwnLAZLbM/9yEzNqNye17vwFmcG90ncBrsq6HYPbpk2/wR6wKtf/JKdsphlZxY9Z1ojLz8skMnQRNkJgK8HUX14lZAgTAH2R+1OslgRNY7em45wSfqmuUp57FaCKPDMryHBK7D8OvnAAoDMo7nUpz91VeteLjWyjAqsFVfyGT/pcZAKrIYKXU7u2gl9GMkavFMTX2nPFu5UgzKVBD2xmGJHEi5x5AIM9Dsi6TXZJUyDfGYP6PsYhDQ9wDq9lR/fVsCuRFafeAXSPy30bcqOAv5ehIy1thcUyljiLGAjqzC1DFvYH4L1BlUO2/0cNIHQN/6cfGaR/pEuR+yBmDMljKmUEjRhQbtC9OHbkW3zixuJT0oHkbtgQUntDq45aAFl90Hrz8meeuVBGqaU5iujQCWwudviCWeHDs1giHyOihr/TQQZkSR1OwDqz7mkXBd52XsGz9XRH9FgNe9PDCKh7Ke/pgNeADH9zDoaA9vILY0S85W/go6xteD+9vZ8bgqA7yfSBLNjV5DsfybGBkRwA5jBd9xzfD37V58XDmTRYdpVKz1+TJ80rVNUSbpnyhD6G25FRDXBu5edeRYGgfZ6N9PC48CAYoHEfQnMeDLorIlF0MwDLxzgAp6oFbrGXyUg8be6ZWYAmwNF656r3fwHb9fRROP4So2s/iwt4kMaioRQuRJ9z6WOBg6V7XJjL25S7eVKA//v2vs3lmTymPBtBzrqTKgoIExPw2/dClfGbyvcQn2tKbku2vIWsPDKGh1R6es6SIBtiy6rCURE9fM+DSmMi35Tn+mcTocGfEvwzFjcaMRknHmyMW++qRIp0UaRGXUVgDBgyDL3lLGL1cbwtx8FWlj95ZfEpGQKQoHWvVXumRv/Roqz3Y3SiB+OrXWz7sL8/5fbG6bJiIj1+4z81KR9+xVIymQ688es6Ou1abkLtB/a6BhgpuQjNn3kb5bFS0wwKtss4DnFmHQptaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAAAS59ojKqOQZos2A29j93LLxvjWNUQvIdIjsTRZ0dyAyC7SnXiiUcI1Y6qGmJc0EW8+Aucas0fVP2+kx8TIwGNqnMIeN0SLKUD+pAb636rjOL5ZD8m1WgWKvkhJgmc8BAE8/0wSFMYuZujSxMJPGfSmjSayc+UW9gqxr2//0cBpooRzeiXuLk0nOEx66WKFmk0+sfs4WmUylIjF75iQan0E" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFf+CPiGT+/QGEuDKT0W3PlsxPjmWXAS6V/DT/Mm7VOOCSx+RgOLiVtIso/oFhqwU4BIN7XzQlCwlLGiql7gQA3svAZnF5jh73Ak49E6gIbqITzwk1orylJIvPTpmzhBPCh+Hk22rtzE+dzOj77B9JxqKELvY+zMhLEFM+niMjSkWwCYwxZMXtJOQIz1iLx3bVGbUjMUt8AEqqW8eAg/1Tvgi75vp5aNVSzNIiAdNrG+qmHHuxqwGAr4GHS99JvIlMdL+9IPtqgJ94PJDesytxrUS24kB/n5lo4H+43p1nxrfUWJgVRfqImIffQTvCIDfN3O3WbaV8nUVEvm9DW2qorW8YCWUYMiXL6AfIqMEbzXQul/WfTLOqqMuLPoKUZ9Z3DAjsomgY5UgvyoOV115K8EFihubS/5Qz60bneEqrsrqbOfQNKx9Y+rxHsAb4tTnA76x0Nvdu/aHoc0AB1MNGmh9A24UnMhSCYzgnnvp/EyRLUdPz8uJCryQooHT9aAaVDsMyNzD1bJ7mqqlAoKM6IznMoBlcXNbC6apb7kibulwGkSzTNmq6yUaBwVhDxrTo0etXRIAklXis3ubRccF3XLFM79v+cBC24qVEV/x/nKFMvzyrCRNFikJYVlChbFt2/Whf2I4ZA/IfWyf/kZ7PEVO4DtxRvc9DbrzpiMGWA1C6ZdSmA8E7CbjjyT33lUkOHXebgdm9iZTdk90FsKrYr+wInPSPHlCpLOd2ryDY4PP3Z9EX3R50Q/xgP615gtD/EAKZhruk9Zuk3fcloiyz9XhDj4TakSkuKnZvMDYP6ttttEf1xHnjno3tP6n5f81EerPSd96hXHtpUFES886ZGVNg7Aik3TiCufYngXcSqWBkdSRz5NiUOcOqe+7paYksma376MtJgrUihs6Qwk8gcbkEeba49bZo/WZz0tVLeBmPzMm71YN5sTjbzswVEUUSX5bxFc0kt+0ChK81y/K3Mj7KAET59McSI6euqdW4V0r63SmXxX9UXRDObwieYqPTomMgvJnBCJtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAADMkCD4QF3klIzAczx5kdXESc4t0fHpjVubhDJ21ALpRNNjmLySE2swX2tREsoPlADK16qsrJIbOGdEBXvTj4DOti0STKM/MP17Agw2kMYH2eGinDQyDEEaZyitV/CgMwLFxxCd+Dxe8mCXOMXn5Tcv10+Rb7zOeQqceaqqYrB7FZ3v7CGVYiZZk3YpfJm9sYHMUwXns57RgL4OvV8P85QE" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "6AF2F7691644791051EB84D0E78ED308A5C4D5C1AE8C59CDB846FC57138D726D", + "previousBlockHash": "3FFCD8A9457741611CDC768281EB1AE6524E157DED00966DE2F4030CED5318E5", "noteCommitment": { "type": "Buffer", - "data": "base64:I6VxmDmts/9T4eZ7dR0ZO1/5+U/ST7qtWORzQa67AlU=" + "data": "base64:jDlZvftNWRkgnsIWoGV+Hyw+APRDbU0rGhKmOoFmZ0E=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:pNONv26xGG+l2xrvGKxWWOMLeLZdpUk29EOiV1J2FDA=" + "data": "base64:U11O7/PfyF55eBj5VybbOdAQjvd0REJ7eDI1t1vLKAM=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470849546, + "timestamp": 1671691625077, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1604,23 +1636,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAnBZPRmvP6y6+p+di28Pgs5C2NcuqyROCE/fRJoGKcDeWqmoZsi8prQZBvjhombYlm0IEV9cW2Mrp3EmH931xK/qCea46uHwpb/HdmjmJ0sKkEaDI+X51aiqzQUO6jwoxAgZMGEnbMBaKCi29OmDe3OpYcw0Cer/6GpCgbn1hHY4Ikjd5OPYknbIYOTYJoHBZBpk3iLowwxtAIXcMknMVKUE71R9HDzcZJkSLz9jluTawhH2YRtYvK7NOYbo6whFpsdGM7i+xnm6MkGRb4tSkbfljspZB1ZJs+E8vC7XG84zlfNGvuabkYsmMVxqZEFkqcVDJRZMs6iWBnicLO+L3Sn+Y4xGOPF90UdZ8MJPmKkVdb5LSKJczFX3PxmIhklxdBXDZNd1qiCbBIB9Av0lyT9JAkYMRlWnxSeEUtHr+GQEVePT5jET6POUUPJ9+dI2bRyaPxen3GmOj2Dwk1BJ8ldWhH3aX9Fm2/QGV7CO9PI0vj0tMq7YFDZAs74KLusETXPUmeDnhBtZN5TaGexSG54ZfqTNnvYQHBrdID5YyOK7j6XIC9lRtA+wdkDi4mwT0yYAzWym8eosI3G5VN70br0TiZPDoVvmESylV7DukwApxx9LlLVuch0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAww/eGfny4ppfXfIS8Z90jD8cbeLEIK9TVfHQ25V5culFNs3ztPgP96e2ZTtgYcP3hKHN4RQhpROFFUyxM4aSwBA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAHDPzpuI4nYn9syQIhVw8Vu634LqzYq3zYtfk6nVVAgaPsJhK+wEY+Zd4pA9Ava3u2Fr77lnNQbhnpW9kEaETLsbxdsZRvLKGWiObKa4QZQazNZ93aWifJ9K85+aHJArHQyoHCySrEUCm4m7HIo+a8aptvNv+mBvomP6dyrcAcbgLhJUrgfxO6BcTGIIgaCKoj50dxx8Dcpdfc3R6dVbgXesxueH8nIxl842AiSVFot2ouutsJ5PNDoGvtDyferrpNaG59xOAP3VPx01kPEsJzpODRMcGz1JAH/Uhli9pbdSSXBKIxsSjU5AwY5spB4o2cnfvnRL4llVceFgKYA3EwNTMfHmJD7Hng/DGhkFxWvLXfhW9QStpTZgbp3yQMmpCeZz93SYaA/8SZogyWNGV3Xbj1aLUgWTyNqEYmWyQ2jOc1AUa/lmIal063d1GoKcyvQjzbEkLagm6YMQwU8IKpIPsYLMI+5Do8EhNKOKeFHk3fSdpxxJS7nToLO9qttGTY1XxFj7Lv1eaZinN31wy7KmsJeU5tYL+UNBYHie4szWYCZztipdf/DQ99L30XcMILgA172CcRp5EAJOSde6PYUTpi1u6w56GkovwjkL60i2bCle85MC/D0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw+QrPHEN1lrdUyOTHQ4BwEIqmyT4S4v2jT0lXtIXIzmsqpT7/4+XXrm+G4YyS+OypdgmefPBaLF957/npML1qDQ==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAmAoFG8BlpaiIHKJQPX8cvXFcxzCB4/nV/JrIjDsMUOm0VMxk0y6YkW5NeVmd8HHNV33tnowGRNj4PFipqrfAqKh9uCBjMIyhbhtjH/pmyf6tNrSMNkfHENJangonQlNt5AE7GgxNChMJAh+41KVsWH2+dBpolBmfO9H5MK/Ih+QRThm1E6eFW78Pf96eTNxoH2IQRF1Pllvv8/RhfVaWeoJxFH9APXT6tnlcvOjV0o+LX8h0kyZfio56xk1jVaisTI4OFkLuHIhq/hr8lkqIP5ochJ4GGmQSHdIHs8co+/YMgVgPspencqyocj5qeym/T92hdBveaAgNP7SMzG751snOkl/DY7KYj9ZtbtkYCuqIAjTN6jn5WL7xQbGadJ5jBQAAAPzm0pQrHVWb7ZBKvh0HpZD1pKbzV/2FbWEsd6wvhfmwr1mplyoc1lfZBVvBArpVGtFosQ52Hr1mHnGmYOEV48xfmvDDwSHjq02OEEP4ZeI8HYyzTHFCYsQmC8Bdju/TBpdIm5cdXSlmwHYCyzVfPuz5mGJ/jvbWea4DNo1Waxv2ILbHrXEzkGmD7F2TN5W5S6oknsDvICDmPsD4MSebq9CiKo2uRGjNBoFYdzHZvGchMe7erg2oNq4fx4CetXsOKQ25PJu1RDF6XvkGaBaMe2cHOSS+94paf4RNAN44ISorKlHo7I0msJQ5Tgckz7RK2IK//hWsdmYyGnAXMSrfSvMdD1pkIhsYWQI20g3eAp4Giiprxx+cSHlck7R/zUE9TycviGfV7mzv7S9HlduQEQhD1Ql+3mBj0Wbkv3e8mVlDewUxsOfTtopwKqeO2HQPfCS4oLVZ556c8VI6UyGmX2QaA1EphladxXmzOOwVgktCKMhtoBsFG8JIXIeWsED2BQXeAkcqvZ+3NzG78YaD2xnYtBKAY9e2qW25439040nDlCuhU6jRP9A8BNTLr3rM8AAnolHnBm/bur6DA0E823GpqnV7W9MEzR/Xwjm+fyiln9zLpgWP+CxtUbpXXGORCA40LAvSIx3GbfRfklwo0f8kk+w3NAl+PyK+3QX1U+uCWmi7nFZk+y1CTkQ4fUCL6kvg81+7eBPEpcWdyYrzgiJ7cqQMPM0xyRU+AmDt1/TWajWD4nVROk9kr/4SvOnXdWGPyUvY2dQL3jstgOvwgey37+LAXJjN9bxCbf7ZOmn0Rg0tMUmLnUIkHm7Fua4ar6sqDZWiisS6pVkrm+wEl0UwJ75DctQLLAMAAAAAAAAADR4COWdzAWNUeamEPG2iDfsOGA4FPy8OT0xtY94OpJH3mYHrY/ZovEYndgM8qobOqEyIaFezJdymTvVWATVvDA==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAATft+qhw4/9Mfc8p27zF3ylsBP57GcioUdrpGMEGiHFO0/sQexxu/Yfvzhrd4HL7oBQjp6BbSEMqxY+4PGEI8fZ5olrJ7ojz9scGdvlMkNNGBYyzxLZ403EpwWErsM+vgs6kK/Y/C699NiYOoREvFhvsK/2AbcltNmzc+HlCFh2kEdzsKIvL9YbSHueL7vlYECAhjMEk76/QZ7wpI+dkT8mOmiWbyrO4EBOgablFFNK2G6PYlsVDVIzTX0c95NHRJevDsp5iOs+pijBIwb9b23EkFtlhyFz3b0t1CZtlZxstlU1UPIppZJi1GSP5HjkFna+GnXRMcHOAG0/q/Eln3bEsCbdFHb8+4HXOFg3P43kGmWbFQ8WWZL3tV5Y6w5ENIBQAAAEMmn4j7x4FmlnwH2fngItrMcl7/T99zMJ98S/JEuSbD5qxNEfU3cvin+gNOn5YXc5rHmy+y3kb1XR6npk/vXZy6hQWlC3RWEitz7/V0XKj36Uik5tE6knmNbVTcj+GuDIUxQVkgTazLR3a5uVaeNoYwX39zriknfqTAGjdHA8FoKFXKQFkTHo1p3YQnxn+R2blbkd0aHn2ktZJ/mwLbo0Gkzic8LnQRei50UYBwp3WJb43q2SYv5YhKf/PyZgZF9AGXxmeHRqNc7OWw2kP6XBhlUwlONK7J5rQ32YTNSPXp6WyZIujQRplsIsjvpGScAIpnKhD6jQeLe8OBQzoJH9AxBTgd/kg7SKU8OBhEE8Bm6ZzPzn1KNIPHH+/mSTa/oJ5MKjDrBmQWHnSeR3JCVJ3WlbSfMJDbmTdf4kq8+UpVGlJ0tCyNEg6zdZsB1f/T8shR55bQK5vyNzoZsSgcBGfwIwlt/A0nJX6L20PjJhI1yKMfkg/m/B1Zj4cHeYaM73abznHDEyZkEkRtUQnOuKFHaX+AmigdM7d4cX/qfQc02ZXOMep62Lvwf9eQd2k2Iml19ZGzGvTLoRVGPKDSaKJtKIj4BFPXYfm6wJk5mcXoKvWYInIVKMm6aTqaRwf31Qv7UU3ouFKBWc0YyARL4A+saKtgZrTdvlWaoPjs1nAg13HGLMLyb8Fg1JGCfLLiAsfjvZEj+gKXW6KAlE9HiZn3J14P9L6UA6i6urkD2syKvMjfvljEQVrr4vEZa3e2+KKdL0Jyd16inD99ksBX/l6tTLCmuAQwoGD0pN66kPSehuncAmEXs8gJZzbdrr9bgd+bqo84V/LJXAa38O9+tdmpdrnr13QBEAMAAAAAAAAAZCA1Slj+TtfSE8Eq34kK7Jfa/qpxdgpt7w/WhLWeuyQJK8Q3XWveclH/TqK5V9aFH1XHlsh/IwMkdLyeOYOgDQ==" } ] } ], "Blockchain asset updates when burning an asset not in the DB throws an exception": [ { - "id": "5d2454e7-b639-4aa8-974e-5f03140749a7", + "id": "9f97e5a9-6132-4f3d-a9d7-cf3074eb3576", "name": "test", - "spendingKey": "257dbd2c98e10fc42d6998518dffa7029ffc22b931caaa7d840c471673302753", - "incomingViewKey": "4a9051150a34b2e2d4afe822509a76bdb9a498d065a2650f0ce73f10a5572002", - "outgoingViewKey": "9180b1c66deb0c289074ceb9dc81bcb816237594d487786e0b101e6108044c6f", - "publicAddress": "2f038686ffa0ee5bdc21248abb7cca016305ab91269707bfadbb6fcc50262847" + "spendingKey": "38807a3e0190b571d96b86c230e5ba3e9c04d64fcc529f192281917ac01a84ae", + "incomingViewKey": "4deb68d1e9d16d337bd9ea11a01525ae35ba62246b61ca4962e9fe3e591db901", + "outgoingViewKey": "5673babbbfd9d54a28b12bbdf563bd7bb011e27391f102663a6898a0fabf6fb7", + "publicAddress": "98c63ff634a404fd72afa91d9310f1d946334ac10eceef8bb962e779da9905d1" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeOMhvH3u/vAShBBlBCubV1nz++yxJcuSOGVoI8U6/CKxmDl3DEqmMg87vwetlVQhTW3Tq2UARomcB6R1Qqapp33FAjPBsyCIW88CbjH8jAahfI67DqKA/if/2cmKQ2me35b8533MNSPvRWWnMlGJ2uqGdJS1kiCc7SDqh3/KXh0WQZ0HFOsrRflWvR89N9RhWT90JVJ0mV8KjYFGYFNH4HgyrdiayYunGunOYsHmQdCJbR7lOCG+CM+Yk+/xGNnabAd1pnEqG9sYXS10eGgxFB7SHq4mIROnCa5e1a5hfRalOqyaSgf7oEIOW9NjnPX3HHNNS+SsY2HzU+RggAin5L53PRsee0rkt8p6IpSroI/XxT3RzFq0oLLbnFWrA3JWK2wWLWYdmUKIogmK/hwntn1xA6S8EBuPemxUqne0EtujBwQWxStxY1YqxX4nAknouNdaSGqo2QrDfsm8dU2tVfkMyztHXFcC2bR4cksHImhsod3G+wYyjedGn+lIOsPHDGNZ+oIMzR7LYJ32cJ9T1vY3KG5HXHAiN9vGXsL/CTn4HdyhLD6x4b9Arl0BiXeeCYK15C1/lRSmiW2ijopyXAA17r6tDvGt74n1s3iBWq4gq7CZEZ9pc7aUXSw8WqK3R6JjIRL5FWqudRTapMoBtyF1d1VRJlblH2S+UfNLbE24tCm8DFmHiQFxFzIvaJdGNH/Tnpt2ESv5N1a9fqkEdzptGfcJAQBWlomccroa9BE5DpHcDOkDFs/uHxg7csQbV4VByncGUV/2GECvCWqG9RjM/KRp+nuNsh7ec7nL6FdMrXZbg2dFS7Au5J5rfeuF1AW/Yp/SX/0rXNKxnmglZHvgoBXnP/r0FlOIIrdEjwUSDlssrlFAJXA5zecLsnkQyun3PmbV+f+ZNjJ0muZ6QrhYj2soh62wjr0XpDnRLH2XMmVbBEXpiplZfJ8y3ji6Fe30LiIDbNH3mVvhWOzkK6ZCGzmd9temmMY/9jSkBP1yr6kdkxDx2UYzSsEOzu+LuWLnedqZBdFtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECgAAAAAAAABMcpusRF5VBoyd2m9qZ7pyJNBTNHloLF0918nY1tnU5CRpXIOwBDECxgFJ5goLCZ8ZNw2iOie6523JoqH7Ym0n5IiCiAuLdUcHvIqGedMlzfsDv5caqG+MBWDOpXwfHQc1uUO1E6cwVew2pGBrmFTDXYHKqTbzLZeV6rP5EIFCtZ+gnf+LA+r7wWhEbjGfoA0vj211BJaaFTbSs+4bHEgB" }, { "header": { @@ -1628,15 +1664,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:go3EfXyYlzZa/tfyKJSs0Cerx7odM0UhstjaiGc7Xkw=" + "data": "base64:QbBCE13fDxjOWIb8rIHDlaHlFt+HJD1stOhOUu0rE1g=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:QoTjxEM1eYmz9PlY7TM1yXbhNOOPnrS/MrCtSa7zHRc=" + "data": "base64:FoviMGDH7pDZL4kzTB06oPIgEHTBnpFewBph3h7fOz4=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470850453, + "timestamp": 1671691626045, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1644,29 +1680,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAgI42bkP/fKmk9t5X8F/zvQVhCpDQrh2LMkiOmuULnQCGvsd+LASpbOWTKjy24qF7T7Qyo3gftsOnC76O7BO6e86sd91XA49fyo4W6nOyLW2JlOEGTzDA+wpuz8AC8C7ZgZQf9gKFCGPSF+7uStgodh+ZGHSvpF3kA6AYgndYQrsUDsHbqDEa0PEE+NPjlOWc8XMOVzrLqzqjEil20kgOeMJnx5gJGJg/9RVj+JcxqTWN8wC/nFjYfpPjyo83bWt56m4lkgY4SADsZCr/tnBTss8H2d4cmwgfB3ckNADTqBH/TSfmf0pj5M5dAJmbI/y6PAqwjvDQkNG6W9WucGPLpIk7Qb8iVaOeIqUZ0BSWuQcLgKKCaGTKetPvFqjd6+1J75GEEDZOT+mDRzfW7+2y544f7Fg0TAttG6YbQ5jvNVefL+lF1oI8k+5aMZ4H8Spp2Nj6Ew9RJJVSACBdL6lfL765uApIrtbIsAlVZszPUe4kEpHKzlphBlXE93lUABwFYQtABbB0ypNZjguH8gtvy2JwR5/n5u7RZps95HkhW3enRhdZq795JjwYbur5hsRQH420eS/o7TjAAAC32Brv6LJDdDz7oYrIBFVMTXmh31LZ4eWGyt+8gElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwyL0Y1DAmrulw3L/FSmmd+CkQbH4Ojx+DcNMZlq7GOwTPygH6KmSrrVZCTePlOcymcgC6fyHs41wYD4zmbZzPAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAACp4DnvFLNbWZ3GG6UbRs5tcUlai/AdLLWWlIENt2DAiYWSy2zIO23CUj4HTpL5K5tXHKZQl3AGdbmO2TImgR8w+o+49bE5tTp2W8U8ksAMu0MaOAIEERme5GiXXPTsL/KUTIF/jIrcU0hSKUj/GpGh/NclfWHDgUDYNCvtL/nhAMhWSrxj6NrVaHFgvn/2cuwJzMiB6KVY0LwranimT1sYCPaT+88mWOxvBHllGUyBSLMdORH0ioL8SXXX6iSUOkDI0lEsUYo1Qjhz0HZwVO/XFoWw+HfwJ2kzo7zJdnj1+sWzoo6huSGH+ZPwg2nJGFJ+I8q8MeOZ8KtfseKJlT6yFSY+JYakZ6AZSqlGrOJWiNIfwsze4sy6T1sJj9XlRGV2WJn7IrrJkvb/898OVzE7OS9cNSNQC8kOlCD8eeDqal2zFXXp2RUDhuy5+h83IPDM1lq4UBievo7AtJSc64csKmH6zbIMCjDrg4nLOJOucmvVrAuQya8Iu9glzhK8m3GH8W/5Cubj/nfsNNkAteGS0/rwVvvN+HEnegGsUeenaFA+9sXE3DRRjUWq1ZeKQhjgUudkHhjvWhFHNHKmM89LXuttUJGPuIOdLd8/ncE4+F6puq7hFcoElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw1+8dADXoml+HyZ7Rcdg2+O3RGAWB8NxXVXqUUE5o6s3nyHY5cLsejLFdLbyNSdjMB1QYaFXDZgRzJNGTI0hcBg==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKs29vEZwm2aVpbfZxplUPzkDWGDzlMo3KwJqC90xFmC1AVLhpqO+hDX5HRZunTNZGYeCC1wJshXHuMpW4AaENx4YRoSZeUj7W6It2c5doAeth+AswmFvMR4+WuPBlSnzDO2XqVcF8JwmtySdzyonumobtnBbFDA90guvgCy4hl8LD5Kx37es+ZU8Ec8Ek6XT+KfjAQHE0IksLPiNSE3/fLWZIIY+9kbrlt+IZmhXzzelhr9Kk/PGiLltnTYBJxRjSDtX+piqlWGx6IscLpwJvl5Yr4HbN/wTNqek4aMePh/GYYO8JhXLRxWHCiYItIiauW/ArN0xHALSoLVHJ27qXZGrXOd4IZOeRpJlybLK9Y1/TX4tSBp4F55nt27wyAQ+qfAeh0g8NefsbQRM5/dg/IiHY/5Ii62W07ZfFmGS125lFFx6Kqh4MqRTFIoIxmSFLunIS3XAcb1Ex+ejfTErI1lRw3nTOY3+x39mbS5Uawe3m6eBw1iOASgzurMiB2ewWY06MJCFKCDNrpuMhXhp/lItkKSQZuDSc2GGxtasakUcMdTM3UkkmWL57EHj8lMCZwwUBiFpFkrNju1FkLXjDPtouU/CZ+JqoSBA0kjiPF2/ODXBAKSXm2eogCao54zqeuRPpy5Y2WTJRTK8ikJuf2rzdL2V9Y+H4p1xOlewVcGO5H/96SlcQ5f9boQPC8JV7N+nIyFqYqE3GVnmkMeAn2b9pm53i8v/gTjCXpoZKnMb2bBZl4UH0DqMxe5e0F88WoCoetN/V27LP7ias30ADNPlTW1LFIS/tASxDb/W48uZSMiBLEscJ9653R3AVh5SqX69fWGySfAaDHL8Mx7OaE6IDybuRyawCfIx97BqGF7ySOjuB/eVdRSsq9VLNYNvx02dIlXw29ILc3vAkNRFDAA1r30tdTIXquoFdkMkwSorzizPcrJfVB4PHU1xlCcJGrHT5CdP7+N+lW4mdRdgP3zJR5wbRIlLLwOGhv+g7lvcISSKu3zKAWMFq5Emlwe/rbtvzFAmKEdtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCgAAAAAAAAA5ntMGL6QWgLrZipPFrK202RkdlMhcTYMRyKtE/+UZvTouoGNiOSznHHanNoEWhI7iPiSJn6730DpEsa8PKHTO/nd3eP+337nrvt5z9MesBM8abbhBA+kT/CurTUI07wQlr/iExGXgGvv2rWXv/zjmWldcraCqcW6fH/LoXpVfpWPquTWzlsvtzPgWv3Jsptu3FwkpfGb/VSkDwFhXbe4B" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeOMhvH3u/vAShBBlBCubV1nz++yxJcuSOGVoI8U6/CKxmDl3DEqmMg87vwetlVQhTW3Tq2UARomcB6R1Qqapp33FAjPBsyCIW88CbjH8jAahfI67DqKA/if/2cmKQ2me35b8533MNSPvRWWnMlGJ2uqGdJS1kiCc7SDqh3/KXh0WQZ0HFOsrRflWvR89N9RhWT90JVJ0mV8KjYFGYFNH4HgyrdiayYunGunOYsHmQdCJbR7lOCG+CM+Yk+/xGNnabAd1pnEqG9sYXS10eGgxFB7SHq4mIROnCa5e1a5hfRalOqyaSgf7oEIOW9NjnPX3HHNNS+SsY2HzU+RggAin5L53PRsee0rkt8p6IpSroI/XxT3RzFq0oLLbnFWrA3JWK2wWLWYdmUKIogmK/hwntn1xA6S8EBuPemxUqne0EtujBwQWxStxY1YqxX4nAknouNdaSGqo2QrDfsm8dU2tVfkMyztHXFcC2bR4cksHImhsod3G+wYyjedGn+lIOsPHDGNZ+oIMzR7LYJ32cJ9T1vY3KG5HXHAiN9vGXsL/CTn4HdyhLD6x4b9Arl0BiXeeCYK15C1/lRSmiW2ijopyXAA17r6tDvGt74n1s3iBWq4gq7CZEZ9pc7aUXSw8WqK3R6JjIRL5FWqudRTapMoBtyF1d1VRJlblH2S+UfNLbE24tCm8DFmHiQFxFzIvaJdGNH/Tnpt2ESv5N1a9fqkEdzptGfcJAQBWlomccroa9BE5DpHcDOkDFs/uHxg7csQbV4VByncGUV/2GECvCWqG9RjM/KRp+nuNsh7ec7nL6FdMrXZbg2dFS7Au5J5rfeuF1AW/Yp/SX/0rXNKxnmglZHvgoBXnP/r0FlOIIrdEjwUSDlssrlFAJXA5zecLsnkQyun3PmbV+f+ZNjJ0muZ6QrhYj2soh62wjr0XpDnRLH2XMmVbBEXpiplZfJ8y3ji6Fe30LiIDbNH3mVvhWOzkK6ZCGzmd9temmMY/9jSkBP1yr6kdkxDx2UYzSsEOzu+LuWLnedqZBdFtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECgAAAAAAAABMcpusRF5VBoyd2m9qZ7pyJNBTNHloLF0918nY1tnU5CRpXIOwBDECxgFJ5goLCZ8ZNw2iOie6523JoqH7Ym0n5IiCiAuLdUcHvIqGedMlzfsDv5caqG+MBWDOpXwfHQc1uUO1E6cwVew2pGBrmFTDXYHKqTbzLZeV6rP5EIFCtZ+gnf+LA+r7wWhEbjGfoA0vj211BJaaFTbSs+4bHEgB" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "AA015FF2CDF99BD5C0D1D0F743BA1E91D43BA98419B8EF822F7B3AF31851B3D4", + "previousBlockHash": "7A3FFFD962176FB602CDF191FECF3953CD0E2ADA4E5175A35519BA3C23B7568E", "noteCommitment": { "type": "Buffer", - "data": "base64:BnylQTVo8lrbpxQLv/FBu1Ynyu/3lF6mvENEeMQHvz4=" + "data": "base64:qtAG7pINQ0ear7qEfiQ8459BtdlRU7yJT4yLBqkB3EU=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:G0DAPLNCrmi/P0fLs1wj0lgLIR9pVvilINs+SU421Lk=" + "data": "base64:/4jWvTNyDh9hghZRTq0CVLBgYTRDyEW1rhkeZiYdjAU=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470851819, + "timestamp": 1671691627559, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1674,23 +1710,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAApCpWgvCtTrW0tjat1MUQUi18UtBslso3NBjYrpy1cRO0i0lfjK2BAIYLzUVzwLute5Ly0+gnQhVG6BzyKsqo48c6eP2OGiY3bjtxHzjJNPK1inB8Lnjfc4OD6OTL3s7Pw9xbHMABcrW3dcNuW3Doi7u8HMmh0IYsWEm+InuPIpoTVhMW98fwHTOLddumDu//or4lnTZYqRGGBRVoG0Qz9ScRS/ZzgXyVOz6AhqwoTfiIEGbJ20PhqWr1OKBnSAKASY+aF3iso/2E6IVtYBfR9YrzJwH+lWuZOBU+Qc3VvoCY6PM6Gb48roQwiR4orOWHudtJghm+RMhAgQEyrXkMxoYADV66mqbzJFlvqQdoayYTOlpXQwHWfq2oFCs7tYoJcSRWNYMCNEGI4r+ntDFHKM36tg2r8eCiVu9+kvNh0o5mqAqFJuETxL7ha1oKWK5E1nfDdlQSdzSH6ULTyRi3WqW+/cU2kLnmXBltxmOmzP9uSvmM+mGe3LrTPNNXw6Fkb4Hv4mSPFJbzNxRklyYHYzfzXllbqg8qy3P3gBnSQ+yGOhj0GY3N/e69HFJJ4dzVU+FG2EkKq5IJFCTSO4J8/97p79UPtkZR4sifJNEvwIyp97+ceIzSxUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJKwhPwQdb5HDcxFeh3pF6ufUCrPL5wfKljirb2hh56XKkpdJayZKNdJ+xe13c0pc5Du+DOe8QKToAFf8rWTnDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAZDq6CFGlkT5GqfqL3tlQzD7jroKZSh+9J4JTUlaDI2q33wFL13iwXKK+3jMOD7zuavr/KKpSmCXbWs5HHs4EsANejGrntC5YVt4IJgQl83eM4xdKTb+BtVy8YPoUDTsOA8LhKwHArLTQ1J8jsfU2mfqwREcUawXFs1YzNnCM7zAE7ImN6ye0FwECiEsFTTYkhFmf9mE5uB/K6VlLNfdKnE+kT+X/P/fVlCSscmb55L6C673GTx9jmq0T8JTtBx9DPh1RHbzPNZT4fo3upSF+MkejJAUU8tRDeErFk54skCYvtO+DpaGH9aEMjwDD1n9Q3n3EeeBJ8ZuVr9AoTmPFSsI/XmPKyIMb6rNux+yh6vJjtinxk1vMHY1TdjYFkIUKDQxxpQ7GKPv9kKOSl6CV8RVBaRIyevecJv+MOXAOZLx2d331/e7ZU4rQYOazPKXRajAc14EJH0hbcknQz30GpoK/EzBZmTlAwyhlusfkVcVAzFvjU+p9ZkcmyI7uVhO8/19BFGZoyj8E8ILCEukQNIgeG04zzJszpglLS4+CiTiIu8bG6cOf81C2K6eBT91xJ3Z4HUaLcNCR3wbRogjfBe0EcQ563Ij75bFBX/Wy0LTd5x1Ol5kla0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw3ZGGikjn6oq5Vd9//KMg2lYQQjRjfvA1nrgsSgLCobTgVA8a27frw+aUkAzayCMJ4XBhJPiLihoeK9SKTUGRBg==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAArDa+SItmlqr/Q6y+sI4MfHWYmxZ4F6lsfKnLq5bncTmUxlyAvYUm9O9BK/WQOs2wAt1I4krxcMNdRRSPCZyQJkA87Arlxjep0YO//BFG8iORGo4tSCwELDO5egSelVZPg0hfF8LEl9bHaKPn/N1fkyeCkoVvVsR2AJMyKF18FMMOs7d8JcR2cY0xE2VvJPU26wrsIBeV8u31K75CFT5yBn4bE56Qq3bDSKPcZEnKklSGkWBNc8EjLzXCpRrIYPhZ2Wmza2THgLyPkt76vA94z4bt3fai2HgsnIFB/d/+6Z1Kva0ZI+MidpuX9yQHkLv7afQM3OkdzOSZ8TXN0tEv6YKNxH18mJc2Wv7X8iiUrNAnq8e6HTNFIbLY2ohnO15MBQAAAP4/P/Gwu7yz9gQAmZY9VY4E7fdP0dCybqmJ87J1FF5ygyXomHSZ6sCROyrijTpTq6RMruvlGjBmutFBVfHXLmEIyuwrO3pAUPEq7cx7MvAOvshOM6jrNwV1xq9UefAJCLBNixJbrtaKEeMRsb+XfqUWchhjsmCNwVvW+HNizLfsbSvJXQVZWAub7k9KxfDkLIkx+g3YmiaTbGYb0cjpEr/UVaCsRd15gFqwY2cRgSKvogAYS9zXRq1QQKVWO3AJ+QsSvfli5v3SS7i5GmoiNoB4J1wXY+ml8CiJfn2HUyWRK0+h80XN7wHde0yba4be66OIR2H2JGvgfN2di9GNl2w0vWDvBQHFQgLt9GvhcBecxAVmIIcZL+TBF0CNl2YoK3R5uX2GXD4FbTAl6FQQCYhjIu+6DKZApCriWDPJeMvKfHlqM4TaIrXAJ4dfKKya56VNAlZSBroxu6lNIfZdL1G290DM0WZOHojCwcxf/mraunZMlbbA8aST5ikelhSSQA9Do1fY0H/Y7U1v3zeRZlDMUA6Z6xjWxCMq2whFzfeWH/k8Y68u9xSdODrVD3uUwkQ6KHrrZBWY6Pq/EMwwauu/PkJTTLf/QWsbxY6irAJz4/mFIZXlNqqgJiV9lJQeswKbgAr7r4fDi3RCSW9ycidRPcmhpFxT99LoAKCOP8alFecfhrRBGyaje4PBq4Nr4SpcYs6mLJ0PU3MgmtZQVobfvMi5vC0e696NIx5AhS1jyVRrubmOZYDKFtxQWDwle1jvEyncnNv369ZL7XFAkTDQNlgjSRT5/Rc9u8Ggw5NONz5BxVjHy1ANJsq/nfGyKVuDQxA4dw1psGbu1drxXBkg7CxuwKxglgMAAAAAAAAAM0Y7S/Vx4qhn2yCtEQ/SSWlgM1PI3NVmYTFAewHG0BIWGCaRAFDvvo/yxqr6BjPjmwCLGKdFYAjwnuYK5eaZBg==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA7oROi/RSn9hdO6TmPX/uTJ+Onvs3WIW8vpmNALI4cnGHO0GwIMX3vj7Mj2JqofwqnKBUbm/ZX2SMqiCNumEgvRDtBipHXq1Hmk1G1y3eramu5h791lQlivRIv8U725txDFavvEr/KENN/kBO9LTScmqiptjmrpgLfDjNL+U+x48N9DmBtRPf36wm0SGk7EaVFa4dNadyzRRh3KIOQI7LqvyHCn4m4DAPPxdYJkAUGcCM2x8WR1SrpcPjglGADoHq/IBwVdSd+QZ+QweqdLWm6MUFWl5fmCLBYsmC8A2MXehF6r/3gFQNQuXs579yR1+P08GanU1J/l34QRFl4Rcb3UGwQhNd3w8YzliG/KyBw5Wh5RbfhyQ9bLToTlLtKxNYBQAAACeZpYqBa0lZmO1JOydbs+CVa+d99gCLGdUmw1cN8133LTMi4yoq9tSKzBSQpVDigmYNBQm/prNl1Fimrz5C4AQQGIzFjpq4LYUsNmNlCj/0W2XGmmE73uUEzl3sx4x2BLMdlji1/H4YCd7rbWzFzxTYfs5ihu/6TJZfEZr/V5fZDh+rI2EvsLynyRF6aC3K/oWPqnLtJQ/wLh1ZhyeXCn5jNbuV7bp7kZlLGvO6Ez+i8GQVOfojYTxj3IntDb20zAQnoWHrSj92AhyJoAVltYJWNiWw3d3NX9kLZcgeWKdLSt+j9VLXD4xsh5D+IHqkB62poKBeHWn6JJQeFTp2WCQVLl7cpUA+NxRc1lWjEo1ctTE8h8V08XJrAMvgmoTrAuOd4ftguUPVa0tOrN4te4YcGpShXTdeja/GPeV5PrUKdlHFQDdox/bgcArZqDn1J2tfTmSJsJI65oZPDEYCVx6i0zwStkHHN+fyFuBM6vdQtaw1B6syWEDGuFVtYLYjkC7pJLj7gJMQd0MehmgBDqyu4saOE/0H3NcQDGCy5Rshmfq4uChf6A7HPd/6gdmqXx3NbxVGrg9IEBBWGUO11HsBiQvRXSWEhFiLnpYh1HpxFfm725bAfuhiJiKg/NnleczPXorJRrJjFcsXQnwSOkC9WVbiVvnsRo5o0uNkUBOduqiuyKllf/J+9BJr4+Ie1XRZLkOCKwKBqD0xVn5GQHHHExD/cjCq2FKooEQFN6aZzQZcfXwVxIugX83jGDE5E8ORtG5IMEC4n0HSRW/6F4nODxkRo8cTAzD8ah+scVspspQTkzcx03tD0Qe0SKRsDmICs7ViHmibSFdZksqI5Obhl5Z4nE6qRQMAAAAAAAAAnQBIFYfKC4wgmYAzxPsDqbgeFy+29lnokNmwofLHH+qriV1wkjB0Rw755MsSuQcpMyX0ibCd50dlDRD4V0Z4Aw==" } ] } ], "Blockchain asset updates when burning too much value throws an exception": [ { - "id": "f6c74676-a1c2-43f8-80d1-4ab435380efc", + "id": "7cc50266-5649-4d42-8372-ab666324b001", "name": "test", - "spendingKey": "9b4a580135cf4d43149907f569012638dcc06c1e99ccaa08cc2f862e8823300e", - "incomingViewKey": "da8018ffb3ac4d764fe6d1487d87e8b102845aa4bf6579fb51ff6dd921a85104", - "outgoingViewKey": "03f0f2f274e7dbc9c4b5e082ec1e1239be6ef064bcf2bcee35b0720779455fde", - "publicAddress": "750ee1061933c294e083a531e017f96dbd034696cf05e8ae294f345f70dea2b2" + "spendingKey": "d3af5a928ba00b0e97e0e8020b429e7e1940672c0594ebb60458dfb66f16130e", + "incomingViewKey": "d45a42237c4a9731730b7c906a00a30f1f38f2faef67d383f8625f42fec44306", + "outgoingViewKey": "c87b927b1fd8a2886d2b848e47e50463b573335fc1f8869786d9da27c8bba0c1", + "publicAddress": "1262d915f1843c822eba28d479f8803e75ece3c56950fb9b99a466dfe610f9a1" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATdgHpaJ7lh/m7SOlWU3BjUG3GOHAt6YGsBMxvbmPA0y0T/B2+UIicrWMnSvWbLd/idFUnXmu1OKUqdyvoBhc3VTymiQXpwN5Fp9VWn0uu9OJ5Xkpd3Wq4yKYUOJniLunKeie2MfLxcqxQFVbDD7W8tPJBnuS7YEZCAVsNeYB8ZsIqCbZ5134QRc5WKnEbWaivZCBbyQNnplKOQVhFKEUaNB5PxKud6DAsYMEqlNcpIuLIMKu5QKiGJ92P4/jzAwulCJ7/Mn5rHym2Kj9r/f+y0fhXTpPrXwbEZCxaHwZuOdVExNqt6O4lARniD0Y0kilVeEoaqEvZX4N8Ec795BzUxJ00c5dnTsnMRxDVdb1iqgXHLEjmIdTO77QItBZtvJNJ5TmDhzKx/3EJPl0XgMabnen5gZJWkviZVQBKsfgLu5zrutosZSOL5LdtJhsoQls0AcwbC/hSkt2d6bKSFIbThwNcpr8cC0gIbYJOOlfo8gBeyiRF7Y7K9Ebb43r3MkOE7B77ZUVnhrujb84E3EO9WTBE0KrRfuPmJNMlfQO2jkivoJRYTqffsW+5h9RFpGJOSVrYF0Hv+8GWwH+G5GonyiSd5/4qppx7rvXXKHhbLGseP0pMfSEo3g0FAHGDCTtHERK75TuKCvnQi69neoViDl4R8kyoXe2DK0TLG8Kk6p6yOBF0AJuKTGhnVNkPH29C9mPCthRtK8G1hDqb/bLR/Bl660Fqs/7heA9k2BOoAND8qQYqq4PDJmOtJSHhvAnS85xjmqiGSq3ld0HBxIXil/2fbL0dJ7Pksh6CwdBxNXaCbB1zfSeen73Tyb05Nco5fNcFavA9aq/MHQTUT2uTDE/IqDx3KDtFidpa/PoqFLKjI2EKk077guoBhGgiyNEkw2ZOWq9/2wPRxQIRnxqOI7riEyGnXI6hwybn/KRE7hRbf8q8huf0vV//BeD5iF6DM46RDu32kFFBsCxYbre5kLaSWLH6dOzEmLZFfGEPIIuuijUefiAPnXs48VpUPubmaRm3+YQ+aFtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACnGOpyEmZHWPq6sMiG/ufyM+yPg+JUo29DMW0IxnIDNu5JsCnAG4VTetVWgfhAUA/Nrywbt3RTr8V6ZUbidUap7+NLCvG28R6ozzOgZaHPWM+qJjdk5BMvwfX8xqgTvwEmOfVGAMaBDeLkeUR57qLZPkLX5TyecnnJXF3tMIBNh1ONNmGyv/X1Q3FAnZ2fy2/cyn1rarZldfbKwFGd4CEK" }, { "header": { @@ -1698,15 +1738,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:mIALEz8hvki5k1eyOQA3XgdUqxKUxbWl8vxyZ3c9cC4=" + "data": "base64:N1rBMuMczbduwspgvXhyH5x/AJlZynckOU1EQ4vSXV8=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:HGobq5DFGOCDrOQWr4f27SAHrp1BZKHhjl2Jg3JjQ2Q=" + "data": "base64:VeFZNaZNO7uXUBXOJ1xx0krDR+kcpe0/sAOw3UB7ra4=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470852749, + "timestamp": 1671691628641, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1714,29 +1754,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAJc2r+0x5ZneZxvF72NW9TlqEdeBRBbjbOUGn2cgDSBi1T0zKliH63bfMO0QSh0GW1oPP1hlFzc20m9XNOJnvJ38DimdtreL9YqzpLjRGcuWIzbvuoaw6pLegVHWhzCKwo4kQp0HiY5pS62INIJ0bA9+HJNBzXPq/EEmdLwnzJCYTn2enh8hHlb/J/qzpvqjpdbFSSYNBaH3LLRWHLmwXq5znkcQCr4ZvtjE3e2Pfa8SZFOG+tk+HZuGfpUfj5NQg6RxIWsBuT2nfQjyYmJKAUj2LsQeRVK8vC6wqnws/d7B+vylutj26UcOx/pOHWO+U6bPGp/uF/dJJVQs48FxHpygm5FrFP24yeuJIVrHJR7JR/UoCBKCMptHY/jIjADxVr0oiRO6nx/aBPNySWod9aWZUVbPer3flGffUKBcDXZe644NDU6mrpUxVGBxYtWuZFboRVThWvJQc5oFDnya1X47KAB+zNjg2plgKiOpclu/89lQTzwBbwAzXJxqmiccXSvAVrB2etJc/nlkryI4cO3+aBQscfiiY+mRJsyEzg4QIaQG5mTikJuTpRxxpx4P4ya3QmDHLMkqNALX9XaTRcMlr7fNwuqV9m1AlCYXiCk2Erb0d/H09p0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw/oRF2TIxaOMWj0+R45E5xHYGBlSXH6S1GAvjKdlv+txQ28hLhHDnjPlksRzPFrX10taUxJF4G4KMnh807DZJAw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAdxyzMkBJ5Z8S3nGJgniUJOgAkfTMObOnAGmX3iIRPROD/NQesRPOPcEaA65fC7jkQV6Ky+r11U4Z5jEd4UuqKC0ra7jWzEoP7/jljJg2Ft+SOAM7XrP6eMKGCGfO8LT6FtPG/aEcE2iGwOz7ja+od48w7N/MMas3t9IWdtG0PY4NuFQgxHKRrROiBovq3CALyG7NOzGpAm/Z5fWjnT6cc0DbzZvKGRz2tH0uWVhA9wavoVzaFFY8re9OUT2pN0cZnLVXN1W0Dwu5FAuBwSNqy5PVWi3hCqv4Dmk2cp0A+matGSPkm+BO1v1IjPGS9R/fpPOpRp24ykFSUR4cOBKpXEQfpVP6CZt3Tbo3XiyZoJrzxKDGab+RTDJeckrq6ug/eDBTABylFEkx/44srXDmMZeFEy4Q5XycnonP53m5xvK8yDhqGEpH11YrJEJ/Je6d7uWPPuizUGd8mN02CfnjtHbsWF4I/zMi6yiqiv3JvHswaKDc4iKaNpZJ3F/Ynf+C7tFS2ArGx5+fVi/I8OguNKhTWqrB/BXoITgfosie4YPQLThQgIkM4wPb8U5TiAZaFuCvh+y8ajneTZr9nhyHS2c1nz6r6lPk8h36M3uHQfemWpoCQWnNSUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwVbKptx2KbXeLWQOgm6SYEKWbEhkXDUN0/iaZ6vlG2s3/ctFqbFQB5cHtRNTlT9Sxk0Pv7H851WukzaqlTAc8AQ==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2UvVRzxQXUudZb0I+kkNUfQBetUFShzEq10IiydKk2w3trJLT9t75ENDzhOurAIBmHxeXg1QmvWHt+wOWybgS2Ls0K+EjSsBkyIMViWaKiioGJWNhd9ZjCSsZNtIK6OWI/PhzChWKJlSOZmPJgvqFYBKGvqUR4HM4nQ/Ffz4Hci0XVDtElaOz8XBPhFIFomkS1Nu8n9tpALcYe7APtRb9W5UVHvu4rAvrI3Cede+H+pW2HGkRCf2t1huOHXO0DSoa9prux60KIlOSKmgE7DZiubYmncsBF2dXFrTy8/UJvzvUBhEygk8fSIznvNs9C61EwghduljMH1RFaQvSPOFHal+Nu1ZtZuGfcHT4jYX14Ml67bjpWS6KLY7TD7Ma8K1Xg9BjUrA2/R5aTTG4NOmmVTPMkzrfR3T5RMOauxHWc6p9DsQe7KO07UY2shz47iU3PRtNJelSb0CVdptxF5WWgZTKOXKxpoN8d7Pi46XICMZBkj1e/k7G2OxyF0T2RPSqtpqwkRATbaMlr8xXiOBm1DHu+7QXTR+FojfHrlZrdbFJXk/1i1D6bd/bV19AtHov2HGiLnGxN7GcC97+8j1sRPkJ0rYj5fvFFbbBFkKB/eyWFXBf4GNL6RIS2x7TliqisguaGGqCgbWa8avXeLZS4iHF2dl8UlftxI/Mb6oIsWrkxMvIW9BLUdSKMqS4i3FsBE2bnBO7cXsztOrN0ceoTj0F/zAAleUOHFWi8s96sq7dMP/uX7nJ5aJvlMiG/7V20qwNPtiulkl7NKPBR7d+rZZXvZM3jTITeLuRp8F2tByuWVuytadq8asdgdgoBHj5/av8uyZ7sQga+rV1kluVMC1WpRFKDsqnOBvimj5FVUIfEXdPHCBkF8dYLSyGEv8vaAaIhhGq1bHigf8iojsjc5Sa4o1JmbA/DOwE59UEFcyD5Y+gefdM4k3j1aQVKDK4xqP31qNkE2RfeZVoBJnEzh38dht2dQ7hBhkzwpTgg6Ux4Bf5bb0DRpbPBeiuKU80X3DeorJtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgAAAAAAAABlv1rT1jTlt8MQPRbFUWnDeTN+tGRx2JqToJnssUpmr3372aCgWyoiXqqlHVZocfZE5IuG+xFvGyz4AyKR75K0SMg7RxIdvrHpuXcs4DI+uW4R7stTOg8xNUFPIIdtxge4Cw5pv1ZK7TttGWkh9+1B8N3SJHzIGgwUpkEe5ybPHWDtm7VX7eNA9PoLjg5E5BTkDnvbenoj+EuNeJyFd+gC" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATdgHpaJ7lh/m7SOlWU3BjUG3GOHAt6YGsBMxvbmPA0y0T/B2+UIicrWMnSvWbLd/idFUnXmu1OKUqdyvoBhc3VTymiQXpwN5Fp9VWn0uu9OJ5Xkpd3Wq4yKYUOJniLunKeie2MfLxcqxQFVbDD7W8tPJBnuS7YEZCAVsNeYB8ZsIqCbZ5134QRc5WKnEbWaivZCBbyQNnplKOQVhFKEUaNB5PxKud6DAsYMEqlNcpIuLIMKu5QKiGJ92P4/jzAwulCJ7/Mn5rHym2Kj9r/f+y0fhXTpPrXwbEZCxaHwZuOdVExNqt6O4lARniD0Y0kilVeEoaqEvZX4N8Ec795BzUxJ00c5dnTsnMRxDVdb1iqgXHLEjmIdTO77QItBZtvJNJ5TmDhzKx/3EJPl0XgMabnen5gZJWkviZVQBKsfgLu5zrutosZSOL5LdtJhsoQls0AcwbC/hSkt2d6bKSFIbThwNcpr8cC0gIbYJOOlfo8gBeyiRF7Y7K9Ebb43r3MkOE7B77ZUVnhrujb84E3EO9WTBE0KrRfuPmJNMlfQO2jkivoJRYTqffsW+5h9RFpGJOSVrYF0Hv+8GWwH+G5GonyiSd5/4qppx7rvXXKHhbLGseP0pMfSEo3g0FAHGDCTtHERK75TuKCvnQi69neoViDl4R8kyoXe2DK0TLG8Kk6p6yOBF0AJuKTGhnVNkPH29C9mPCthRtK8G1hDqb/bLR/Bl660Fqs/7heA9k2BOoAND8qQYqq4PDJmOtJSHhvAnS85xjmqiGSq3ld0HBxIXil/2fbL0dJ7Pksh6CwdBxNXaCbB1zfSeen73Tyb05Nco5fNcFavA9aq/MHQTUT2uTDE/IqDx3KDtFidpa/PoqFLKjI2EKk077guoBhGgiyNEkw2ZOWq9/2wPRxQIRnxqOI7riEyGnXI6hwybn/KRE7hRbf8q8huf0vV//BeD5iF6DM46RDu32kFFBsCxYbre5kLaSWLH6dOzEmLZFfGEPIIuuijUefiAPnXs48VpUPubmaRm3+YQ+aFtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACnGOpyEmZHWPq6sMiG/ufyM+yPg+JUo29DMW0IxnIDNu5JsCnAG4VTetVWgfhAUA/Nrywbt3RTr8V6ZUbidUap7+NLCvG28R6ozzOgZaHPWM+qJjdk5BMvwfX8xqgTvwEmOfVGAMaBDeLkeUR57qLZPkLX5TyecnnJXF3tMIBNh1ONNmGyv/X1Q3FAnZ2fy2/cyn1rarZldfbKwFGd4CEK" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "DD130E96A94C961A2D89A5ADE420168078662D769BF4ED985C0A7EF0B2D9EADD", + "previousBlockHash": "2C94E37909D2B4676E361C1CC54F043D88FFDF39CB693BE3089B4AB744ECD8C3", "noteCommitment": { "type": "Buffer", - "data": "base64:FCYlXWhsRcJ/BTCq+RgU4DoBluCq3/n39i6LaYHNIQg=" + "data": "base64:XiV+sdhdVXAUps4d+yTEyx9UqCjhsqnAbuDR1TcKxHA=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:xTsAKHN10oUqY9EqtYBtXcYjRFl6AJvcAwUK6X2OYF8=" + "data": "base64:4gHXaksrlrZ9BwN5/f1HahVj65mCo3yI5wxWlrHj3Y8=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470854159, + "timestamp": 1671691630097, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1744,23 +1784,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAylOKbF1Dx62tepHXm5pomhCNpInXSHtKVW25pvbV8JC2ytLp0gyvWn+Bc70tWQsD1+TCpP1hVQHSQ/Mwzcp8DqWZKiElc9N32/VnY8taHxmAJ1JSo7AU+tDoqVS7DqypZ4apf1R56BtYLUcaVEqeZOn6JONG6gVQhfWc/FJxdD4VHeGqFyrwYml2yr6Zq5xio9abWlqaz6pUOffi962z429nsLNPOEsZx2JvI37rUF+C7tJv7xmrfFKV/59zbXkUY5d5skOO+bw3M//VrAFjLDtYkB1VsqUxJvy7l0Ke0Dx0CYKU0nLUqScgJWvwkvdfbxYpXPd619ZTUIHM+4gFOnzUIS4L36W+MB2WlgaugXwjKFoEff/HEhd9n3RqosNnUs4+MlfPiRVy1sRfN2EYTl/CS6FFSyGAeXaZBcIgoeUW9saFACPD1sXheqa7YLZ0yEq5AvQ/nl4r/3nadtEmuQ8QCj8FBIZ81GXAiwKvfuQhoUt2T1frN82bC7QDh0GGpBBZFhcKLlPdxOb5wFWLUNRLJ4DYvHBYrVwR7MNFwM8igchvW7tv4DP0Rf6LLWwFd9mrstFCUBqs10Ot6N09BJdbzyRN+wVJC6YMtJELTkz1RbWUP/A15Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwQmIzMOESTW8266C/hZsw1T09/Aya3fR/eo/srmMnM+zzVPTTrhS0rPTxpEfdf8PGf6Tmj65ujPG9iZl1W1WmAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAy+8tm992AMm58jS8JxelNkJfxW2yTJnG3Za06lponoyC/5GsdV3xjgduGWeQqSR+sidVW0LN/upHluNqGt1PdhPrK04r+fh9Sf6Fl+5MuzKw4WvmzInEp/USy00YsiBIeApGymm1y7qrxGN+aO1LHFCgddgSJOm5M5UQFtpWdv0HQ0C98WIF7HSBZ3E0vFUB1w5KFyC2RReFnGHHmFicOaJQ2H71jGAEgbtgpmb5oxqnH6EZ+9ZYWrVyGS7Nm0oFQYmaU7uGQFl2aPDe5W7HGGWvNK14s8AqYjETM3B84PKl6dycSyzHFDbzXo2J2XUJpM9CDVpSOZWDlEmWichO3HifQ4GDSD1r2tspxyd37L3xZW3Wue9ww5hlyG/6EWZbpo0efZ4ef1pl+peFKNLlSzJi1RYXCAATZAOyI/cscQdnDVpHf9Crf7IV64CQMawrwvxaAO0t9ZKynZ/fsZI/irNni2LSa/JF/IYNydYYXWxGvpVyz6qv5zgqQpfr8VROM/otStu5N3TgIO+KsnqE4ucrjfIcuolUb6NdSbICnuvWml1mP7bUNuv5qeHziXrzSrWi4E6rUZH2EUg7Xh1xYMTWfhVsS6Qn7egc2bzNR7m/QdhG1J+TDUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZpdRlmdoeB7v0NJUDtQi71NeeOPUkdhj/ZwoQxGHduFwtmIdQ3TjTYmY5Fm8iIePrAumRvwJ48YS+GqhHo4XDQ==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAJoaULVwBT1qM+8BpAxD268z2qitBX8L08DQtQIypu6GU6+/YWSoaW1adjKVLj5+iBLoFxB8mNynmv0AE/c9nLPLCQ/2AakSFTs31LuBX+2mUk1PGsw294o5GKWQkCaBW1sfC88zc/RfrNAq8z5QoSs+Zpu3Eb5zl8pPjuyovDEkBd9CZ6h9fSXXrE+JqBevHy5jn1OkNQe+3haI8+nIIBaR+6xLN+441EUuvh+NRGruDksfIdHWxoI5O2ntEPDrlTccaSseFDqX+8dg6oIRm4EWGqIPVnPbtw54+W+AgEMvWf311es4ZI2k2SzOWuJP09h9VURKu824Zyt6ReYZZDpiACxM/Ib5IuZNXsjkAN14HVKsSlMW1pfL8cmd3PXAuBQAAAP8gWUaTqCxJvvByHyMJSMZIf/ayXPQ9IJJ8m44Mb8FOA9RuZjcJBxs7Ege7kpWF4uCwh0pKXcHXmdU/hbdYmbHrr1SadJnn/oyh9csXXApwhU5yA/8SuA0i50y2p3xZA7X9Xsf81GYttiCo/f1pSbvam+Egk4LEVRdY8o1mTnzXWQrE2phi0G3XWtDhNy8Fbq7VnymHD+jf1h1jOtJks2AWwJtKnhiQp8exJnaNCr8mu/xFGstqzugPfSu1HaPAnxakWPWxOHxmF9FCc26lyl10OUhWYO/Olfahq6eupd8Pl2kp0/U6zqgQ7Dyao9lrg4eldkurbUVsT1KfqdCtGzDwrEeBmqUrej5ysyh5nHcBKcIH/EfrysmorOHTDTbcSpyxUJ4jLGB1dYqRUZWa1QE3arE9RnFHelE+6rLmqAVTHC7sl1/kIhpTPV5ABxKZt92AX8Vr0Qmz1deMn6N/o00XuEnlgmLM5gb1bJveMVtcP+a5/Ir38hocXCDtUYS8g8ymQiFZejoV8JdBv3tm5sB6Ibb9teuTLs87xOqXbwkmwFarA285oHEYI3WpPro9YR9yqj+wCS2KyY8iltLebu3rXHm/SkYuOvJZ7sZMKJc8LuJWZhifxC1k7jXKhSf6TH47oE5qj8n6z0GSJ8ted2FB4bVnjvwolpUujeRf6xEguGamTYde3+sYoZw4I/LD2Ltt0bus9fRkETo3VxanZqbO7I8TX8tC0Vu5mGBR2/NLfTeBo4hqcd1ecmvBmUgHf7UKBePwSvn742VJfmP6ocroEcpdbbYVJilSaUVtAnZnL/HjXSuXpoR/Pg7e1z2mhxwXiFES2kzLwjQQYNE2Fyg+4XNtPzsyNQMAAAAAAAAADxliPkw3RQ9c+eLbZcQjY4nSjNbKkrqr+uYqX243atVEuZxQZvBrnaC+pg84QQ07Bg89OPl5TbijxktGHFfOAQ==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA6iY7Qu2D3e8q2PsKK8Keeiz1kRe2+IbwfB0IuFrSoSyth40fiicPdJuRyNF6VTve14Xipersc/+ex66K9ftipE4Gjx/See9/0ryZE/TRRGOuXCwJH8QKDZhd3fesTDqpgnIuOfIIJlwOgwtQY8zo2jFElV2+tlQGcC5C+ZsQPIYEhJyxplB9IWFAP/3vtBZHUWTdvryCX5tMDtEwD8eBaWHMLOF355ztr9AMaBOdgWulddAUWenMXW214WNYt49FG0gnyjyVru+50/uux1bD5vRgaAbxeN1qR0/aYnh2O3D4WtsjJmmoOg5B4fe7zMbMf+ga8FGj16dRGn1irMuwmzdawTLjHM23bsLKYL14ch+cfwCZWcp3JDlNREOL0l1fBQAAABvRlx64RindDmYOIgC5CBab+ewd06zQptjYpjHZWHxynr7DGO+DlwQE/FmgEV3t+bw1rEiW434vItuaNBYOaxOZh416wLGBY/BRQqfDtA3LmATWGzjdKRns7fLh4njrDYoSMZY4pECwpoo5+FLCeIGtDaEsZZ4PTmer8QoJp6iaHXmpYPMVWU1JlwXdf7lyt6bSQNH9vpB+zn17pPZeyp+pu2/YiB8AoURiIzSwQC/Wpq0sHPlCQhAuhF7lqw0uyRCPfaJCinRuu3p2ae0rlcj0Q06UaqmSevl5UYSLPcI6yw0Wj9r2H8lf7pXSy8enToadvqz7t8fuhL6eKIJCHB4gzrIHnkyS/EmuJqdQIojUDv6Owv18I6+OlApxVdSPJJqguoMbe8wVlm9aX25R4PoDCmRn78M6EI1qw57t3ZRCodv9GNqcjoTiwKfmUbRKebtCJohyZSJl3ozig/IEWRJtVSaDCHCJFQ1RndhQ1h1YpE4dLjNp+ROmVU3lR91fPxwoUZP8GwfJXuIQJMW/46oGaK6+wBNwsAfY9whyb4wQbQZwwoeVfJkpcwNs0U5YjvfEAq771f+qtV+HmgQYj0X9sd7TiFp1kameg/KCGLRc61oexS7bx57dqbt6/cwczVr3ea3Fy+2SpTV7xVhdio/XYlFWWvW+5lmzMvg9ei5kx2cCOLRfmUInvTqUqMUm9Gwh/Lu2lNCP4zooIt44SS3oyXfYKvP/7KQGG+Au0+QAFj/A9nN5nd57IS0cSyCndWQvOG8+checp2v5FdaqXEP7alugCe2LFUMtnye6kxkiCjqGr/4xvq/4NIXfWRkkARxKaTv0VE0I+qVZNxvFQdRd6GgCColDWQMAAAAAAAAAlqn2Pv7ZTyfwcsTyYGLHoQBHMsxdqApy23+ij09p7cWDud7G4sRACicjYdD/Uua7nrAQKH9PsTHz2Wor+eIzCw==" } ] } ], "Blockchain asset updates when rolling back multiple mints and burns adjusts the supply accordingly": [ { - "id": "00f5bc7c-30d1-4d12-8f6e-e75b3fd9a8b6", + "id": "fb758fbc-02f0-4e04-944a-5877972ef3ea", "name": "test", - "spendingKey": "8f2b5390e4251443ab4a342bc38c3251746beb1bd19b02c83b9fbbdf97e13219", - "incomingViewKey": "2146f6e4fdcc627a7cc1902476ab22e046378a26025e6dedca113c034a2f9f03", - "outgoingViewKey": "08f7e95f778e129e2c6c88fe453c773348503cf6efb0c8445fe0ad490a898851", - "publicAddress": "1e8cdfd8fe5d3ba463e41c52b83c293b55646f339e82af3bd8127e43b2d55c1b" + "spendingKey": "8f754204c8a863e848791a497a4e70675a5d4c262c1b0e3df6470de561c66bb1", + "incomingViewKey": "898a62efbc83358bbfaa660f1d0144de9d22a50394033767d014310fdb4f2901", + "outgoingViewKey": "4476d500d6291f2e1304582ed862b8eb133c878a1a8a20ac64ea26d03b582c35", + "publicAddress": "fcf62294a833f61640b1e1142c062b733ff708fbbe83bcfcf91ca9b77e36f99d" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU04Kd9pFvwOMSArXSCAqK2hSUbnbSCRQoas2SyeyU1uOf+74wyD9a7nYs6FcJ4RIaEdlQGat27d+JOZ7nIYM7gWibEEDdauOkKP+rsEbLXqw5O3TX9dH5RnXLUX5YImWBQuNlbtGUupzgEFafDTo3QTvd0pCz97AKtAfm7Jf5T4INftVjFNlY/7wW4cVyW2Bkg4/eq5MtTIoKkngg9pAfCLFIyWO6EI+ZzdwtLIxaKyUXysD97L8gKCbc4YkMNNIIfD8/ExqpVIibQLIUDdk//PaJlc1OOEsY8cSABnTMhzcJtPh/8is16f/zAbpc4iawGcm1Ahoqjy2Dc3bQIOmYyZp8xv9HIEavj99c/osfATDnUCBychsvQk5dh3r7bk3v9nHh2YKMdI8/8h6acxoGa3E6T5mChd9zOVe78euL+5W/cxS9YspkBm5p8cx8HN4wbyRwU+R+jKdOd0UFoucMk08fLbdiLgFUYaja1Ct3ZNe3S+2sH4nObOrph183CK11SKaT4J/3w8+BLfl+iXTlmH9ud3QRvKo3rzxDlRvG1yTlYlUorYu4WDqaZ1FS07GL3MGuYYwEcVNqPRSi9f8g0P5Vl/xOaXjsHqLpEZrKF7EBWGYb6Wp/uqYZ7scgwiUATmrdcDlDTxl3sdN/sAL/k5/cGq7hHaKjZQqvcjI3LccnQhWIh6Te92SLFW8/zovSfoHlq7G2Ad7O4GzBAOhvs3A9dqpptjkhkKJ8CIlddZ2Nlem83GBTDWx3u/A01QuFO3UNPiDP3xM3GKY3mVrM2vTMoM1wOOMrrUaCSvjuCHtIReIGSZVm5KgjMxGLVRZolc9YzjmSHEPKCDf6aw0d34+rB1mhkl5CCmhNhWPnCiMHvLj94yTcwAkm4GDyWElKaAKTKaCG1pQcHxul9lcBsxN9fzzVQDgg9nkXlKemG6fYxlcwkWazVAcF3TgetEEerb0NebEK+C0vFlS0tJPtRWxK0+6ymwz/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAABwmgosHcHziBmLJ2cPO2ZiEDqBWXIgTNVMyGJbsmj9Ls6tZiQHG4JLAMllyLktEew1h8UahUWpShF3521jfofC0ZOIgaIxJVK1Uz4/bCsQA42XzngEESvnHVwJyEFAUQulxCqG+R0icA0bZP4aSOqxbRsI6mdmj7ZIu0aqCeW1gEXZSwnGGzf160KjhkRpGYZ8AezmPW2m9m811wpEY+UK" }, { "header": { @@ -1768,15 +1812,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:E1+98+qos5nVPd1Dof/AJqbUJXGqP9gdpOpnWUaIcFI=" + "data": "base64:0tHb8Dr/MQeE5axofQcKoIgBcOJ6b26vnD6BnYu15iE=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:zxvs1kUzkP3jE1Cs7gcHd6Wf5MdZbLuL+8c37J3Eo4I=" + "data": "base64:CpVhM8giBYvIzodplv4yxgA/RihWTpfPjhHkKe5ScIo=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470855079, + "timestamp": 1671691631133, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1784,29 +1828,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAzjgYlxPyqcy3ZDv+i3uZr/1BFifwtjwbzcKnK4Dq4s+RCRKgwWOFhYCDnrEYhXY7QM2PLXwO3NvtHvFPOT4/U3FRVyOGSZssMMNu2QzMRMeDcKx/84RifRhRGcrSN4zBVuGW+QGWug9ES4l5hTqWsi6bqjnAGeC/QGHxgJJNLX8OLxE8VZhaXgBreVWKZPyk+uw6USOMFfqsL49zMeTZm1QwMq06xvEV06I3VfRgVMCZ92FQRYozPWxqLPWyp9cpBzrI94WoTu+BIWaaQg1GCER5/FR6baWdV2xdpxkktmKDzu/AoYfJP+1256TCEuSHi9dTpfUxZGEbBczOOSe1sNKfyh4UDv9u8aFAtA3w5cIItTn8vQieb/H0yDsQOK0hj5a9X6laQQGkXQM7FHFKHJehZxQ8QZCEyhZlSUH9WRjAnjugp3gV13lngOTJR39ZiCS9KDR+tla2qk4W1lwninNx7uj3qu5zPEFp7tVqgP0cBNJgbKqDUqUgu/v2rrhukGmqAVsXwaQJrzgzPmtMtp1DBcqFYc855pObxsCdKQIL92NCn72Azn9RJser3QN7cnV7xH+jBbysarShiMfM0ytC/4H4jkVGaSS7EDUSTWIMVmuUYfOT4Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw4LAmx8nIa2Ot2sm4+GL019YUSvHpfr/7HQs7GNxAlSmug45DPeDo8zrm9YN+nkETThCp1BS+b0YaZCpKNj+VAw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAANWhSYSxZFMLaUhSZwjXLjO+sy27sr6jLVPvb6bodjDGjZkkOmhQuwPrwbpvLSqakX+cgqb9vcJBFQmeMcKV+rv1qCZtD85ahqJLyRh2C3syl/64YtOlbTrA/QSQvEhP5XTEuyBKA611CBzTjqmKvsSq1+K5tMKBaLbUsBiw4j9cRhEhtkjXJhs2R/NGUYd5U3Gp2YqopX4l05sJpv5OFARaOsB6nDQIWe63yKVaP6myNZRSQ7nKwbJmGeacjJ2SWZxOYZd5QtFK8YPO5RWy5YVoRQNO8vq0XKs5U92pSOZAi6i7oWna6kKIQnUeE+mFVBKlf8tP4RuQvB1duO2r2PfjsNqKaKMYYUqvayLPrOyVSnHsYaE52XYpbGS0PQkRdZhEfYrxNSt/FdYGd3pxRWEh3yPdvp+uQKj6m0a/tyD2RnviHSp02FVJWAG6/lObjiR9QSmBbJbQ022V8rusvXdSjSfodD7hFNR/p+mClh1DqfYcoTDjsCMAepbhythk1mulyOlYddBmkTSBJuJmXYPm2McjDrkaSZ4IwAphFxbYRXVK9O1cT6O7rPQPwup3lm0x4wGKV2DKf/nbBgmqb4c4kt38QLNCi1abnuTAoFllA5Q82lGwiSklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwliRqcctUC3d2avCLnPFl7TTeuFda07bAa8pyx+2Sr2grkA1RbanGWQU3iegrBLg8YAT+rxNQ72y2b2MCIRt+DQ==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyh51S6xo3unpCAP0bNhvmPtFiaTpJeRLGVunv7Ra/rCxWacgV7/qMQqjMe7SkQbC/BYH75ZnuRd67k1U1wJF8pbBXXP81lrD6M3kQYGOP/WmFk73IfhA5x0CodiGK4xnXYqdGegS9L2MLJgtMHRUNo/aA4LlmQPCQ1R25hzlvNEUy8YG3bd32QQEvj/I3Npc6D8s1DUowEpzJ9Sn3evDq1szbUoIJF00I7EsQHt/IzikGFi0iUqz7AHTrEwGLY8dSYtPd062ScQKF0uXxowEPUOjoyHdpP2NvnVmk+8hzSE4uXXrfqLEgW7scZinq+3yP32c3n7NRUGj709TsmR3271xR97HaNAytjbMQ7L+R82uyoFFB2qA19VklUBlCtFlaVxDHetnFL/ksLpUjNAfPur+5Sin9QfnVjAAfiClp0VVPmLsboG4VIcvGNxVHW7GMWmLiEw/mj5seRZi3BDRwHcAijtHH1JRJezRpmtaRn5nMVzlYJrSOtkZN6P+AA03hX3cF30zSkH0bRa8eDCc3h7plTdke+L1oLcmcp/NvO0M9h+pUYNXtey/ZNn8uBly8C2TS1lvD3ELCRqov8U03/IWPvCd1rd+xt3W82U83gEe6LQIITJ74AbNzZ5sAIMtZm/zaUJwcb4MGE4GaFmKcVCYdY5oV6X1/oX9QGMubMU49JhqWR3CtWhUX7lvsEwCv8klVcHqVJiD2wAW0E4IfvhuTXQYGMdLk0GqIeH7t1O+F6Vz3tBkxjIQmRfZWDOKcWUs8s3UKu7ypLcU/4ZxqNYNhTRJa5CLts5yJdQjDac2j77PZgZEvPNmfzc41Eki8Lmf5iScWOM8xjHpE28JxSgqwZ7REA5cEH3hfHyltfRPi7dvUuibzAhc0YW3qC+qeffAjK7e5OmVtlBv8AHla2xi5B9lR1MRg5UrmOjZPvXfk5U4IAfmJNTSOD40RiiY6Vo4E9JpB1prYbbI8rsMd9d6Oyy5jsBHHozf2P5dO6Rj5BxSuDwpO1VkbzOegq872BJ+Q7LVXBttaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACMiXHY7MVALc1IXIjnThVLbpwZ+JLmCU+NaMO+AJaUk57gQj5fqgP9Bs1pZbxKNh7z4WiY2/nMN1eKWj1QYUvaMuzgvg/mQ/fxn6sC9JPvxrapTBiruNACjkoWAql26AlHm//xb0HurNIVZSvJsrdU70f0wLH7dzUMSJRcK+BmOYRRHdVWkapFfo0LxIr2TqDjC2zKSE6diP7Pz0YOYfgJ" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU04Kd9pFvwOMSArXSCAqK2hSUbnbSCRQoas2SyeyU1uOf+74wyD9a7nYs6FcJ4RIaEdlQGat27d+JOZ7nIYM7gWibEEDdauOkKP+rsEbLXqw5O3TX9dH5RnXLUX5YImWBQuNlbtGUupzgEFafDTo3QTvd0pCz97AKtAfm7Jf5T4INftVjFNlY/7wW4cVyW2Bkg4/eq5MtTIoKkngg9pAfCLFIyWO6EI+ZzdwtLIxaKyUXysD97L8gKCbc4YkMNNIIfD8/ExqpVIibQLIUDdk//PaJlc1OOEsY8cSABnTMhzcJtPh/8is16f/zAbpc4iawGcm1Ahoqjy2Dc3bQIOmYyZp8xv9HIEavj99c/osfATDnUCBychsvQk5dh3r7bk3v9nHh2YKMdI8/8h6acxoGa3E6T5mChd9zOVe78euL+5W/cxS9YspkBm5p8cx8HN4wbyRwU+R+jKdOd0UFoucMk08fLbdiLgFUYaja1Ct3ZNe3S+2sH4nObOrph183CK11SKaT4J/3w8+BLfl+iXTlmH9ud3QRvKo3rzxDlRvG1yTlYlUorYu4WDqaZ1FS07GL3MGuYYwEcVNqPRSi9f8g0P5Vl/xOaXjsHqLpEZrKF7EBWGYb6Wp/uqYZ7scgwiUATmrdcDlDTxl3sdN/sAL/k5/cGq7hHaKjZQqvcjI3LccnQhWIh6Te92SLFW8/zovSfoHlq7G2Ad7O4GzBAOhvs3A9dqpptjkhkKJ8CIlddZ2Nlem83GBTDWx3u/A01QuFO3UNPiDP3xM3GKY3mVrM2vTMoM1wOOMrrUaCSvjuCHtIReIGSZVm5KgjMxGLVRZolc9YzjmSHEPKCDf6aw0d34+rB1mhkl5CCmhNhWPnCiMHvLj94yTcwAkm4GDyWElKaAKTKaCG1pQcHxul9lcBsxN9fzzVQDgg9nkXlKemG6fYxlcwkWazVAcF3TgetEEerb0NebEK+C0vFlS0tJPtRWxK0+6ymwz/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAABwmgosHcHziBmLJ2cPO2ZiEDqBWXIgTNVMyGJbsmj9Ls6tZiQHG4JLAMllyLktEew1h8UahUWpShF3521jfofC0ZOIgaIxJVK1Uz4/bCsQA42XzngEESvnHVwJyEFAUQulxCqG+R0icA0bZP4aSOqxbRsI6mdmj7ZIu0aqCeW1gEXZSwnGGzf160KjhkRpGYZ8AezmPW2m9m811wpEY+UK" } ] }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVce4DE5bPaeVW5Y1+4/t705Gm/j4UCdfHQDTKFbnMwitUCRmf3jIfK+/sdwECIExwcHKibTUdDsBhV3UGf7vlrHX4JrftuvjN5enrkbasEOAneVe0wblQdy1U0vLy3YlWdwk11rl4yagYboniwyQjy/OdR75ccfgF57m67OS3pMU+JSKUAjbvwL6CpzGa+8zLQ4eKf2AS2XjkA62az76vt0eCmRXqpZP9vGuDJnrX6uR49cmAPqyHGzIz+Ui72fDS/0Kug8nYxpGEhSEZj4TDlubkvUet/8Enhs7b1prQN3bgt7s1EvYn8/PwvUTJhWOThGLNaIFcT8k+j0TUosFYKd6saOB6cuayAPCjl5X7KRGefDNmk6NYvjjHFfsHIov/l+gRLiTPRzUXP1T6q3bLT4Q5BdoVgKezisae5ZLcCRuoMkDOzC0SV7NL6fpGFjLZFXddYfKgJyuJQGfC6ycPC9tBkvJ8jEhDQgxuKQiS7V+5w4IJbCHx8RVmJyeuj3jFgpSI0FKGZCw2jgQxlJDhXlBB9rwSkw6RBch+tK5ChKsunwlnz05Xf7gcCJQ3PixVJbS9JajaRNNXSeD44WRpYm4W8TtCxVDKBeIyRAVwdNZNRyHlARW+VbAYqNfl9ef4UCQDOXO025RO42wWYKpa2ZkAtw40nYQ32ofKVm4JH/PdUQXXPRhH9jXlspLN4yStfnD/6jtXpLz8Pihi17nWXHNoOADnwQvhHqZWiPVKNB2i+GeTaUEIJc7qoSVpftWsJgjU3/lVOfRGa+b7vX46hAXZoSPqUrStj87os9vuEkSSjPx6KJn1GNUYCQ5naWpv2BXwbbxZbbLuF53weiwWm3GZsA72zDmB68vF4l6its5PwzWeIj8x+x4vpSLW19YxsBs5XYj3MJsqfDSBnF7QFV9lyZz8ny0pDf2+i8YizMRDBvnS/EOPTA7s/M2dIGdTc1LbCTDmPOLrVmtKUSfs/eJxZzSuVre/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCAAAAAAAAACBYi+2PoXr2CaFRU/K466offXklE9RdluTZ5mUrsIFLHg2N8zvRNNnFPmCS4OCmvIL3AXZ3nRbZ8LOX/I80rZKqVKAp5Jr9ozwbakXEZQnJbycJg0ohuJNx8Aj6MiYCgct/lEAv2UoRTgKmtH/GUFufSDj6Ec6Egs3pAjp94MDHj20lqyWRz+Oer/pxyPwvjDiok6wqtFh95ttO6h2GF0D" + }, { "header": { "sequence": 3, - "previousBlockHash": "67DFC436D5FC14AC5346C5CD24398A5C25189EDAFF275BD2267A669FA8222227", + "previousBlockHash": "00AA7282E8DB219F207AF0A0813838E5E13B2EC5D011335C4D36F704284265FC", "noteCommitment": { "type": "Buffer", - "data": "base64:PDgv9AKfUaRGz2BPL5hb6WSiqoHJWeKVNmu9BKZ2WF4=" + "data": "base64:0iNAwC7MyXSdOycrazeanwxoJHznh5x7qmmdfAme4gk=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:lisYUCM7R7hRFr4S1SqpOPTTKvkI4fgcW3WQknxphnw=" + "data": "base64:vANhBLy4/XLQ8BGhjyyBIo/74oCvFme6HPO2FcH/dJg=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470855919, + "timestamp": 1671691632046, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -1814,29 +1862,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAewotzTcrmzgUDj+Rzgm9ows/tYk4mw+BAgfW7wKRl2aYbPtIcmDEaKDCaamIFLXbn6BuOP+1GS9D8wKemw1KQLGAfqv9Ux/z6LFlSU/xOLeuNvNKWjwA8joiV+dxHOjdTAIU1cON2/dtgydJ3hzDGtvV6bmOMhS25nfiB4/WNGMO87ndgVj1GHIzNmZPQ7h0jNKbi6acyts98B+zhz/0lqEHQLm5XBCcGQDXkltDoSGy60DzL3uQilY+2O4lZWuoAIfMLfix2Rh9hMXit88WXFu9ChsqarBnroEGnZIRWUkA4XT0z6z86u7yR5AbJG/7G/D7QgT2eOaRNFN2w+0SGuOuaWAbvRLO3ms/N929BOp/Yxr4HVbmZN+B8C5gYO5O6Kq2XnsNG5Ygq2qNxSSnzaJ/bl6/TwU3dxR6HPEGOxE+rVUqF5qzWaw3j+U0dY2z9SDAiwlYLu5hJkOUGamCe+ncFxAcrFmbfyIUtyr177HPxgofS/ls2dQRzIXo9QyFpyDfRSC27M23Fki5On2kKhya52A/31Bp86r+ddXHK1s5ljOdB/+9aMczOgdhTBpIwZV3N792ftNN4SzGpF2/noQVpMC5PqebTreCWyIopZrvEeyjbXbOEUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwsVt/+bpOAwCSwgEHHLh6cYX0jG1JXBdzLN6sV6jAotQelEz0uQli2MmNnFDPGEBW4dzn6CHm/eVeknFbOg0oBA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAoE7UvMMvSxJC8uWgN4McN4R48ABVRpUNx4zs+vMUUY6goZtQQNgQpe9p3dvUWlpHJmlB15LW/LyPXn32U9ivRaF/EKDqW/Gry46TGruw9fenqAA4ShG9p+JlLuhDiMCms+OD+nmdO3Iuq4WzZxa3rsy7hOydwJk3QK7jonGJhwwYGsO44zyNhyo/xLQN4kxCvFmgDQTAYunTXGOOorfyHB74FdfIe8H7Muf8CmGtVq2DgFdmkOLTy8og+uuFL29qUBkAURLqtmM5QkIcGJ5h1Ml1Wf/j9n1rEdTWZaCf+DeslCLmPzfgaC/rxLvJx8ocQBNRXnOphOyXdjFjy++7tY5AOzBpUE3YnfX5OZZHtuYIdR42HWNRXvs02/epmIsViBO9JqNHGQpZ+sXYV4Evr+ETZrwK1yMmyOX+JlaKL97hOHPJbrWHiczby+Psr6T3/fUfi2CbsvKs12ASrNF0yIfUCvP/6BYv7B4Lim0hjL3lnYFQs09RuQhs3kRT+G7TGav1qm+ryZldNBkAfmewmz4Grj+2YXXES/ytL9w001I9ZYzMzBKZ1e4UijSTGABY8zRYsXHVpEL3iPn+2o26TDASX0VAArlgA0pgCEjEFjfj2LNtbJpMqElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw33+yhc3ri5uqhofJlVRkTgPirfogjEB/jNvAhNDbQ+5HAsEIChu0HxOKgEd8hQQvWxekJ52PzQj20EQGTYW3BA==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Hf0cET4eMLEvoGQMEubnlfFNeMTZBdeUAUK+YS8DRiEuW12XZ2SxxTbjN5fF3xr/MpzQYEjzSd0LKDrHQuOpxu40Le4pYTJZSCXQYyL/rmDKdBB15gqq9dmpIGv5u9y/xWW2wJdkE0RCHv29ZaZEDOeCVDkf/9gSvH42DoPvd0SdtcWUpijuT31A0qKqitMKDXC8LyoYnKcaZNegVAP5xvRhRF0IZST+rsHzZjJ2XWYYz8EDpIpLDcYATpMFtkSlTBAgdn12FMRQEtfP8A2+JRpQDatJ2/yvcm8U/F/ds4GgIp63AipMtBktEAsU074/nnJalMX99ITjxe9U940CIODkNR4Vi53DUZgMDzS1o8Cx+bND1VlsJIthzOMXUpw24YZI74JeHWkyEDs6h05cvdJ4Zcs0FFOX/do/w51aUrCzr88aWvVlUq5V95z4qLw4sNLm05xRyIAbcXl8F92HhoPOx/pcRPxdWu2G2nXjFQN52pkZk1Wj5pbZJGqx5ZpBM135gLW5XtTYBDIfBOSWCi90e/HQuy+o9nojo3MwsaMqTgk9opP38SHUzFGVfb4wuIYeF59/AUkEPCmeQ1siUt6+pcgtIc5DVYN3IXQwnlxlqUl2ig7enLa/JBVRIEW6/xj/vixFIihrQfQmUD7BOebaWzXsF3MIWZBnabYYxVsJ9Wsa9Kuog3r5V/ulZDc9A7zfG9SY40g+3i4p0cUrqf20dS1TxU2lwZWiYnFQohgxXt7wpN6tbWuaZbVy2bV9iM8GaLHdb9ou+8+mAIrb4SZmN+pOLcjp7K97Ig7R/tAf4i6mz1ZEUfbvs6JOQ/Ivq9KS4CzlZl3y9PX4KeIgPqxfr2YOJzHBd345RzbLANM+FHcxrqZx2WAK9ym2KTS1H+jHNFm38W2LMQALmxl9SRS7ULhpJdTmGiIScgl+QyWZiRshm7IEitllZJ4UHMtZsFWeMWD8WaMlbMSQG5ztrKJ/Jq5G2EUHozf2P5dO6Rj5BxSuDwpO1VkbzOegq872BJ+Q7LVXBttaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAB9VM3nFNVgNWPQFP9FeBppQNAQD3QTa/57LE99GxINAzfC4PGFgErfmiVTszzqH3EdWLJgmB0y3eBpOUoIiENwyussbv6LpRWlGiWWP4YZ5eQkfgP6n3mZOqgL+IUW0QNH4GYlvXWtixpETv+0corR1QUF4Wo+9QL1tA3Uram0VobiB0x9RmjGk0/xD/W58mVESElPGS0FaqQPOBzhnWQA" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVce4DE5bPaeVW5Y1+4/t705Gm/j4UCdfHQDTKFbnMwitUCRmf3jIfK+/sdwECIExwcHKibTUdDsBhV3UGf7vlrHX4JrftuvjN5enrkbasEOAneVe0wblQdy1U0vLy3YlWdwk11rl4yagYboniwyQjy/OdR75ccfgF57m67OS3pMU+JSKUAjbvwL6CpzGa+8zLQ4eKf2AS2XjkA62az76vt0eCmRXqpZP9vGuDJnrX6uR49cmAPqyHGzIz+Ui72fDS/0Kug8nYxpGEhSEZj4TDlubkvUet/8Enhs7b1prQN3bgt7s1EvYn8/PwvUTJhWOThGLNaIFcT8k+j0TUosFYKd6saOB6cuayAPCjl5X7KRGefDNmk6NYvjjHFfsHIov/l+gRLiTPRzUXP1T6q3bLT4Q5BdoVgKezisae5ZLcCRuoMkDOzC0SV7NL6fpGFjLZFXddYfKgJyuJQGfC6ycPC9tBkvJ8jEhDQgxuKQiS7V+5w4IJbCHx8RVmJyeuj3jFgpSI0FKGZCw2jgQxlJDhXlBB9rwSkw6RBch+tK5ChKsunwlnz05Xf7gcCJQ3PixVJbS9JajaRNNXSeD44WRpYm4W8TtCxVDKBeIyRAVwdNZNRyHlARW+VbAYqNfl9ef4UCQDOXO025RO42wWYKpa2ZkAtw40nYQ32ofKVm4JH/PdUQXXPRhH9jXlspLN4yStfnD/6jtXpLz8Pihi17nWXHNoOADnwQvhHqZWiPVKNB2i+GeTaUEIJc7qoSVpftWsJgjU3/lVOfRGa+b7vX46hAXZoSPqUrStj87os9vuEkSSjPx6KJn1GNUYCQ5naWpv2BXwbbxZbbLuF53weiwWm3GZsA72zDmB68vF4l6its5PwzWeIj8x+x4vpSLW19YxsBs5XYj3MJsqfDSBnF7QFV9lyZz8ny0pDf2+i8YizMRDBvnS/EOPTA7s/M2dIGdTc1LbCTDmPOLrVmtKUSfs/eJxZzSuVre/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCAAAAAAAAACBYi+2PoXr2CaFRU/K466offXklE9RdluTZ5mUrsIFLHg2N8zvRNNnFPmCS4OCmvIL3AXZ3nRbZ8LOX/I80rZKqVKAp5Jr9ozwbakXEZQnJbycJg0ohuJNx8Aj6MiYCgct/lEAv2UoRTgKmtH/GUFufSDj6Ec6Egs3pAjp94MDHj20lqyWRz+Oer/pxyPwvjDiok6wqtFh95ttO6h2GF0D" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "5FA150C03FB7A7F7854E61E4005D7CF680E678F76B5D90AD049069DFE1A331FD", + "previousBlockHash": "49D844AACA33801555A627E882A0957AC536F8F90598BADB4E5D2080389D88A4", "noteCommitment": { "type": "Buffer", - "data": "base64:a5EnKGZtJ5loQRTqGHkCLMeBf8oZmVAiRCLpKaT+cR0=" + "data": "base64:H/LB0ruBWTv4xMAns/gEYgoau0bFftvLedIYHz82Jy4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:Ci4yuv+WesfMFxc2YftnZkznKq6gOf9+Jy+l01Q9OVQ=" + "data": "base64:q69vi2qklnY7DAU/m1rp2Yx6kFJQdBFSAc7FOXBzaig=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470857327, + "timestamp": 1671691633533, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 9, "work": "0" @@ -1844,29 +1892,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAaHiuoeK43fYOO3IWlGUIO2zoHuWEtflLdzsV5++2cESwzwGF5RYmLKB3d4gausLSP0TSyVYqSkBmxiyFRWEP/QCbBhG3Wj0P4bVSaiQ+77WwnlRPNK++d2ugCxn06evV0DGcC8YHMYsfXXLB16AkB/VEzvFkhT7rL9nV4hGW0CoF2jLhdZhLRs3sUfIJSfZOU56fWGqYeWcZaxt8/jkM8Gbixo7TS7iDz0bEQ5Mt3PmSVuEaAjjXMW1im1btYoSmdqgns/1IZ1nys3dkVRO41qVj05P3uZVLdEFVelNhXUKoTU4Qn1My9n6cJM3QhAwnvwLrRZ6616Qgpa+c7VpiMMfKmwfKnUULo8BjiZmhYSV35SX7mtN8dTpvDDIY7+osjQBgcQEvnFfZCBKrCkhiFoi/hJtVP2QeP71hn/H08BkukUVfhXIhRVzOH9tLW2BBC2F9qnDzeoUL+tHIxTeeErwPz7J/weay2uG8tNLjUYzI1jf9o4n40HTlJDY6rxR3gtDdsViDRsX7LKY4+ldvbOk8ruB6CeqO/m3Yu5vb/Vt4l2spJRt4pmmtypWq0w8+dYqeZSl/f3w71oWFj88yt14IfDTVU8IR9idtpOul2qbxzGNoIb62Lklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwXfatTPt+GEoiZdC8KS7Nh1l8zMToYSp+qOyB9FOu/xgyYod2oL6cBWoL235/oa5Lpg/a1CHD2eOI5/ZiBDgNCA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAkk/sQruxS4h1kyBOdUUSzGPIMuq3mtsBMQr0u+lH4tutKQOWTQcqmGMzUZeBfIpcTjMAFpBXQbZ/sg77A+MEIPRrTmsYljmgGslTkw0a8iqOYk3r9g/mo8NPcT0gQNqVc/XxD2RWynqIhdAEkApaAmF8WTkA9RQtvfZcercAF1UWMA6sML1lnBh1fRT6cF4uweAUGNHJcqBZYkPxxbmlGjGcjv0MSrFxi9+uuj4IGR+TCPilldXPR6qFj4k5MqTTi6/TuhLD8Fj2WBQAkZrCqwwxdSbZIKDc/yrby+SKpGCxp7VZC8HD9m4xymqj/OYFYbojESfWOm09QYTkIOwYENhvQwvFj93ASi2SqXnfH7jq6K0j3WTIvtR2fM+yeiJJXNz+G4BBJPgQmSWBUVvKlRxpan/XXzUdRoyMQtmKNSWBq4fQazJ/yrfg/MpvryYbKY8TuFmSCOPP1hnmh/XmC5QwL3YfTRH+oBKRj4UhYVUFHHPisB1cKq3Ne+yLrB0wn9gZD0dQh0QOtDK92ydQ83V3z0rAdQRz/jEAP8eG6dJYaDd0EEKLvg0v0aC3TRaCFl4XZuIZPErJMQ+kK2ZCy50mAX+ViSCWYk8vjWgyQeeNlKqx5fhWpElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwnxuzhbQeomHDzNw0sZS75KFWyI5MTm0aId983uCsKMhDqqx/Y+Vz/mzMSXvYWV86meC6QuS0go6BAY/ndFkvDA==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAdqa+HoNlBKnDc73qbus7TkJD5cJVomt7qBvrTjJacSijkkpDgnzUdYtPJp5vaep6mA0QNa2INj9prOJv4LPS4bS+GDQEMYELufmi5znTqkaniZFsoTV/C6omKY5tsp6eBf9UW7FuHt0U+9y1qK54u0k5I1KWCEIQxfmlrP5/q6IP/36f1NlEUJKN6NgH69KcCMoxk8iJPOJcQsMnusohsAlHzaRhPAnGcUy9CRG4se2UBmNBT60Nx6NHJYNblehJDz6XU3krDF8sreoa+5kA3F0Zd5G3WFttL6zu7UlwPhCmRDjSlRzRGiaXrff6nJgoDPOpeyg81xAsi/DOYrXnJzw4L/QCn1GkRs9gTy+YW+lkoqqByVnilTZrvQSmdlheBwAAAC3i/Q6Z7d6CAWqH2KgGDAcOXGOMwfwVbAwhO9Zy5lxKNE//3zbhg2E9qawAtP4/zH7gDLG7o6oleK4aO0iXJKWUDaUYAct2zbod5ks+tpIz+KBE62rFmOzJbIAy9D8hAbjXayGQz/2iqCoZrrNAsRq6oktzVpUkLQb3QMN0EY+6tuovRcPqc8yVaUZkL/0eY7TFXQOEZufPy4+g4e/HGJXijWq3vSomN0aBOKcMPw5tLXO215IaNP9fzg0QpPnkCA8twZvmoyaerXFZwwOFMadwYKnvOy+ZJEoOqHP/gb0YLCTWwpgQLuRdpmM57GzyA42GgBW14+A8k87TjxppfD8WuXhg16LBfbwQ2dgoul9AGsry/WR7VV9qPZ2hdj+YSUJRh0hYB0E9dREyCq78YtkU+HFawkNPRcDBK5hoNJJR8JyjBJHQkA8t1Rg0iHdD2bbR/KeiwxiUaYm7G4dDQ0haQX85rZLON8oT90kwvHkb6MqHpLw0rEjVspd1iuVcA4ki7wpmqnRVOWfn6jO7zDPivgiBcBX3kfwnquLoHjsdaG1fnXbZ/OLj/qADrlgtNCMCXOMMpHDvobS3/2ImdtxtRG5x1a7q4O3dCIcQEaFx5BxVC9JjSu5UxWzWFo+oj4JTX5Hk+ArIwe5WEKCYSvRXZRJo539t8r6llieorfksZW83Qy6dZa9wZdh8LQ/kse+RyCVKsguC/Urnkil3norPCWeJ9iPhlKq1VEVvxJFeT9RoQviHq7ZOwbz2tXSCxgFo2UykBWuhcge3sSduxaAaEV6CqN0fvfRVKE0ZceJ2PfBsOMr+bTY2poevhP6o2Hj/JuFfw/9NNvltm8rY0YOEDpxMqBqHygUAAAAAAAAAmpHzxAkA61/IlLfxSDXDcOeqjCA8ELUhJDE0BxjWPOPv13HOLnJB0KbHR8KNhvH/78X6wl842k2brpdfnFHNBw==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAWrcM4JSxW8TDRTSKa4UCmKLp1ayyDgMGKtX8H7OFrRCsc5RptneIqswBQzWy0kq8KcIvn5lLQr3sGq50U890Ums8UMPfELZxBiDp5FotsmGReEfXeeFUS4EGkEQy/kS48xv68lbvaDnO9EGZ8E4wSIx5VbqjXYhhqOM67yf+UIcSFGtOz2FoBpM+1rL47Q7H+ZvIAgbHNN3clQCV8gj1rTBtL9DDWPCbzqXmmBDj7WauMn6f35EJz/CCSoQwjZSHRrTadDNoIL62pIL0lTxNAUzTpH+hn13LqbIwsM2Q08HyemIgLyd3iTztSVqUj/0A7oB5RGphq0HaT4on9NYd8tIjQMAuzMl0nTsnK2s3mp8MaCR854ece6ppnXwJnuIJBwAAAIoEwdr12AHi07OO0Z+5p7O/N4R5h6/hI3Yybq9u3IplXNGiUwnyr6/z7iOgOuxOV2FQhsgizG2QwOEbeQZRYbyNnxX9mGC2jWQc1b9bQ9QjftzG3zw7cudtKQjmctxxBapGQY14fqyZ3tehrepeWuHzlaoeDv7U1u2Cu+cPwejC70+BuhQ0bhUpDV8vfX/hBIRS15DU6wKd7dyoW1KiUb3HQHN2b1AwXyn+2rQf3u0wQYgr4bK3rzRm3b7g+86c0BBYsH16wy8Ot+Xjhov6W1ctJ1FOben8k7GcUbE3onm6He0j0m6V4JvNDEPaZsWH/Jn9MYlmMl4fnT2AunHlhJjNPIfsAjXlCgWyehhNix36yfXGnhmVHbDCEys5wlnwhWG35PwtJ2+fxYywZWA93RCGxq23CwM3wwbGtBI2ymauym0Z2SgnhTuFnnSJa2RufcvhaIcsBMgHfQ+A41X9u10mnkyEYieaoLHxWRNGgKgqlMyPSfgYo8QLZf+NqDYQIfR03eaD0uyzp5IpfckzoiJ16tLk6wQfODKxcc1Up6B1uG/ZuRBSjrSwvQGo1xfdiXMua+0FVa1ZoXx4jGylk53Mb5gZPLjOAe+Aqz1v8Xt4En8Hi/agnNv+d/Sqzpup6mW3f2V9Acr34PhhIqeYlLhzuiqspMYkiUudGLjwfh8HH+MZupp+n1Jv2Oa4QAfCB7NVNvYBtDJXhnvUOtp9H+Bjq9b6mGjoEMjvF5o8JFn6Hv7/jZa6EPcsfNT6Z1vq0qkOec6u1Lv4forXOy/Gq+HwqMZ1tPXt+mKGwpeGqx/qZJsH09wINy55b1XJNp0D5eY7xxi2mFaSPIGtW4KI71b7F9j5h40x8QUAAAAAAAAAuiK31IwzM+UTw+Z6b5HLJ11Me1x7S+nDcV1gRVI4MY50IN01dpdkDz4gD52KSaua9yIFuywu4ZQAVUB87DJBAw==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "5FA150C03FB7A7F7854E61E4005D7CF680E678F76B5D90AD049069DFE1A331FD", + "previousBlockHash": "49D844AACA33801555A627E882A0957AC536F8F90598BADB4E5D2080389D88A4", "noteCommitment": { "type": "Buffer", - "data": "base64:jwdSLILDA4LKJdSrsGvTq8LXHuFS4yDHsE3fZSVnRTw=" + "data": "base64:VBlR48rwM8MS50RICxEo7cN3fAex4ImVr81y2wy0vA0=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:uQx+iOhCj44J3lqjqIHzReb95RbRggvoOHPfUw03hcM=" + "data": "base64:yPRjaCot87xQuichEzEWyBR92Tj7vBue7zynBEda3kA=" }, "target": "878277375889837647326843029495509009809390053592540685978895509768758568", "randomness": "0", - "timestamp": 1671470858705, + "timestamp": 1671691635060, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 9, "work": "0" @@ -1874,29 +1922,33 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA9b3+gJ6pRHc5n+VAoi8dNOtctYN1sIEX2AcUqzSVXCeMLx7WsuAVUMfoPyyY6z2NVhnLFpDWlpb7xDCZDfbVLuGjExjZDaB7KhTh41qme42qqpUvleq5C5byWIeaJP9Z1gMzOJ1TFdfJrAJaGYXn2cBKiEUeRrBYBmLiuJem1QsWXQ1z8c/dwqNkQBPA7HKHSDrJZdzBp5x14BL8zVU430/T6v93pfs/XbRBPtGKx/mWVMIqYQh0S0t/C+8B6XBVN6JjUjH/BpXu6NJyOfytBa+vhg/1x0hvsJbT3uQlN+Q+ludCISIzfd1yqC8CDRWmQUZbohEo8jqQJ2QnppEnbSuwYBxULYHUxErKlkqUp1iLxc3ztTZntkeFSHh4mUgIKRnDjpHH530vqNVrOftSJfuwbrFpAaijyCUaM4HO1iyy0PdQ/TV3nRgHBRX+h+87KFz4uRv2DYbWQm9oYBZmdILdabbHCQZi6kq9N471NR8DFwR8kAiMbBKdDrcq5R55oZwUDo6krUiW9ob4pLWXvsd3DLUg3IFUJGU8AmolRucijB/Y27x+xROUA/LoGf7HSZLkIp7lj3UjhWhaZG/7d2T9CtVPcCMSam8hzyBVJ5ykFqiRvWABzElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwxzQCCSOFULJ5hyODgjL0cgA5L+BQwdt3wnnYvHkttOtxFPi/GAcDWNA3Po91pXk85cA5cDC2WrXiuak4hrPoCQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAy+8RWnSedTzZSQEXI3CvuDIJPKupBthaqdLW41VAeOaOxuAROQHEOEwkAtjVKUzW5sW7rQ36pFDfXtmLiHgAEYxDY8xm0cHUI9yXT5tWKJuJ7qPhWHfXk4F6G0MIyJWQjVZKEWXFn/jX9hBGWW78YE6GKlk/N9IwOIWB9BeoecIUC8zdqzFnuo2TV1r9700JdMU44rnwiEpwhFfJxNnvcB0FMPt5QLVghfATh3FMzCazUPhRsd8e8USZdV2DOtmQrk+fh3ZfiS2yf24tKMJquDjogCmA7ZK5LYXHKVuD6EjUUiM0Roq+fN6bI9u3Qzh6zd4ScxMUZrlJTZoTjyVTnEHuMdjgaz8T8fI3BeODE7ZZZJKPdsP1byYyGTnQViM3V/2MxidrITiHvo10faPcIiGlp0mM0DRG1NP6ByaKfJRLo62T06Fu4roXIRFSC3Rc0YCDNInBOoeTVypjLII/zJ0rVfgBormTbgI0bOawC/rz8b6wExLyHecNjj62mVPAVeK6ZtvLgvW+kxRpAvV+VzmWkNXeMtOxcpxd/CWNdny2V1aDwRxhyUeRiw/V6mCLrK1uk79ws9nTA1c09QELORpR4pYSRJeSD3F9GQEHso3w4mYm77GIDUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/SwvKIMYHAoVxIaUgfHnjs54GBvlB8nxtJfIdaCtz6gii9wlIoZpMn7DqcdHcj62FAqdIHe37UYPgXS49tcDQ==" }, { "type": "Buffer", - "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAp/9+CbrsFPTJRlonhwLWlqrmSEeVhdHBIgjGZ85Iy1+puaVT+pcXMS17DUVByc1H/+YAGS5g5+I3bW5HuG7iDEoUBBQlnr2JRUMxWrtP8PSTr0WX+qrDPEww5ChTKFIOjZPDDSY20McfC43HTxuAyxd5s4G88PbSuObNf1j303oNoVyCR/EPsJt3aSSLTnm4b6/ixR4m+6Y8JMK1C03f+mWKG2WAASCBx0cNE0egK4CpjTZZ4C/I98OqvEXG5dZsBr8ivEFJoD/FJa+s4whsEXnW4HLIzVrWuWWHmjvvTkDs+DagqdMIj5H+BJF3kT6MNnvnVQOInDHiHwWFIxfvRDw4L/QCn1GkRs9gTy+YW+lkoqqByVnilTZrvQSmdlheBwAAAC3i/Q6Z7d6CAWqH2KgGDAcOXGOMwfwVbAwhO9Zy5lxKrZSPWrRv7OzYea11Zw5iNV7g5LYUqtiDLHQFAr4JfLGuiSxhhzLgnCUGHhHau5wQTswUNysS0ZUhJEG6mg/uA6YUTCIgb2mS6k4+0mv+YC2EJeCfg2On/LQcBzipmQ483SxkX1Pey9WtcieimZEqsJQKCOM+JbbEujfb03QyL9VYLf2394mwJzLJJs2CfoslOEMjykU+AfqCSrDzTSXTvwRBz2PB+N3Bg10F0v8ZulMHywEozAswAcainAk9f+Lm233xnl3oRSnHsomMPUTnQ5TrAFPxy8LzXYp8Kol8x0G3tPDwagrL6DsGW/wczmF3gD0P2HFyTIWDNY0YkW3gZIPkj8UhpUptKjZGuj4pPWb6VFqou+/pTfFV0MA3Q2bf8BLjrzIbWxhOmdq10uFjeFYzZHeuH0sMGh/xUUvLegtc/Shnx+3QvVufgmCrbTBGR33pEmF/Pgo974a+MIck7QbsIfqaDigd51ZSxIPobHvEl+dWF8GO9dA/GVDDT82F4ynZ+xupF+Cmdxzr1yn4z8Ad7a9hX2FpTTU2aLMocqx9BWBAc/lJ11o078JIoKiaAnPWhMdeeq8OSmhFpzPwti0/83sF8Z/hYCklRgpE35w9OEpJw0uiuhB6fz6OBWG12AXWtIyUgRaaAGOr+icnDPZNMuf4KQF1prRImMsTd/K8ZfcJHd9ap6zKelbnIlCKUwC2onISTvpuHTw3Acb3OpVOyHdAKXuxtHQS13D2BEKwaEDxziBe18AwNjlIbRDwRt4ye+nWdeI2poevhP6o2Hj/JuFfw/9NNvltm8rY0YOEDpxMqBqHygcAAAAAAAAAOt1xYMVI9/48+MjhcNbNbZt7Nok4ATfiLLuVRuYCHjlSHRfRqkbgb6bnWhWHKoEatgaThjcZULbnzqCoIEPhCQ==" + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAASUjVS9w5skfv7OwT8M0bWc3X662wlXN3SMLPOk07mgGiQz/RTjQ1Okrs9+KJ/VWHbcIf5b7ldguBB/s7dkn+TiIDCG+sZK48JpdoNAVyfGGiFx+DfuNWmxrqWxmrHWyymiRjLKmBWKnFSNtFUmlhIR/wZCSXyhjAk2YoGzYzCf0ZUykmft1Pgozjmezu9mcJfu3Ep2exG8jYePmnpAVeGjxePp3Z9D4Haji555br1eKqR1CRo/cn0JKSo8A1yPeCCxVbNfm/BkBxaJ1VehBPq1jFgCVTDk86HYKcl0/jYl7NkdlUe6cac3N5UTicTMxHTtggq05m5ZluligIeSr2UNIjQMAuzMl0nTsnK2s3mp8MaCR854ece6ppnXwJnuIJBwAAAIoEwdr12AHi07OO0Z+5p7O/N4R5h6/hI3Yybq9u3Ipl9SpnUEKRySBS9bToc50Rmx4q9qdre+YjTojEca1egiINMW/pvE1MUGnOwSyg4nY7+kFUA/+c72zMfDEXdNpBBIGeHLqnqJ7XzNG3vyqvnWdI6GuSh1XhFg5QWVsj2o33z9qPOIS2O/LlbPYRsn2lKa6y3g/qZPPmbmTfMUsoyyCE7I3MszcAzJpHv3qyTZbA3KP6zXYsGsDBSWVtDp/phQvfh2arjBvTE5exzfAChDClbbKhTYI/b+e1bHzh1cfWl0ZrkguEzGyDky/5656Db7D4lzd/yuGVq0FFQJ/2l9Jv5Ey8R6rnnX6ElGhCFGknE1K6vCYmsOfCaa2JWOTWewZ596DvWwlL/SR93QjgEESlLRaJa65MAZyjKDRdDNzSBJY1TmS1sqD1Qzu0uJ4Jl9jxA3AYQVFXHFbx05k3ikcn8V3hlO2dIELFOuqTD3FnYj8usXk5bBEqcIyoYV7/kviMhMBPVI8TMhp3OUWfk3haWMqIeeYdQMT5E5m48Eo0tPw1GYb+Kyn9R9zaoA7V9Lps5wHJT5d+7OEsBoprSM+03MIr4eEFh8tywCCOACG1OcQJG1qKEoOVsJVrfARmDV/K2vJK9I5vubzE2pPQvkul8IkXXEOKnBsZthatesFTKsjCKsSeRrpyg1AG8LrdoRGaz0iffzOkp6KaWfOhQQGxftIXULSuAWhV9/s9F2clWZET8je4s4TUI9gNLlXeBOcUlATDZeQ2eUao9LuhplQTbNoWP8ASR0sIpExaObZrJbhuUe9znR15b1XJNp0D5eY7xxi2mFaSPIGtW4KI71b7F9j5h40x8QcAAAAAAAAAZ581JDgzPzO6kAZXlPAHWIvUsYtIpjnf5dbZ5LvzAQWPGihDHya86papI9h3Nnio1vMcNpFysBRvRMm+kx3LDA==" } ] }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuU/H8gazDtfcwLkzmR76HnGqTu4o/c5EylDmaShvu02K5W4mf48VztKN6bdakRUtMVaKOgiLe84FqnuXqssiB4vcg8O6FwsesCEf953JEcas2MOpfVQErJFafDZ0VD3ctgQ0oDjnqgWUvbR2SfnzYe5QNlRTgh7toCc06xnJrPsEDjr0qFRoUUh03QOmnpfjfaPjepNFgvPyfp0Tea33HFqAZ64WYthIzlQp/DIPngeTkZuqWFd4+qx3jV8SZyHcZlWFEg6I1u3uKDH1I6BPx5j3Z8rzXbQUBG+SkCPKKe7hEsCphxpoSIv3bbHDr6mhRyCsXfGDB/wlFC2iCKb0mcuVnAfIcY/FFJaV5DU36E4JBx9G9vRXHhghe3d+o5snX6PbZIqZ9TU+YQ8MiwgoHLfEQ8Coit8zx52tzNQrXjLo0EkNq3boNmBenqoJ7U5BRYrcMP35cNpcEvGjpZkBUc0CwkC572ldhYQ1zS4p4wT4XJtcH3NswDS2/+L/oa11ZJr8AUdHoi1Utge9+usHXTGBd7gkoBYI315mb+PadCws+cG0d8v4NSJ+yMjmPSi9ZYkQMRGhWI370H6ogg6cenzV/rP5e1rBTySA+XxsF8GGAMFWeQPE1h/378q31oCtZbp3mlMAD/cZL9xNi70HyPp2apgwfm59V+eZI6oxbRiXMaZEdRcW3RiK33e8+AOFP68OVisdzVkz5Lw4ggjgJXCTmbSPScvdtUmo8Q1A/qA1mLNQjLAudECipsdRtjg/jpnysfc2Pwqt1+agBh1JR+bqjBpz5LwZj4dkhrAV/c0JNJgJUrnwo6xj3MoYacdqMPhoezH5lh0iS5J8zr2yjp48L8fK1IqcEyPqC8pX2OXwg3ZGvlz8vBGfpuTII1ApHaWKQhNmRA9Nclxk47j+zPgIpS/EsnkbhG1bSuL/YqHPGJciLFG4tMWt0KVaEcOyVLoVWE8EJqj377BLih4fLJmNY3R6XQJ6/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAACynRHV008y8NHbwuXT6gRB6Xfi0qo5JQNdfnNbqkJqoLLiOh9y5HZVXCe3pumKvI3lEPgoIBf+8tUF0wUj6SRPYUM+hlgtiJSlA6GUkryE3+aVxC9mdQ22GQA+k2euGQCiYS5/i6Tkvlw1mMg4q1OSLVW4ZnlGVPdYt2yRTKL949ODBnQ3blop2p5vtyD+bNPTxc3FEaFqYMBf2tfCZFwE" + }, { "header": { "sequence": 5, - "previousBlockHash": "0A69D829E8FE7DD6B024C83D522FB6C641E73E56586DC7A152ADA3980B4BCB66", + "previousBlockHash": "CCB8464AB128AF0E4932DC3012CD1DB3907BBD38628F577641DFB51CB0C7BD66", "noteCommitment": { "type": "Buffer", - "data": "base64:zBLLxXMf/y0XLY+DKuw6lCYNBlpBwGTFXC8sf1XoQyc=" + "data": "base64:63TV8Y30zOCFUCsnIqeg5ZfEVeNqLhn06WxOLV+JdRM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:3Tmo1h57beL2xGfqeb/3ID3GVQs9MPq0j3q7jTnKL/Q=" + "data": "base64:aElIuZ2Jy/NVwro02wikNXj8E06TsUjUiUdJjA41rcw=" }, "target": "875726715553274711274586950997458160797358911132930209640137826778142618", "randomness": "0", - "timestamp": 1671470859537, + "timestamp": 1671691635923, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 11, "work": "0" @@ -1904,31 +1956,35 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAABixy2wHLBxgT29CPJhzC874yimSvEnTrG0t3KJ5aZmCgjVB94QPWFGFGDCUzfUHuAr+LNbY/zTX57TDO25kgDJkdxNHU3qu4/UWLj13TDOaLIA25c+J9Ccn99tXb+yzJIAd/n74W5lcXlk6gzZ69o4soQwyBFmvSx8Nm5kJ2nc8T9+sziT5MTDG63yzN4P9iDqFJE8EmIDH3TJKrY/DKDeXZdxK4YcgqglJdOr8oLGKvZ0mfM168yKjO2WWg4xBwuoChC2W7X0GP99mu0PYqpjYFotsZpq2AIvkYl/qkVFvgKcFjrcWrEjLxOI+qp3fstnRUvgMcYq3rvKKV2M/Ic1Tk9l3CINd/4YP2pLvyliKLxoo8kYATl3xXKDymoTkFqDwcE3Fz0cZk5hIe1Tdyy+okJ+oT99tKsvmvdx0RxMKmDpogP/6LbYCFmdqqcurNQIfa6PIVVJwTDLIBJPzchP+fDZppmpuiEiOvYgyjEoxN8EmEtXW+rkyAMsOsp/Nr8J6+Ut05vsMUclPOvR8YUESS0kfGzlK58W7RUNFEVHr5G5OX8pmgIQiyyCXeO+DXtuPIE2HyRFs0j+R7V1+T5aXGAcw8+/o7/z41i9yclPzPz5lzbdDZyklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAws5Q7zg6z9BEgRFNhz4LRJeV85Nwl1/N9WyMelDN+CF7aHU2/r8XdyE78baubYLK+vM7BydR234aYCk9/XuPDCg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAk2AQwS+dRngYCabsi5HP4XPhere8xJQEz56mLrQsrzmOIjEL1rfKp8mBTGPmKwhp2qPSUuo2Y7WIPK3sb5qPxkXa7+DX6SAvIbayQPl1+t2Or6MT3iKDVL87xfPuGs34nJHXy49q9/YNmjvSr8CTqzk3VuDXhF4zQk0rQsKKuNEEKMLQgkq4B9c3RY6qm4YzAuOO2UjF7W6iu8WKJ0+9dgfj2m61qpj0rY/Ffz2yWzWoJF4pQk2w0cp+19SHq35w09F1QY2Zn3P53F3rIxDzpz4KNYlvgvoUotGJ8coLa5KbgrpSO4gO7EbLn7PKVPBToCmY9/eIbHI8KjsjytKEslN85ItnnKNSTsypVsVdmSVM4kU0GTCjsbj+E9Hs7UUsIbC/GvtQ20do785HiYq6/ZflKAhOez1ubcIItbkJeaB9LPiXineN7Uql+T059n69S/sHj12DaDj3JZUHUtp+hRFxUwghNCZfjCSTNNdkhKnM6ImelY7jZIZAw1Brxeq4WRwxfzKHjMXHFQsMEXV1KXhe3XCCEhEl4sXqztot1Nh1ad4SZUEJU6lFwbz9n9uQ1ksBLdN2/NUxNgnXhIA2pd2swyi27vd4seWNNug8rSx3gis3/nxR7Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwveKA5KOj0jd/V4NjU6bjdb0RWIN6BmLGbl3CgjctPZSInSVcS0MLGcZOPUzKMBRYp2ns5oNGV8aBYcVBq/WGCQ==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0HffCkCRbNZPDQ2EOsxBCQv1/RNS3evHrwykYlhrEE2ZQVAiV/knLLjhyQLyHamFU5f2HcxPq1dEtZUhNnYVSQkGjnQXQS1kwxXThiLIOkuTZN3g3WQlURbouMEUhcAKXxeMtdk2lxPTepYunS+J+sZGN51IXvp6QKkv326noroQOr3L2mh2gfnlpRL/mXtL3yaoykS/b24ymuPMVnE0LIaBMO126n/YVzRy0AHabLm40F+DbjvrPiCaFd41ZCVCcSGJI93klG9jb0NDlSTNgDiro3rqK7n9IxawraGre4McZPVZ3ZsiUKaL+h6KwLBWGw29agyBhDAY135E6MtBrsAKVr/eScrDd9BCDmOS0X2B9ysSvbOvzCSu6+UXbHRlFXLMonGjTxEWT3WadQwB7SAwh6EcvCyuHvAwYQsFkCwpZN1Z+JGNzH+N3gzOn1ZJohB9yNcuNjL2HuuIihhuSw3OC5Smqn8n76cp338hEc8bVvILS7J7l6CLvcQXlQkXcivRW4Jdj7NfZ8E7uJXJ8KPDHb3W1VbvEOqinkCtQDavoFh1GFhC6N/p6n3YVHKLOJdtpcrHI4w5sB4QDS2+gAoYR+MflWVOqmgv3ni+eBVxv+6Kp0QNu5lm0WJpOtF2F3sz0itX/lHf/1aCM2OpEu/tyxGlpjxn/bdNzMSuKVlv/WzALhJAHVtxcEz6PPgLoGepFlIcXxOFTE/OJsCQ+GdB6VRU22BSjTu+81v+ugrdD5jQsadyk09zKWML+oHfbwHk4BpN4i719/0fSYJQ/yOU5AeCEsM8lzx9BU0sfhHLesoubN2150S3ztZMOul9hNEw4kLbyIFZJSfbtLeiC3/NJOPEC26GDLiU2ZXjpHCV/ED2S4N8CSIvwleQfzwnBqudOUBCYX3f8oVuKoKMRKh10vdLald1lGD/U/ZMK1VZfFP8sP9xSD5R5q7kDeCou2GBkYQircZtxOAdhKNLUW7CiWNDoKZ4Hozf2P5dO6Rj5BxSuDwpO1VkbzOegq872BJ+Q7LVXBttaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACgOr45Y109IUSNrKCk1feilM3yeyzlVYS8CEysCzP+zhc7TWKWbDRXDHtBtxeevilVMe1cP/a+AHOaBFQ/+zxsj7N6WZxBxcge7RrFOlXspBJG86D/zPXa8YinengYJQ2GAYt89z1kc2h/3Po4u/hBjcHW+o8U3E3WA02do5V442Y2qxPpOAqa1jb6rNvaqJuk3RPpwDe9U6l1dl+zOCwM" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuU/H8gazDtfcwLkzmR76HnGqTu4o/c5EylDmaShvu02K5W4mf48VztKN6bdakRUtMVaKOgiLe84FqnuXqssiB4vcg8O6FwsesCEf953JEcas2MOpfVQErJFafDZ0VD3ctgQ0oDjnqgWUvbR2SfnzYe5QNlRTgh7toCc06xnJrPsEDjr0qFRoUUh03QOmnpfjfaPjepNFgvPyfp0Tea33HFqAZ64WYthIzlQp/DIPngeTkZuqWFd4+qx3jV8SZyHcZlWFEg6I1u3uKDH1I6BPx5j3Z8rzXbQUBG+SkCPKKe7hEsCphxpoSIv3bbHDr6mhRyCsXfGDB/wlFC2iCKb0mcuVnAfIcY/FFJaV5DU36E4JBx9G9vRXHhghe3d+o5snX6PbZIqZ9TU+YQ8MiwgoHLfEQ8Coit8zx52tzNQrXjLo0EkNq3boNmBenqoJ7U5BRYrcMP35cNpcEvGjpZkBUc0CwkC572ldhYQ1zS4p4wT4XJtcH3NswDS2/+L/oa11ZJr8AUdHoi1Utge9+usHXTGBd7gkoBYI315mb+PadCws+cG0d8v4NSJ+yMjmPSi9ZYkQMRGhWI370H6ogg6cenzV/rP5e1rBTySA+XxsF8GGAMFWeQPE1h/378q31oCtZbp3mlMAD/cZL9xNi70HyPp2apgwfm59V+eZI6oxbRiXMaZEdRcW3RiK33e8+AOFP68OVisdzVkz5Lw4ggjgJXCTmbSPScvdtUmo8Q1A/qA1mLNQjLAudECipsdRtjg/jpnysfc2Pwqt1+agBh1JR+bqjBpz5LwZj4dkhrAV/c0JNJgJUrnwo6xj3MoYacdqMPhoezH5lh0iS5J8zr2yjp48L8fK1IqcEyPqC8pX2OXwg3ZGvlz8vBGfpuTII1ApHaWKQhNmRA9Nclxk47j+zPgIpS/EsnkbhG1bSuL/YqHPGJciLFG4tMWt0KVaEcOyVLoVWE8EJqj377BLih4fLJmNY3R6XQJ6/PYilKgz9hZAseEULAYrcz/3CPu+g7z8+Rypt342+Z1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAACynRHV008y8NHbwuXT6gRB6Xfi0qo5JQNdfnNbqkJqoLLiOh9y5HZVXCe3pumKvI3lEPgoIBf+8tUF0wUj6SRPYUM+hlgtiJSlA6GUkryE3+aVxC9mdQ22GQA+k2euGQCiYS5/i6Tkvlw1mMg4q1OSLVW4ZnlGVPdYt2yRTKL949ODBnQ3blop2p5vtyD+bNPTxc3FEaFqYMBf2tfCZFwE" } ] } ], "Blockchain asset updates when an asset is minted on a fork undoes the mint when reorganizing the chain": [ { - "id": "14b4a747-4620-4d4d-82d8-7d2b0fec4fa2", + "id": "34b06bd4-81f6-4407-989a-5eae866d8760", "name": "accountA", - "spendingKey": "4c4e34f7fd8e53815c05895a3244be8809c72648e2ebd68e43ffee3fb8766a29", - "incomingViewKey": "1ba63f6e466487a04958afd7b5be43b6298f1cc34db9602de835dfc576c3c101", - "outgoingViewKey": "e15420ec34f219628f3d50a12794fca4b1e75fb5ac86973e1319e2a4d29b143a", - "publicAddress": "14f7f7f92e4ee2185d269dd9076bb897ec4a909ffee20aa442b8cff3f3585f6a" + "spendingKey": "cb338078892db5918da2667e68a07bd0362ba74f3aeffda06a8f19caf627dfc8", + "incomingViewKey": "a59a748bcbea144c8a645240b28f6a0e79d51a693df22c450258f82e0bfc0704", + "outgoingViewKey": "f87e27e23f2d1110480ad84cce4b2efde1ba31fb2b02b7f4696bf07351b0ef29", + "publicAddress": "ff2354e7d055da18e7625335a778a2398a79a8753c9c778ccc2102cfdcd336de" }, { - "id": "fe5067c0-b497-4a1b-871c-8035098aa562", + "id": "21a53c0a-2869-4f9c-950b-97e4abd67712", "name": "accountB", - "spendingKey": "3654f198de0e878374bae07c07cddbf23fa156e884b90c067066e0a351301a54", - "incomingViewKey": "cce032c0fccae314be7a715711f905e08bd4c5229c5e11d3221efc23f1166804", - "outgoingViewKey": "253d64bb4403cb258f3a512e57818bdeb227030bcb0a0c609c961ece9632397f", - "publicAddress": "3290e3b2d0777c871e6575df928e5c16464a01cb58936737c6e72615a5b4ac23" + "spendingKey": "388a9e0631fcf469affb36df5fa828bf364eeacf239d28ab514973d11452652b", + "incomingViewKey": "b51e9e0c78b21309d74c7da9a9eba36e7f4c8169a1af24a9812e90deb25f5f01", + "outgoingViewKey": "fdd3ecd9f04d07a699eb459aa9c419a9d4ae769607f6162ff4ec80aadae17ec0", + "publicAddress": "a6661add8c9f58a838715713b9495b7d5d073f2196a9e8fba36044d45a767bc3" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyFTiH/3OMIXg6GfTEYbrjZuOtFAtVKyU7MTYwECAjO2ra6dkji3WRhMTJYQJ60mXycQ6cbEiiqM7Wm84hZOypctlOcYrH/rob62jo/7iZ23tLkozU2/j63lalULl2SUm59eZLFiVQhAxvI0cxYe8C3KwiOgeZDaUP4z01YAQe8QydozOpZAMmnVOr4k8SQI607uoyP6d2bdHCk6HLs6RbXuywFtLCtFVKm8o8Reubyi/2pR9vGHrICKGC/OGw6DuhtkAWkSKIZUo5+XoNOqRBZqrrzICJHUy9LcGC0gjlbtErQM4xKRGgsu1Rj/D3Gpmv9h/+49SRrQhedfS8tpxyFC8YX8+QzfU5vJHQ+xaHPWDbeg+NWoRYk703nQ/udBJfZDqyATO77+z/AEPKsqQnhOKPL9pisF1wkCVz/ejxPBa6lR9FmevW+QhGnLaxGXOiV/3GFe01580warDpm8aHwbw0AiA+0NC6Hsu1wB3p61L9OJV02gTD1QhaB6IWb1t+IJUuo+qPsTsRd4BOwDE5OG96kcNmrPoGo5rX721rr1Ep/P/LRljXD3cilZN7NMEHTO60Nc5ODORqG1JAndGQ3KbqR+qHPm1EOj/ZTxDDRLyMMUIbj5RmO7mB1z3FgDFYaa7Q1RZ+EtYUEiUGIMxmzO/z5gMjA4+Ijbv4MgwxgMOiy1rsIt/YqweeVe1/OCVkYcMxcAtmwFuorbJK+KX4LsS2IMTLT4gHixM+fltdO8eef5GjazdDMV4OqDymBtork8HkwBQBQLtt9fu2uBM/jS87nel301iFNbjRRI72uLcwFc9nXChpyAJPyDWLXP8H/0EgmA5R89P7MQI8aB1i/Xtmx8ocUMD1B/v2HfiDsHouu3S8qDc8G4xf3ZMMA4yoj3hvvWTXdGzMbXzJLIZVGH/5YXwLi2t/hiNQSEbdmae2WPnJzF4ssvZ6jsF+C8aIPWtpho8C2zF9UA2wjS7utgPQMdR93x/yNU59BV2hjnYlM1p3iiOYp5qHU8nHeMzCECz9zTNt5taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECgAAAAAAAADNxTYfd2f1pydZuycSfIv8Ls3jST/eXQhxGhS4LaDDqQ0zTtRdB2buUh3YHVrqrW3C1GzzLKYaA0n/ZGvKfQCmlqFQQBycAsAU9VSU5GOqxceTSWYih9yn63KMAfi0RQnGBJNm4E1uNBCZR0MhhEdsldNfWQeaR6UgUQqWvY9fgTJ3O+hI9M1VegenRfVo653xYgxr5ZAet7VAU0OokDcH" }, { "header": { @@ -1936,15 +1992,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:rNGmom5ve9lnqX21mLiAmJWx9OAuVKBSbLly1drz8VM=" + "data": "base64:THXabNeSgJbEsp2Fxg2LUl/fuAP9agUp4kskZNj5LSM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:rjWVdklAsUvldFxTgu+CMX6IycYiQUg6XA3eTdpjX4Q=" + "data": "base64:uJI3BI84zVQfS5Q/+nmzllWjZaayVLqSZyK3zjM+ZPc=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470860480, + "timestamp": 1671691636992, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -1952,11 +2008,11 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAjr5P6tw3JzJr095I+XNrs5dAw/AEELVFzWTO9/LrK4+yGaoW7f9zQd9XbZWMnLILOY0AkakKKm+b7aRQxd0/kf7M/9eWnBssy5rv7Obv5teyPtJ7uRJSBXvpfvDgNMluXidKdGmc3whPwL6U6IzOWA7LdIKz3qkqDbG8RaKjPvAOqwg5OA55vX1DPZLBK4oynuXrwblAesSPqOS9QRdymXmX6ZbAkaMxhrTuMFrEA7KEwQg1DduZ7VvWr4D+IMb6uQfuJyBrUwZNnjrCgIlv/zuaCSPNp8y3fTYWz4gLH3s4dio3SaAZqts3IpB67Ue/gmX+9go/Ag9afZHFCwA3LZp0xbO8+VW8GtJU/KLUi8KewBpDZvJ9GLrINO3fw29lkM92R4UrU89MquvRPbTikTmobyK0CPoTBjDnX6jH47Z6saorCxP5gFQ1sYfRE9ARyedcALzEQPqQ940mlP1HdUuEzxW3551t5kEnlaLmy5dQjV51Bs0Q4+C0OeIT39AdOHH50Odc7fJzzvG/iwPT/WXCu0BRm8xK2skmwk6f4a7g1qfHaAR6mTstAlrjxZah6Hesnk7Bl71pDy+NFwCtIbz1N3oknT5A1sfWdgkVsyC77mbQu+CsMklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOnELbg+Jcf5bPnAo0oSN7nD28jwYvDU+h82B8QJNIeiZkh8YnNJ/mgoMiJ/tPM3CyY4O/DWvgNqL7cmoSEdDDg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAVmsS4X/cNGjHJYFgY9Z4PrSTVLKnwXHv8c73wnjPgDmSrxm2UBQxDvrsn3GnZdtBybXIHHCpOCrr9hYTOcCkIsOEs7xiVUoX1nxxPLwdcCqYpK/mPopYzadGIizi7nA+8SxGSxfPq6ScOq6W2R3esrh+/DMWJyyu9B6X/7bliGoMG6UQUFsImtLupxWK5KSYIBd4smBLxexqkYoKhz3/blk6KTfz12gP00354jLzXLWy9a0UL6j4B4LVTbSXXqIAV2CAGekwtCyaJawg7zgSOlXzNNWrz4+hUE0FYWy/JkZvpNBBptXkgZdbWhQyOQH59C99O8FB+6BcrQI17NpZBVpfZUI2VR5+hHoNyjaT95KkLlZHEWKiveLcj8Th04kf8Wx9TW3TA8Z1rRb/7zb8iflOsc238CHU821dFfHhauIg+/feZS4/MWSVpJ8fxYidGUOuGNNZrGPLO04W9sQ61+b81ZeTUIjBafEoDeYwJiLMtiJ+O2kS67NVH+6tNYUN7g1WQjrFm+iuT/TMCcBqGLQKN1tTaeZQ98kg1TFfbq2ZavfylGZ5S9TMLfUL9WAoxeS+I5/I5htADqU5p/Xy1QjzKzK2YAuS6Oe7NdZY3GcdgMru9L16L0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwVKtmUTy0R31FoymGUHyaBl6BVT2zmALpTsQFnfJpZKanj/hbMTfoTYe35fvnd0cwu+RR00uNIAF1RsiibaUjDQ==" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApRW+kULqnAEVkxiIc2fRG3q9PrxPxLDxCmvUoEEXHEynkqP2lto5kF9mM/rquIqFy9DJsMGixOPw0OlfHCzBFapPxarP6TdJ/CyWV0vNyn+Gg8jkmMLorO2OMbsW+djfLnUGg34IflINjaPlHm/j8IVy8e5GWZWpfSqxr1PhlO4HsF6JD2tv78Wyo3r6vGv77UEP13VfrMNPzDhbfZ2Wmq/pB6Ou7MOECC/QrxU8Ls+VE9gyZPwm/iOYqqqkf7AbwE+Grmp4iXdmx4lPnpJvoD/YdaVpEhxZW/yF0AKVIq01NFOzi9kH0EdMbWC44w4BLDLgC5A03RDxkVDVmszQx4JU/q0Ll2QJmcgDCfwn33YQDLPtKv1M0NoKl5/kCj0hQ60DopDUAQDGRvEMpPt3WxLIhd8lDu4Lw+4Q7w7ah1KPKe/QXaeTMs2zoG05zMjvxL6Vrykjo9ciktSN6E457EipyE5o4uG0nIW84XTtBCoR7spp/LweJYHk0FKZwWK2ATH+0kuQjJJXtSnBupzaLJ+KWTqhvmkFrkTKLopZDqJFE2YYkXqzcukMUEcU7edchmXDJxjnts7i1W63M1wv0QGn8onUKC05QK6QntI5xZSC9VnjLVqb/TvPJvEFBSjrvKYIg/FUCdgyD+7CwU2cy+s9Xjiq+VxnYoWYsLnUrFW1/9Y2dgo2sRIjDHQtQGiVSdwqxEg8P/+bhnOpdLkuV12o5kwLB9TAuES5GmCFzIzqf4BkUuPijUbW5mNYiseb4SB+3nVn2Elnd/lLwchISSTTFHOsl4q+qwvYHKP2kN6yg9iCPng5DEMWdKPbUyHXuP3qXYyOaOLjSZZ0aB7CnwBCVRIrg1yFAdgMXRJq2ZO/QTs35aoPktWB7sGzDVjK4vVdtFoX/PVmccUiIoBFBZ3hQ8iTo0KmoLflKuOiliV7bq4RXO4c82G/95B7As+bFB52+3sa1MTAJ7xAdfY+VV2fQQbfV+kFFPf3+S5O4hhdJp3ZB2u4l+xKkJ/+4gqkQrjP8/NYX2ptaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAADj3Fz2PXV0n0bNf2cXH2mXNyBKqlcCF4oqGRc/lt3fj+n88oWE5KsUGtD9F7efms5hlq3/dkDRqJTjt/BscZbPA7VjRNhjYtMiePB5Nb+HdZoqLHdg/UczEbdjgNhIxQjTqtKOruaKZJTrokWvtQrMPGi44BbXIUUIaWfKG0bh3oERNbXmBBPCY21ctHm8xP4ntUGu6V5mtYdujGt8Nc8E" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADyFTiH/3OMIXg6GfTEYbrjZuOtFAtVKyU7MTYwECAjO2ra6dkji3WRhMTJYQJ60mXycQ6cbEiiqM7Wm84hZOypctlOcYrH/rob62jo/7iZ23tLkozU2/j63lalULl2SUm59eZLFiVQhAxvI0cxYe8C3KwiOgeZDaUP4z01YAQe8QydozOpZAMmnVOr4k8SQI607uoyP6d2bdHCk6HLs6RbXuywFtLCtFVKm8o8Reubyi/2pR9vGHrICKGC/OGw6DuhtkAWkSKIZUo5+XoNOqRBZqrrzICJHUy9LcGC0gjlbtErQM4xKRGgsu1Rj/D3Gpmv9h/+49SRrQhedfS8tpxyFC8YX8+QzfU5vJHQ+xaHPWDbeg+NWoRYk703nQ/udBJfZDqyATO77+z/AEPKsqQnhOKPL9pisF1wkCVz/ejxPBa6lR9FmevW+QhGnLaxGXOiV/3GFe01580warDpm8aHwbw0AiA+0NC6Hsu1wB3p61L9OJV02gTD1QhaB6IWb1t+IJUuo+qPsTsRd4BOwDE5OG96kcNmrPoGo5rX721rr1Ep/P/LRljXD3cilZN7NMEHTO60Nc5ODORqG1JAndGQ3KbqR+qHPm1EOj/ZTxDDRLyMMUIbj5RmO7mB1z3FgDFYaa7Q1RZ+EtYUEiUGIMxmzO/z5gMjA4+Ijbv4MgwxgMOiy1rsIt/YqweeVe1/OCVkYcMxcAtmwFuorbJK+KX4LsS2IMTLT4gHixM+fltdO8eef5GjazdDMV4OqDymBtork8HkwBQBQLtt9fu2uBM/jS87nel301iFNbjRRI72uLcwFc9nXChpyAJPyDWLXP8H/0EgmA5R89P7MQI8aB1i/Xtmx8ocUMD1B/v2HfiDsHouu3S8qDc8G4xf3ZMMA4yoj3hvvWTXdGzMbXzJLIZVGH/5YXwLi2t/hiNQSEbdmae2WPnJzF4ssvZ6jsF+C8aIPWtpho8C2zF9UA2wjS7utgPQMdR93x/yNU59BV2hjnYlM1p3iiOYp5qHU8nHeMzCECz9zTNt5taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECgAAAAAAAADNxTYfd2f1pydZuycSfIv8Ls3jST/eXQhxGhS4LaDDqQ0zTtRdB2buUh3YHVrqrW3C1GzzLKYaA0n/ZGvKfQCmlqFQQBycAsAU9VSU5GOqxceTSWYih9yn63KMAfi0RQnGBJNm4E1uNBCZR0MhhEdsldNfWQeaR6UgUQqWvY9fgTJ3O+hI9M1VegenRfVo653xYgxr5ZAet7VAU0OokDcH" } ] }, @@ -1966,15 +2022,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:ceyUoRXGswL4pPZFAfjjpinj1GbNRjHnZutCU45zMV0=" + "data": "base64:nPDm4htXPaod5EVYAlBVJfj/pR7CIBTJIkjBoNhYORU=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:R71xXAZqVzj2A72DCWJAU7zkqWy1jcTHkdJ9vjLHszk=" + "data": "base64:kOMOrAz+zQz0VBpotqLYeuQ1vY1UPbCAS8u/CBpsw3Y=" }, "target": "883423532389192164791648750371459257913741948437809479060803100646309888", "randomness": "0", - "timestamp": 1671470860796, + "timestamp": 1671691637313, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -1982,25 +2038,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA5dnBdk7ggVqJ1hpbHT5+RlXVXhrFi/tjAIVpFmTNT9uzFHqU+NPWnAaNhjXYCwXRNIjTuKKSlScs71r2X++Wb4sZAF409rWEsFJvT2rOlOWr9JfShljUqbtmf3S2OiyhgtZ5r7wwvVbyZP3bAMR34Y9oTwlf66d8AWbm0mMPDi4UoX6WpOTDe2j9r/Oe7U/JCnd+AYn9oNsBa1NaAnzYZc73qpF2bRxXxzO9jHo2ScCNXbN50UnJT7AOfc0Gg7IWGhlvrPv7yvHuv5mvP4BXzt7kcu4vMHysKDTPBG9WsaH8zDOqwPPGrktVNrSVKVUOQPa5KLrTqk3tWpjhV9XwMCFF6ibCu4P6u8ll0c7bpQxgXMV2/xNCsKBiiYuGj/Q3dQUoCzfaxIekPqbPjp+DnjJG0+QpE76eb86W4obuGuePEto+vNbNncZwg3pCYnLo/x+PTid+eXa3W4qFAjEwR7IcTc2Lr1bfc8yrtjeqieLgoltdAHFkMvvborCLwuYCmN9NN18tCQabILjOpcM6eMElzFGWLtAaJNsJF0tzey9Bh/0RU3CaJ548MUBFtrVYc9KjVwxTO2LaHKSwXPtYYUaY5ba1a5+4puGRMy7yOYr/w35LfGx4lklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2ZYDcEJb/GuJfIT+aZb3Ykf1bqHoOlQUOfRcHZoaSVoWWozUOq6v6R9iCWFgVFqs6YH2dYGeOUPXkjoxuxcuAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA8UJFUbqpC39K4ceSIAzLl4eEIHL2UR/wtpdQXFdZ7vKV7aHYBDBqP//EIhT6QLLKYnDhrlw/QyS4UZPi+N/0z5xz2zxG1A98PnSwVf6Uje6m7JCOcdhY9E3h9geU8FvIFddyatnlmuNH10aCb19JNYGhgQFAtQb2WKb9yFaMzWkLXxLG4xdnyny/crX8Ndq1AQaRDH7siIJ0kfqyXwqi6Xr5bE5EiNGTgpeUwsT68lGOgWZpPSe3fwkWmELulzb8MtSfI4P8Y8Oowmculgpsnr2yEftPVAhIPVNX1ez8m2Lw9O32rmhUd+FfbYAtqv0l5vQK2xjLCvpY6iKwRdcVW8qQK9Vif1kHfV4nKwlq6cbEVx5TzJ3S8dR5o97s93cud9vd/u5qDVWj/MPSCUsV0RdhD/WjdfE3Cgsms8+dfymofEposyj0ynAqHv/LPz6ZYWWlKfE7BM76dX9+hQahnnt4aTa06ayHu3ApiKffP3am6YqK7eB5htkOHxJelPDisWUfgzgM3D7/q1kxPEf9PkXc8OwRpOW8fgBtuKJ7eWIbLcChpDLZJkRQ2BNfEGf/vfaJbpokGX51Qt7JwAtW4iNyFA3T4xNQXpnQlAgoWV/+k1LtdCOO+Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwPygwU9Cb6weygO4NqiT6p9/e+meCy3xgGgutAlbX3dJslYR1nG23qGcKYslwuGKRwyzA0ShSmE6jb6Uf2cbUAg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "ECA59172D8B89CF4C8525E2EE1472F8F6AFF05B01B6DA32C6EF5036DEDE99B14", + "previousBlockHash": "E2BC4953AFDE742A44C2090AD5736A318E9246DBE31EA1282C68DE052B5B9B3A", "noteCommitment": { "type": "Buffer", - "data": "base64:X1tHiVaQED4Ezozi+ZsypIRHpmgPQpgp/+L4uZYC2VI=" + "data": "base64:OLF96fte4/+pS0+XB9lWqNN3EMPAatp52tCsDKYwOis=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:n15iPhXGl9vRU4s7t57FnNj1NqLVcVqfA9Ce43tNtsI=" + "data": "base64:YnY+xgyEwfu7KFxCN0fSE8SZw4tCycMtwX/kVDTsyAI=" }, "target": "880842937844725196442695540779332307793253899902937591585455087694081134", "randomness": "0", - "timestamp": 1671470861099, + "timestamp": 1671691637649, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -2008,7 +2064,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA0lqJhde5sfdHVW+uxJiIQSMSBYbcWWb9078dcLvGjuyE2vJX5taBiCyc+8ZBmXi8HaAzPM8YgLF9XzMnfgDfq4zSS6r6wXG19++hhmfKvEiF4RESkch5WvzC4Do73eLRCE8x37uEMBAyETqS/QQeoIHvjb6SVDTIkWMeaT+w1FcPgKGADyo2Ls1XRNbC0TH4KWZBrl31d7u9RaOfSc4QTwYhfSLVgp9RD6VBQybMl2uXAZ6LIWN5aj9KsLzYvFTscvYTNDlusf83UKsM+gddDJUH6ap/ARso+Bynld54DPNGjA/8IKplGVdqZan3/Tcv4kmUL68XnRp4ogmBvOiwWz4HJsBBw7YE67KLy4Lrmm2CBrPaxkSUdLgkePagtusqtQaaIFuYkwxREyHg4e2m4CdiZa8ggktSwEcdIIsnAmVKfmZw5Jahpbc0gDdCHj7RpVGi5FgmonjskORWGSTydmkZLYyKKzHb39F70h2Qz8xBMWpI5PzZoCoXPU9bYF4VhQE0VMImk/7EJmZa1Wa9D7RWNpNBtr3JmXDdHA8lzTLZ1139ZA3j61KPxpGnJZsCNBK4uNNE+p8fdRUEEKHrwbWYPw8WryGXelkpc5TJiRb9fzf9T7hmC0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwTU+Y5IzcHHpxDRJpBid3Ukev9wlDUjAVAa6skfu2aMwvBFfw5gpgi3MutfFziPPKUBxn27P9dOsv7A3tfA3mAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAh8mEU+wA7nxNoF9qJJCIvgMKxZwtV39o90aYDbzi572S5y+nL0aCc+DRM9amf9MkseUsndlwCU5xVQZgez+p2FI492XXkRoVqz5Vl1JKXBSrZWvta04RwMcnA6DZXOJOlKo114dI21zrx7er5KWWV72y/sjVZA7J4IEfGKqBZ/MA8r9hNl0iSKgc95siMCaAQX/UVfWXln3pj2oH0AI1ybGiCK52rzK0Rg2Ygb0pCVemjV8Q1h2JNhIwvTE32XYQ3hJS9m/fXob3FplPkSDbE5hloZIp26HROHfjwW1P2RyEm8Hkj0bi9q5noLNfjyHoOPkwEeyxrLKOIPlVOwSaMQG3DSHAUyASbx+55JEIs6/lKhIxBRUBRpDN6VLhts9J2itLIYDGT6iTT5xQDCgWG+Ke754f0ePcHGXnO4/yR049LVGNiVm8QuCewz1q08ahqNyaXq4oIGtbk+L+3NrHGPFbTSCAjWW2CnetuWtM1RZ73DHxBRL9LVyMD8hGHx08CLjeL0dL8PsScgM5dU/X/zWXJXBlEMBoKMx99GEROBig4/zJxto4MT6oACvvkm7JYLOkT57bAEgj6xdOu4ULlxYn+qW+c+42T2xpSE4ABO3FjUUnatU5eklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOo9KA5UwFzKFAyCCUol+m5zoPbhpHXrJeTILjxkIJcz/a67v57otXfJdZTIRqtkGn/aRiTyojOKkj8+6Kh2uAg==" } ] } @@ -2152,5 +2208,145 @@ } ] } + ], + "Blockchain asset updates when spending and burning the same note in a block fails validation as double spend when spend and burn the same note": [ + { + "id": "98e57449-b702-4b9c-af09-b723d18a2ed3", + "name": "test", + "spendingKey": "e8b4ba8c402644bf740ec1fabf289e10664ac3ee6993fb212c72da99ade9b864", + "incomingViewKey": "4fadf1d75b4b9840bb74d4325fc2087c19f47e67d4dd183025bffc901add6207", + "outgoingViewKey": "fdd6fdf0677c0eccdc2c90d6c84ca2979b1b1611eb8c9955da2944cfab29ea2e", + "publicAddress": "92156201b114dcfa2c5fa6923887f9a96517dc03ba2250ce4d1a6cc1437002a6" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:eJqME13Ca5F8+BB7PB4/hjrxT0/3tXvsb84nFXQOxGs=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:lIIiSf8MDjeosG6sB9zXb+zPim83QkbNtYqXRKhOKNo=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1671661461224, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAACPdnKPyLjtyttfBXhpWr9/QC6l8gKqPXZIgw59DZi4yWRGJQKnAatX8ce2rsePCIrYobiCfWmREYMhiVFdqGeF0Q3h4vOpSIkn+e25Oz2iC2bsOisYkPJm9fuW9QHSyhKsOLlQKjjwQlK1uRkX32qcte77yXBg4P4ZlPXGyRGcMKtE9TYWAyufAvCEoKsyX/teOEjQl86GVtKugSKCvzgcWkd+WQtRiDMmpCjlDiMgaiJXf2jmQiSKoVFNQPX9lfSl2FqiSYZkznVNOMtYP1KpzJHiigmTWkAUDrl05PUdQuARq5EpM3C143/0KvLLf8VxHqAXSHnfRZEFORaCAG3QXTpxCOft10GwCiEPxN1/N+Xi19kbYF5n0asjKkalIGmji7r3ixip9cRCIkorU6rovoO1LH8Ax3BV020akBIIJkrzojvkHmKCS02BunV6+6iq9YQRElgkCjSgtaWCsnhGrj87lrLxoCaeLlMEu+8AU/0Ya08AKK3VheVK2JfZ8ksM4BINN1MO2qmTYXPiBxdxkmMttXzdg4Mhr+foYTP807smNggnsfZRAoc8ynEGISCPk9w2nKvUweIKzEBnNxqotLQesNMn2WglAI2q7mwuJIVyroG/3lXElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwPZ8fE+tqq1b70ETvSUZppXz19BN2qsRfFK2KZgudja4uMKZUM1FJz9Aj+CoHzYUz1/JaCzCzwKsnTfkadGbtCg==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "41FE487B7D30075115529100462179213BF4D59AAB4021279133682428B4122B", + "noteCommitment": { + "type": "Buffer", + "data": "base64:27LBzlG+w0ZBskZyGOmmHdl5ED2Fo8E4U5jlo7oF/Vs=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:6R4Gcolm24mon8iOvaxWB6GckgKnRvi9WGDZL967Ep4=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1671661464179, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 8, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAToncRMAQNFqz6bkz4FLTGc6tSOzjkMJ8e19VJPRRhDqCspmDKTDKmUoCdLcUB+qzw5m6YbbATQ/FdBY1nBawIJ/NZKyNSHtSogocnhzWz2epBHIuKEZJkvipNXW2JYJ6sCXyoWX3EaYCtcmp8A8f9c7959up9kdm8wjBfjYamrcYNpam+w8jBuXy+/VBr1TYhHCOstTiWb8wVg13dAYbI7/dR/4hZtLQ5KjnLRIWEPuTc/irzH+AM0W/s0ICQwt2vgWCxlsvlKqCOJ29KBLLZmgcdMQBYbpcqOuUPBR4jUNYfG3cbNG5lAsD22/odC2MmUh0RiRcVMIk1obSHmNn404fdGcYiabOJumOXdQi6ZLuU4xciVUdQqZPeD1s+cQgP+CTFHmYKcYcCTIYjCUSoqXrEvR342aIjYYb2WLzfrHRZqautgsr9nQ06NXnBIsxg6tDw8PaRpymQc+aj1+bxLEGWXHAGMl73DHco50eGQsEv61D8pgCu3uoK0fYKy9uQpAjhxMpivTsCzFyReNPeI5OjPfhvW1CZ+zOVSTSR2VeqgU55tPIWTJq5FaptcacGOf+AIqGAta3jb11LpVh6K1hfSIhmHd41w2Nd52HHz5ISoTRor2pDElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUVS2fKvVhMYvac/1hmi/fam5TLNng6NkS4K2b5LiQ8r6v6XTDZW4gLtM5HWEVHlRXHoYk9SrCbs/ug1CQMFEBg==" + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACogUfVkxrBTyleZ3FLWolX8xiwur9yt2K1xiAG5ukc+RK2nes4oOQZqZgBCb7pN3ccfLC06LozoBszBXwLMdlA9iUlHqgQZXeu1Oi3GTLSqFX2medmNW4COCH6MDSgmlnQfEtrQ947IjmKMCHfVT8BtjBYUsWAX2wtwxi8gKsJsR1etGv5S9wyFIgO+sEPVEy/YmU4UBqALjMt44bUAGRGSKZg7agfNGozQclKQDAimR5bAWH0pqasFlJ4X1nAq0zFpaF0P4+XIoKtltZQIBp5cUbvMxWF+XCc0cCvjvs0WHiQS1ggXYRr1MMNoexDnUcO8MqfSogUrk3lyAYppEbXiajBNdwmuRfPgQezweP4Y68U9P97V77G/OJxV0DsRrBAAAALovd3hGON9wvv5AhI0K1W5tZrLnCk1CjL8rXj4Fp62O6SoO51O6xNpsbA1KumIZw1DHt0BC+cRQlf66iRUMgWhWy6TWgL+8ujNF4bBkg3J1Am1dR6XpVRLmjRKsKDm+CIxvAn7HhzvSNTBYDD4n5te2QjCchoEEBYUjc1vk0sp9qa8ovEzhh4p+hqm8kmtZe5nuL8EZEqD0yQN3qykHEoYDZcwejpBCdAw6zFQTw1ec/2nHT2ZzZcreVFgTGUQlXQMGPeRI+zspxLxuv7vCKMc6jFJoHLkmtA940Pay+DOJEtTKsokr6MMden95gWr0JbIb6Cm1E90AYW05Wiq7PVsTCLH3MRckPvyhA/y3Os6vHx7gzrxBk7LdA3cAgBGZKRQIY3e5zXPLCVD6hA4hjziT93s1ONKsDGO3tw/D/X+RbjFm3vEmT3H93I0NQsLO0yNRWo27oOyYXzTBl07NWzaOzW5EVrqGwoXlLRE2Zbg/y+SIXeOBKNMBhZFiwb9FqgVoMLkVsLnDoa5CoS7r5IupfT+f4CjAfjLN1TElMHam4/k0SoGWVvsYQe1IsYw7Hie8Gx9OxlbUUWVIRnlpy9zMT4t2EzLrpwMdLFnd6nU1kaZm3i4758heUXI/sqqpAZ+wPIvFgm4CtdZsK1vZFKdDYvL9TL/LrOvxpH7ItbXzPTk7wNJ0pPTEEuWfYTxXFBYwCJzzpYFvlxzs58R0rbp+0vQXYYW+MIf/pUO8twbm/YqBHD9kzsu7zFixcaH4KG6KJ+8S40vaYI8QOYRvqa/hJW7D7kEK7Yt2T7i1tWzZsat+EjroaF/XyGcG9YF6pxjNHPrQMjO81kp3if2UItOxevaCOn5qxgIAAAAAAAAARIXwrAg9JT17IsayCSdNPY13XGgHm6bUfSfYVMRT8Y3MXcPWxf2z2zlkhfcOfgLdgjWfwmXa9lkorTA84GUUBg==" + }, + { + "type": "Buffer", + "data": "base64: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" + } + ] + } + ], + "Blockchain asset updates when spending and burning the same note in a block fails validation as double spend": [ + { + "id": "8ef4ac4f-a24a-4c26-90e1-e3a7e3c4446e", + "name": "test", + "spendingKey": "4d7306a264d428f5d34c4d92dacb00a97dcd52751d792df608c5e98a59ebc545", + "incomingViewKey": "c815319893304db4cba4bdf5737f33db0bd85d9c7733f6332c0a891cb2146307", + "outgoingViewKey": "387cfc093c7751c1e02174961ccd682964d976fe3351da49dcc692efa8db0dbb", + "publicAddress": "7586f54f064a95f1db2775d63923b8984f6712b6df5b2a3f9f8738a399864d83" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:EmOndeaJ0oAB+j2OgR5aOUhdQWMB358ool0twYXyLx0=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:TOSnHeByy1qiqzTSnt4ObOSPnkyBNRCiN07c7CAhrNg=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1671691638141, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAvnvHikaIzTJ1qtDLyCweD7EIdtTnIpdl6+AcnRSG27SJD2tnBkuM/L0/Q8q+LFpMyxJP47XXhq6s+5hvCHv5DOydHlxaifBtydOcRwnXg6C5NYZ9+gUoIqeb/XAZRqfuC09do8aP8v25eJ04RPeuZrdgBkluSwAZYRMN68Kg56UOMvDHoeGqWnx1/HZlyJpgIX6bscIoZ2FxVuKjDFoU7pYhsEswaCp2t3ikchvEwxCZzxtRHMilkjavT0jBHGghqSEHfgSu6fXne7+OSCGzG/Yv/g3IHOOIhO0UyS2Br6j6DhzVczrh9mrjA2Az/3QO6juy7gQU37e1g8cnulV/OzttKhCVL46OCHfmXT1/n+rsrhHrFGlYLKCutflmpu443NAYmNoWoNcoR4M3Rn+LuQ04Bni5ZWF/OO2aw0WzCWZGkXryu2JVga4uwQoP1ShArPIfsOhI3GT6JWg3ShtF7MWTFJzOvrwU7aJVkIVtWikks/tu6uC0z9FcDMZcl6A3zfbaHWBNN2f/SEsMO5moQ56jujlisfpqTZKEqqmHqin0eSjrUSnaUdayqyxOmyK/MIviSzT/4YzcGitBuI6sVRUTobzXt35dDlsEWC5DDkmR8aAQxytjW0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwlcHDmlirIgsVNUWfLwKYAtfJjZKPg9WCp3cJnxs3kFbBn3IwHxrwT51KrYYaeKp40AkF+K2GZgN11HebICA6Aw==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "50BB4C4C7F5AEE989BAFF8A12E02A93EB0C213BB89B2D42EF7E3E38F64F28812", + "noteCommitment": { + "type": "Buffer", + "data": "base64:tvpehExgW0+taq1zJ6EThgW6Bs6l1cbFL/mJp5o6oSw=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:AUE6OMgnuV9YpmbWKmRM0mLnH/oRSBYi4lvOJ2VO6tc=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1671691641102, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 8, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA5G7tXY+MWZCpZ+4xh1xucculOqILsIrgGaq79jQL3POhR0QqvsMnokCnewDEa7oECYlVnrirczD6ayFKccyuRpD287E3mFLl3hOILRWeYiSWs95gH3YyfkwHjVKEWTUrggaD5HamOTCiQu8DX4k+pYPIDU2u+dAql4xoUWufppcZwfe58dxpPZ5iffARWRCJaujWjHtJsrLPP4C3ia8lSUo2wzHrRrD9UHrgFRNKO7Gv+oiprxtB1+PT2o1uk3SffJBgJ4dxvFHp3tVwtRtLg5mtghJvuvivqgtMdyf6cTkGg4bjx9E7xC6soOJ3nhYwOR8OgAVNdRmwZJ45Rt8HbxKZLC7pFde5763OgEISELJiyxMMliB+aOFd8qH0QVBFgmP4m8feqDsls2hIUHIryuzfFrzyyxtX8QOWHsZcE6wEJez1sTq/6NSPFGBA9CEFUl2FbY9/98zGn27ANK2notfNoyKcav/NSe9aZRFM7PgElnAPxEsxLIVCEC4KyId3qRUwMmpyGPoLSA8c8juHjOruxIVSVLG+z6KmRBJ/PwInJsHWCpUxgD7AHhduBSyK99PRxYxcvWSEd3RrQyaAAGdzucQzZtqqsc7Pu8xn7DhZXMvqze9MsElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwjuitSvZqHL0tjJnClkDIKi6OlfUjraqigFgFumH5XjIkjfHiTb10bCeTkCZXEAmmSqZEXCKUlzQIy8+4RAr1CQ==" + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA/lju+p38PZaHrqAQnDfSKLUcGOSmhlzAtj1+WKRPeTilTuf9X80l5a3H4u5vIX7ml8sPVrb5QsMkrZXWGCM6SorDea39EHxlgNQVc+HZR8+LuCcXVWnp2hc8noEprckz53zAT9zL2k2IPxGYgUHM8C2u7Dd2ZpOdu71ymqLUEq8K5gN+MJgVnkiYhe3NMBzPscOYuM+jGGx/cn8A6E+s+0nudHhSNKZ8s4IoW7/7xiqSHnJmpC7UMii/W68PaqhP6+eDB2IhPgFLvLf4hiRPz/XxoVE4udOVD7dt3WdDCGumbP8xeG5NCyjIfLnW55MfwpboOKcp5iz1TF/pfbQlRRJjp3XmidKAAfo9joEeWjlIXUFjAd+fKKJdLcGF8i8dBAAAAMGRRNx/VDK2XaL2v8VRCegstXvm/WBr+D70+9D9kVBOa2ofed9rbIkIcl3QmPS14M9rF3URRuW5vSLJH+eWjOdOtnE2ago770aTTC5QPWJ9AqW88b0T/CX4BocWOVC7Da/8L1Pg8at4vqjeGcAgDXslar/dd4LBHkOxxmBJMGnc3Kq4SHMZHAG7isunVY7mWYPn6gohEBi9gqQYS9huMsEykfZfri6NLtVBZFd3+SlyLuoCO6QgZvn79MXOEeSafxcz87QUnAFtzX7yPgCEos2yG+So5Vtx5BsKHo0BMJGzR4ivhN2XMzM3534YMiSMvIqF6bYbkJ+xb0CDIFi8PQmx8eorW25eKmcj16UACvBNmb7/pDolrD/UADA4nTwijurqbo/xZdkadE4a/avzALtfVOwuB2kI/tsiBKB1njJvzCptLxqtqOPZASWGLhDJUyW7crnwiKtd08P5E1vaERTD/eDteNKbAetb2ukwtBa0g+q0BSZXNkIey4GwlJYzwk4NrOWYAagkkBCzl1HEq26jtcLqYvlIRNtSRW1KQzQNM4xfYc645LyZMO90pMznjuYJNh45xSfVGvHL/V41/KnhtTbiX2Pc7wiT5nTIIhPxy45cn3hxChJL6kgq43zXyASK3rY1kK4BAIrxndbWAFsE+RZlkvn6SrMJobUsVUrYp/2p6CQhFMFVPjr5fzp+uOj5MsnKqz9nGjncgtxG4k7awxGVypx+wFM6oFQWUSWcdn/NvwcIq2dAGiD92k1j2dpwDQVpnpJQ+PLvAcZ+mOi2sNDX9iIO+Ge9+QY91MDLtLeRq32XayjXyGcG9YF6pxjNHPrQMjO81kp3if2UItOxevaCOn5qxgIAAAAAAAAAZOsM4J8k6ykfZ7hm9vVT1eDlS0GUK13kmJZMkWhgNVtsYOnhMT3Pp1RWS9ISEo1StrnUlBTYIlz1nyju+PluAw==" + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl1gzEkXda7DUiXojKUvPTD+hrPU110pLbt58Cia6wuem1pfU+n2h3BBUqvR9EuGhGZl+r3LfbhcT9PYUrAUDM7lz6mzohl26aDigv2y7ibeyOZB6FS1gY9+g1SkWaqwtXMgINtnPfqIOm2h4RaF2AxDiNgAo8JMgSbQC9EmUeR0Fr1WrE7Qg0zm1ZZMOStIQvKeZJI7+y7DgZ5alKcNz+sjwjTdfBzyr5XiVPJa7miCS1KMaJ1oSwFj+VfhGloF/TdhsZlki7R/metF4cWUo9zYgWGfz0PwC4p9msQSXfIGE1YkHof0G9+2kYloZUUke+mQWDBIBDsuP9ndXMoaZ5hJjp3XmidKAAfo9joEeWjlIXUFjAd+fKKJdLcGF8i8dBAAAAMGRRNx/VDK2XaL2v8VRCegstXvm/WBr+D70+9D9kVBOyvUixbMpIAnR7n8tpHeceSFycWvD30fWmry6wZvLlDT/9O6gzWDmwO2CqEVQu0wrS1PK7B1a4vffz43pFBv6AK+ufBXYjbUYEf3iaqHu4dG/mKDejG+lD8Qep3RL5Y8zvHsswSTm9CDMFXw4gNWJlofuFba9Tkd4MAKTKdqPk/j4Wk0s51NawYEbdjyxwGPuVDzIWDRvBCeVAEzBym0gpRUD1VYFpk3pB2qccSYKnEnB3eGefnA4TF3PmSZgIzivjVOklSw2HqrgCY6XOjxBVqnyNMbuqgI06DS6qrfiO4Stpj5MWV16+4StzYy2h9DAS+Z/h2yJH2hkmEy7q6XEhIjGAwhh9iNnOsjc4fx+zmb6RrKn1i4JcIVX04G5cVKDn0+XaM7HgfMt8nj81nbIu3gfnJsC3k7RAvJy/Ee8ewqPpear85hdMUgKksapma+gny6NAwLhTh/PLWF4GCXogdr0uBAmW053+Zejcsw/WYXgJAEVSRxIDCKXSKP1VfMzSRXDQpmUts3j5Y0GkcauqpKUL9D5g+DReUKbJhGhGr7u+Dz20LyCEdp3h6jDAw88WvIbX/3UH7EJQ0gj8CjsZJCqZEdCmGW/+ahDFD1Vng6P1MbyFY5zDqwXOpB6qrI+8d5W9Nv6IP9xt1yb29gTI2jDpXIOO+Nt9gVKglwpJN/13w2qOtKZiHO0FbtIhvY0a/QR3DLLTSPavR+kcWnUAPun6VeveMecpZirSZnyeue/AofiWXkEgKkaXeoCYH+/qyhE2l1yeoGM7JG5v14YQSru4OuGFBpiPYHOsSPem5Vy7Ock6w7URTCqlZkjvwDHLfiyJiptGw+Lcj8TXHF3N0F20eWNpMOrtEzzUAS5OWkPJCcnpwAzTNvR1yNTTOJM7966a19kLzcNdjSQ4xwco3VMELxYe9zFfZfnKBGQNvSzgOSo3hsBXH4B87IPyVc/7lpi6KhEAFWUACWFFN4JkUYyjcGzH4w642umfzzGPXv8fbVoAqaRYiwI+jY7R0WyFW/ASx6mjYd1mw9apQUktbOWRYvTQKgejVw1eyb05VuQL2AYWoKVB2USrqkptslQWbPf1T8/FkVQ573GXR78dj+Y63PFRW8Q/titW965of9JN1tPyxiW3+HnyLd0wsNlzX3ke6fSV/LkwDqJ71mc88AfIb6l9gMI5F18eDuk0jt1fsKzdglR2QLsQVtmIIcqwgNc/iFU99DG8Q7NTprWuVYUrqVBHlBtE9grOV/htOEY8YmVawldJ66ULvkeYGy6wVYhj2o6srEag2LJOssQo0JfJwLRhIJ8TZk3NFXI2bSfRAtrO09yn9Gh+3qdIo99NeekB4cytxjoEnaFFU+LDkbjMF4Eqhs7aMXonWPvi1HdSZJhAqwU9cbyZc41+Qu+7mkxeApDYLXbjmV3/kEbYluYz/gCV/fh2q3QhYyp9kBFiIeGak9lvNIHCp2d8QEEAZ22eOhgAny3XzSmRuXGRlZklMratuntjmgC7t22/GrANBUmocdaLIuj3hSFcpKI0b0nrjx9GCbhPLYLowqZBA==" + } + ] + } ] } \ No newline at end of file diff --git a/ironfish/src/blockchain/blockchain.test.ts b/ironfish/src/blockchain/blockchain.test.ts index dd6b9f46f6..c6d298488d 100644 --- a/ironfish/src/blockchain/blockchain.test.ts +++ b/ironfish/src/blockchain/blockchain.test.ts @@ -17,6 +17,7 @@ import { useBlockWithTx, useMinerBlockFixture, useMinersTxFixture, + usePostTxFixture, useTxFixture, } from '../testUtilities' import { makeBlockAfter } from '../testUtilities/helpers/blockchain' @@ -850,16 +851,14 @@ describe('Blockchain', () => { asset: Asset, value: bigint, ): Promise { - return useBlockWithRawTxFixture( - node.chain, - node.workerPool, - account, - [], - [], - [{ asset, value }], - [], - sequence, - ) + const mint = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + mints: [{ asset, value }], + }) + + return await useMinerBlockFixture(node.chain, sequence, undefined, undefined, [mint]) } async function burnAsset( @@ -885,28 +884,30 @@ describe('Blockchain', () => { describe('with a mint description', () => { it('upserts an asset to the database', async () => { const { node } = await nodeTest.createSetup() - const wallet = node.wallet - const account = await useAccountFixture(wallet) + const account = await useAccountFixture(node.wallet) const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const value = BigInt(10) - const block = await mintAsset(node, account, 2, asset, value) - await expect(node.chain).toAddBlock(block) + const mint = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + mints: [{ asset, value: 10n }], + }) - const transactions = block.transactions - expect(transactions).toHaveLength(2) - const mintTransaction = transactions[1] + const block = await useMinerBlockFixture(node.chain, 2, undefined, undefined, [mint]) + await expect(node.chain).toAddBlock(block) const mintedAsset = await node.chain.assets.get(asset.identifier()) + expect(mintedAsset).toEqual({ - createdTransactionHash: mintTransaction.hash(), + createdTransactionHash: mint.hash(), identifier: asset.identifier(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), owner: asset.owner(), - supply: value, + supply: 10n, }) }) }) diff --git a/ironfish/src/primitives/rawTransaction.test.ts b/ironfish/src/primitives/rawTransaction.test.ts index 824326820d..e604dfe0cb 100644 --- a/ironfish/src/primitives/rawTransaction.test.ts +++ b/ironfish/src/primitives/rawTransaction.test.ts @@ -8,11 +8,8 @@ import { Witness } from '../merkletree' import { NoteHasher } from '../merkletree/hasher' import { Side } from '../merkletree/merkletree' import { IsNoteWitnessEqual } from '../merkletree/witness' -import { - useAccountFixture, - useMinerBlockFixture, - useRawTxFixture, -} from '../testUtilities/fixtures' +import { useAccountFixture, useMinerBlockFixture } from '../testUtilities/fixtures' +import { createRawTransaction } from '../testUtilities/helpers/transaction' import { createNodeTest } from '../testUtilities/nodeTest' import { Note } from './note' import { RawTransaction, RawTransactionSerde } from './rawTransaction' @@ -44,7 +41,7 @@ describe('RawTransaction', () => { value: 1n, } - const raw = await useRawTxFixture({ + const raw = await createRawTransaction({ wallet: nodeTest.wallet, from: account, to: account, diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures.ts index ead5b9da3e..b6c432d38d 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures.ts @@ -11,12 +11,11 @@ import { Block, BlockSerde, SerializedBlock } from '../primitives/block' import { BurnDescription } from '../primitives/burnDescription' import { MintDescription } from '../primitives/mintDescription' import { NoteEncrypted } from '../primitives/noteEncrypted' -import { RawTransaction, RawTransactionSerde } from '../primitives/rawTransaction' import { SerializedTransaction, Transaction } from '../primitives/transaction' import { IJSON } from '../serde' import { Account, AccountValue, Wallet } from '../wallet' import { WorkerPool } from '../workerPool/pool' -import { buildRawTransaction } from './helpers/transaction' +import { buildRawTransaction, createRawTransaction } from './helpers/transaction' import { getCurrentTestPath } from './utils' const FIXTURE_FOLDER = '__fixtures__' @@ -224,7 +223,8 @@ export async function useMinerBlockFixture( ) } -export async function useRawTxFixture(options: { +export async function usePostTxFixture(options: { + node: IronfishNode wallet: Wallet from: Account to?: Account @@ -240,36 +240,10 @@ export async function useRawTxFixture(options: { }[] mints?: MintDescription[] burns?: BurnDescription[] -}): Promise { - const generate = async () => { - const receives = options.receives ?? [] - - if (options.to) { - receives.push({ - publicAddress: options.to.publicAddress, - amount: options.amount ?? 1n, - memo: '', - assetIdentifier: options.assetIdentifier ?? Asset.nativeIdentifier(), - }) - } - - return await options.wallet.createTransaction( - options.from, - receives, - options.mints ?? [], - options.burns ?? [], - options.fee ?? 0n, - options.expiration ?? 0, - ) - } - - return useFixture(generate, { - serialize: (raw: RawTransaction): Buffer => { - return RawTransactionSerde.serialize(raw) - }, - deserialize: (data): RawTransaction => { - return RawTransactionSerde.deserialize(data) - }, +}): Promise { + return useTxFixture(options.wallet, options.from, options.from, async () => { + const raw = await createRawTransaction(options) + return options.node.workerPool.postTransaction(raw) }) } diff --git a/ironfish/src/testUtilities/helpers/transaction.ts b/ironfish/src/testUtilities/helpers/transaction.ts index 3871b0cb9b..22a172562e 100644 --- a/ironfish/src/testUtilities/helpers/transaction.ts +++ b/ironfish/src/testUtilities/helpers/transaction.ts @@ -2,13 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' import { Assert } from '../../assert' import { Blockchain } from '../../blockchain' import { BurnDescription } from '../../primitives/burnDescription' import { MintDescription } from '../../primitives/mintDescription' import { NoteEncrypted } from '../../primitives/noteEncrypted' +import { RawTransaction } from '../../primitives/rawTransaction' import { Transaction } from '../../primitives/transaction' -import { Account } from '../../wallet' +import { Account, Wallet } from '../../wallet' import { WorkerPool } from '../../workerPool' export function isTransactionMine(transaction: Transaction, account: Account): boolean { @@ -64,3 +66,41 @@ export async function buildRawTransaction( 0, ) } + +export async function createRawTransaction(options: { + wallet: Wallet + from: Account + to?: Account + fee?: bigint + amount?: bigint + expiration?: number + assetIdentifier?: Buffer + receives?: { + publicAddress: string + amount: bigint + memo: string + assetIdentifier: Buffer + }[] + mints?: MintDescription[] + burns?: BurnDescription[] +}): Promise { + const receives = options.receives ?? [] + + if (options.to) { + receives.push({ + publicAddress: options.to.publicAddress, + amount: options.amount ?? 1n, + memo: '', + assetIdentifier: options.assetIdentifier ?? Asset.nativeIdentifier(), + }) + } + + return await options.wallet.createTransaction( + options.from, + receives, + options.mints ?? [], + options.burns ?? [], + options.fee ?? 0n, + options.expiration ?? 0, + ) +} diff --git a/ironfish/src/workerPool/tasks/postTransaction.test.ts b/ironfish/src/workerPool/tasks/postTransaction.test.ts index f9765384de..794738a563 100644 --- a/ironfish/src/workerPool/tasks/postTransaction.test.ts +++ b/ironfish/src/workerPool/tasks/postTransaction.test.ts @@ -7,8 +7,8 @@ import { useAccountFixture, useMinerBlockFixture, useMinersTxFixture, - useRawTxFixture, } from '../../testUtilities' +import { createRawTransaction } from '../../testUtilities/helpers/transaction' import { PostTransactionRequest, PostTransactionResponse, @@ -30,7 +30,7 @@ describe('PostTransactionRequest', () => { await expect(nodeTest.chain).toAddBlock(block) await nodeTest.wallet.updateHead() - const raw = await useRawTxFixture({ + const raw = await createRawTransaction({ wallet: nodeTest.wallet, from: account, fee: 1n, @@ -74,7 +74,7 @@ describe('PostTransactionTask', () => { await expect(nodeTest.chain).toAddBlock(block) await nodeTest.wallet.updateHead() - const raw = await useRawTxFixture({ + const raw = await createRawTransaction({ wallet: nodeTest.wallet, from: account, fee: 5n, From 4cdeb1d64bbac6550033193ee54fb53191191fd0 Mon Sep 17 00:00:00 2001 From: Daniel Cogan Date: Tue, 3 Jan 2023 15:23:49 -0500 Subject: [PATCH 24/56] don't save latest until transaction commit (#2809) --- ironfish/src/blockchain/blockchain.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 51c50c1c28..7245f30688 100644 --- a/ironfish/src/blockchain/blockchain.ts +++ b/ironfish/src/blockchain/blockchain.ts @@ -701,6 +701,11 @@ export class Blockchain { await tx.update() this.notes.pastRootTxCommitted(tx) + + if (!this.hasGenesisBlock || isBlockLater(block.header, this.latest)) { + this.latest = block.header + } + await this.onForkBlock.emitAsync(block, tx) this.logger.warn( @@ -757,6 +762,10 @@ export class Blockchain { await tx.update() this.notes.pastRootTxCommitted(tx) + if (!this.hasGenesisBlock || isBlockLater(block.header, this.latest)) { + this.latest = block.header + } + this.head = block.header if (block.header.sequence === GENESIS_BLOCK_SEQUENCE) { @@ -1311,7 +1320,6 @@ export class Blockchain { } if (!this.hasGenesisBlock || isBlockLater(block.header, this.latest)) { - this.latest = block.header await this.meta.put('latest', hash, tx) } } From 620a4798796b2d9d37b10fe1c1b38803ab5955cf Mon Sep 17 00:00:00 2001 From: ygao76 <4500784+ygao76@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:06:04 -0800 Subject: [PATCH 25/56] Display asset identifier for accounts:notes cli (#2793) * Display asset currency in cli accounts:notes * Create a new cli to get asset info * Display both asset name and id * Format * Move function to blockchain * Create Native asset value type * Remove NATIVE_ASSET_VALUE Co-authored-by: Jason Spafford --- ironfish-cli/src/commands/accounts/notes.ts | 8 +++++++- ironfish/src/blockchain/blockchain.ts | 19 ++++++++++++++++++- ironfish/src/rpc/routes/wallet/getNotes.ts | 8 ++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/notes.ts b/ironfish-cli/src/commands/accounts/notes.ts index 2b633ba52d..cc9d1331da 100644 --- a/ironfish-cli/src/commands/accounts/notes.ts +++ b/ironfish-cli/src/commands/accounts/notes.ts @@ -37,9 +37,15 @@ export class NotesCommand extends IronfishCommand { [note], { value: { - header: 'Amount ($IRON)', + header: 'Amount', get: (row) => CurrencyUtils.renderIron(row.value), }, + assetName: { + header: 'Asset Name', + }, + assetIdentifier: { + header: 'Asset Id', + }, memo: { header: 'Memo', // Maximum memo length is 32 bytes diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 7245f30688..9b5286eb8c 100644 --- a/ironfish/src/blockchain/blockchain.ts +++ b/ironfish/src/blockchain/blockchain.ts @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' import LRU from 'blru' import { BufferMap } from 'buffer-map' import { Assert } from '../assert' @@ -53,7 +54,7 @@ import { createDB } from '../storage/utils' import { Strategy } from '../strategy' import { AsyncUtils, BenchUtils, HashUtils } from '../utils' import { WorkerPool } from '../workerPool' -import { AssetsValueEncoding } from './database/assets' +import { AssetsValue, AssetsValueEncoding } from './database/assets' import { HeaderEncoding } from './database/headers' import { SequenceToHashesValueEncoding } from './database/sequenceToHashes' import { TransactionsValueEncoding } from './database/transactions' @@ -1464,6 +1465,22 @@ export class Blockchain { this.synced = true this.onSynced.emit() } + + async getAssetById(assetIdentifier: Buffer): Promise { + if (Asset.nativeIdentifier().equals(assetIdentifier)) { + return { + createdTransactionHash: GENESIS_BLOCK_PREVIOUS, + identifier: Asset.nativeIdentifier(), + metadata: Buffer.from('Native asset of Iron Fish blockchain', 'utf8'), + name: Buffer.from('$IRON', 'utf8'), + owner: Buffer.from('Iron Fish', 'utf8'), + nonce: 0, + supply: 0n, + } + } + + return await this.assets.get(assetIdentifier) + } } export class VerifyError extends Error { diff --git a/ironfish/src/rpc/routes/wallet/getNotes.ts b/ironfish/src/rpc/routes/wallet/getNotes.ts index 22b48ec5f4..545c63522c 100644 --- a/ironfish/src/rpc/routes/wallet/getNotes.ts +++ b/ironfish/src/rpc/routes/wallet/getNotes.ts @@ -10,6 +10,8 @@ export type GetAccountNotesStreamRequest = { account?: string } export type GetAccountNotesStreamResponse = { value: string + assetIdentifier: string + assetName: string memo: string sender: string transactionHash: string @@ -27,6 +29,8 @@ export const GetAccountNotesStreamResponseSchema: yup.ObjectSchema Date: Tue, 3 Jan 2023 18:27:04 -0500 Subject: [PATCH 26/56] Add chain:asset command (#2815) * Create a new cli to get asset info * Address comments from PR * Fix incorrect error Co-authored-by: ygao76 --- ironfish-cli/src/commands/chain/asset.ts | 40 +++++++++++ ironfish/src/blockchain/blockchain.ts | 5 +- ironfish/src/rpc/clients/client.ts | 6 ++ .../src/rpc/routes/chain/getAsset.test.ts | 31 ++++++++ ironfish/src/rpc/routes/chain/getAsset.ts | 71 +++++++++++++++++++ ironfish/src/rpc/routes/chain/index.ts | 1 + 6 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 ironfish-cli/src/commands/chain/asset.ts create mode 100644 ironfish/src/rpc/routes/chain/getAsset.test.ts create mode 100644 ironfish/src/rpc/routes/chain/getAsset.ts diff --git a/ironfish-cli/src/commands/chain/asset.ts b/ironfish-cli/src/commands/chain/asset.ts new file mode 100644 index 0000000000..c5b74b2361 --- /dev/null +++ b/ironfish-cli/src/commands/chain/asset.ts @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Assert, BufferUtils } from '@ironfish/sdk' +import { IronfishCommand } from '../../command' +import { RemoteFlags } from '../../flags' + +export default class Asset extends IronfishCommand { + static description = 'Get the asset info' + + static args = [ + { + name: 'identifier', + parse: (input: string): Promise => Promise.resolve(input.trim()), + required: true, + description: 'The identifier of the asset', + }, + ] + + static flags = { + ...RemoteFlags, + } + + async start(): Promise { + const { args } = await this.parse(Asset) + Assert.isString(args.identifier) + const assetIdentifier = args.identifier + + const client = await this.sdk.connectRpc() + const data = await client.getAsset({ identifier: assetIdentifier }) + + this.log(`Name: ${BufferUtils.toHuman(Buffer.from(data.content.name, 'hex'))}`) + this.log(`Metadata: ${BufferUtils.toHuman(Buffer.from(data.content.metadata, 'hex'))}`) + this.log(`Owner: ${data.content.owner}`) + this.log(`Supply: ${data.content.supply}`) + this.log(`Nonce: ${data.content.nonce}`) + this.log(`Identifier: ${data.content.identifier}`) + this.log(`Transaction Created: ${data.content.createdTransactionHash}`) + } +} diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 9b5286eb8c..402bb26b3f 100644 --- a/ironfish/src/blockchain/blockchain.ts +++ b/ironfish/src/blockchain/blockchain.ts @@ -1466,7 +1466,7 @@ export class Blockchain { this.onSynced.emit() } - async getAssetById(assetIdentifier: Buffer): Promise { + async getAssetById(assetIdentifier: Buffer): Promise { if (Asset.nativeIdentifier().equals(assetIdentifier)) { return { createdTransactionHash: GENESIS_BLOCK_PREVIOUS, @@ -1479,7 +1479,8 @@ export class Blockchain { } } - return await this.assets.get(assetIdentifier) + const asset = await this.assets.get(assetIdentifier) + return asset || null } } diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index f884f8ccb8..16a3ccb758 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -19,6 +19,8 @@ import { GetAccountTransactionResponse, GetAccountTransactionsRequest, GetAccountTransactionsResponse, + GetAssetRequest, + GetAssetResponse, GetBalanceRequest, GetBalanceResponse, GetBlockInfoRequest, @@ -473,4 +475,8 @@ export abstract class RpcClient { params, ).waitForEnd() } + + async getAsset(params: GetAssetRequest): Promise> { + return this.request(`${ApiNamespace.chain}/getAsset`, params).waitForEnd() + } } diff --git a/ironfish/src/rpc/routes/chain/getAsset.test.ts b/ironfish/src/rpc/routes/chain/getAsset.test.ts new file mode 100644 index 0000000000..7953ef2ef3 --- /dev/null +++ b/ironfish/src/rpc/routes/chain/getAsset.test.ts @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import '../../../testUtilities/matchers' +import { Asset } from '@ironfish/rust-nodejs' +import { Assert } from '../../../assert' +import { createRouteTest } from '../../../testUtilities/routeTest' +import { CurrencyUtils } from '../../../utils' + +describe('Route chain.getAsset', () => { + const routeTest = createRouteTest() + + it('responds with an asset', async () => { + const asset = await routeTest.node.chain.getAssetById(Asset.nativeIdentifier()) + Assert.isNotNull(asset) + + const response = await routeTest.client.getAsset({ + identifier: asset.identifier.toString('hex'), + }) + + expect(response.content.identifier).toEqual(asset.identifier.toString('hex')) + expect(response.content.metadata).toBe(asset.metadata.toString('hex')) + expect(response.content.owner).toBe(asset.owner.toString('hex')) + expect(response.content.nonce).toBe(asset.nonce) + expect(response.content.supply).toBe(CurrencyUtils.encode(asset.supply)) + expect(response.content.createdTransactionHash).toBe( + asset.createdTransactionHash.toString('hex'), + ) + }) +}) diff --git a/ironfish/src/rpc/routes/chain/getAsset.ts b/ironfish/src/rpc/routes/chain/getAsset.ts new file mode 100644 index 0000000000..e8d5f96c97 --- /dev/null +++ b/ironfish/src/rpc/routes/chain/getAsset.ts @@ -0,0 +1,71 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { ASSET_IDENTIFIER_LENGTH } from '@ironfish/rust-nodejs' +import * as yup from 'yup' +import { CurrencyUtils } from '../../../utils' +import { ValidationError } from '../../adapters' +import { ApiNamespace, router } from '../router' + +export type GetAssetRequest = { + identifier: string +} + +export type GetAssetResponse = { + createdTransactionHash: string + identifier: string + metadata: string + name: string + nonce: number + owner: string + supply: string +} + +export const GetAssetRequestSchema: yup.ObjectSchema = yup + .object() + .shape({ + identifier: yup.string(), + }) + .defined() + +export const GetAssetResponse: yup.ObjectSchema = yup + .object({ + createdTransactionHash: yup.string().defined(), + identifier: yup.string().defined(), + metadata: yup.string().defined(), + name: yup.string().defined(), + nonce: yup.number().defined(), + owner: yup.string().defined(), + supply: yup.string().defined(), + }) + .defined() + +router.register( + `${ApiNamespace.chain}/getAsset`, + GetAssetRequestSchema, + async (request, node): Promise => { + const identifier = Buffer.from(request.data.identifier, 'hex') + + if (identifier.byteLength !== ASSET_IDENTIFIER_LENGTH) { + throw new ValidationError( + `Asset identifier is invalid length, expected ${ASSET_IDENTIFIER_LENGTH} but got ${identifier.byteLength}`, + ) + } + + const asset = await node.chain.getAssetById(identifier) + + if (!asset) { + throw new ValidationError(`No asset found with identifier ${request.data.identifier}`) + } + + request.end({ + createdTransactionHash: asset.createdTransactionHash.toString('hex'), + identifier: asset.identifier.toString('hex'), + metadata: asset.metadata.toString('hex'), + name: asset.name.toString('hex'), + nonce: asset.nonce, + owner: asset.owner.toString('hex'), + supply: CurrencyUtils.encode(asset.supply), + }) + }, +) diff --git a/ironfish/src/rpc/routes/chain/index.ts b/ironfish/src/rpc/routes/chain/index.ts index c9e62315de..4b89f3799e 100644 --- a/ironfish/src/rpc/routes/chain/index.ts +++ b/ironfish/src/rpc/routes/chain/index.ts @@ -11,3 +11,4 @@ export * from './getTransaction' export * from './getTransactionStream' export * from './showChain' export * from './getConsensusParameters' +export * from './getAsset' From f13b89523364ff891bcd6857176075409bc5a77c Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Tue, 3 Jan 2023 21:00:01 -0500 Subject: [PATCH 27/56] Remove mintAsset test function (#2810) --- ironfish/src/blockchain/blockchain.test.ts | 123 +++++++++++++----- ironfish/src/testUtilities/fixtures.ts | 54 +++++++- .../src/testUtilities/helpers/transaction.ts | 42 ------ 3 files changed, 141 insertions(+), 78 deletions(-) diff --git a/ironfish/src/blockchain/blockchain.test.ts b/ironfish/src/blockchain/blockchain.test.ts index c6d298488d..5b8a624017 100644 --- a/ironfish/src/blockchain/blockchain.test.ts +++ b/ironfish/src/blockchain/blockchain.test.ts @@ -17,6 +17,7 @@ import { useBlockWithTx, useMinerBlockFixture, useMinersTxFixture, + useMintBlockFixture, usePostTxFixture, useTxFixture, } from '../testUtilities' @@ -844,23 +845,6 @@ describe('Blockchain', () => { }) describe('asset updates', () => { - async function mintAsset( - node: IronfishNode, - account: Account, - sequence: number, - asset: Asset, - value: bigint, - ): Promise { - const mint = await usePostTxFixture({ - node: node, - wallet: node.wallet, - from: account, - mints: [{ asset, value }], - }) - - return await useMinerBlockFixture(node.chain, sequence, undefined, undefined, [mint]) - } - async function burnAsset( node: IronfishNode, account: Account, @@ -922,7 +906,14 @@ describe('Blockchain', () => { // Mint so we have an existing asset const mintValue = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValue) + + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValue, + }) await expect(node.chain).toAddBlock(blockA) const transactions = blockA.transactions const mintTransaction = transactions[1] @@ -950,12 +941,24 @@ describe('Blockchain', () => { const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') const mintValueA = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValueA) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValueA, + }) await expect(node.chain).toAddBlock(blockA) const mintTransactionA = blockA.transactions[1] const mintValueB = BigInt(2) - const blockB = await mintAsset(node, account, 3, asset, mintValueB) + const blockB = await useMintBlockFixture({ + node, + account, + sequence: 3, + asset, + value: mintValueB, + }) await expect(node.chain).toAddBlock(blockB) const mintedAsset = await node.chain.assets.get(asset.identifier()) @@ -980,7 +983,13 @@ describe('Blockchain', () => { const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') const value = BigInt(10) - const block = await mintAsset(node, account, 2, asset, value) + const block = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value, + }) await expect(node.chain).toAddBlock(block) await node.chain.removeBlock(block.header.hash) @@ -999,11 +1008,23 @@ describe('Blockchain', () => { const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') const mintValueA = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValueA) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValueA, + }) await expect(node.chain).toAddBlock(blockA) const mintValueB = BigInt(2) - const blockB = await mintAsset(node, account, 3, asset, mintValueB) + const blockB = await useMintBlockFixture({ + node, + account, + sequence: 3, + asset, + value: mintValueB, + }) await expect(node.chain).toAddBlock(blockB) await node.chain.removeBlock(blockB.header.hash) @@ -1024,7 +1045,13 @@ describe('Blockchain', () => { const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') const mintValue = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValue) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValue, + }) await expect(node.chain).toAddBlock(blockA) const burnValue = BigInt(3) @@ -1051,7 +1078,13 @@ describe('Blockchain', () => { const assetIdentifier = asset.identifier() const mintValue = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValue) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValue, + }) await expect(node.chain).toAddBlock(blockA) // Perform a hack where we manually delete the asset from the chain @@ -1081,7 +1114,13 @@ describe('Blockchain', () => { const assetIdentifier = asset.identifier() const mintValue = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValue) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValue, + }) await expect(node.chain).toAddBlock(blockA) const record = await node.chain.assets.get(assetIdentifier) @@ -1114,7 +1153,13 @@ describe('Blockchain', () => { // 1. Mint 10 const mintValueA = BigInt(10) - const blockA = await mintAsset(node, account, 2, asset, mintValueA) + const blockA = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValueA, + }) await expect(node.chain).toAddBlock(blockA) // Check first mint value let record = await node.chain.assets.get(assetIdentifier) @@ -1126,7 +1171,13 @@ describe('Blockchain', () => { // 2. Mint 8 const mintValueB = BigInt(8) - const blockB = await mintAsset(node, account, 3, asset, mintValueB) + const blockB = await useMintBlockFixture({ + node, + account, + sequence: 2, + asset, + value: mintValueB, + }) await expect(node.chain).toAddBlock(blockB) // Check aggregate mint value record = await node.chain.assets.get(assetIdentifier) @@ -1174,7 +1225,13 @@ describe('Blockchain', () => { // 6. Mint some more const mintValueE = BigInt(10) - const blockE = await mintAsset(node, account, 5, asset, mintValueE) + const blockE = await useMintBlockFixture({ + node, + account, + sequence: 5, + asset, + value: mintValueE, + }) await expect(node.chain).toAddBlock(blockE) // Check aggregate mint value record = await node.chain.assets.get(assetIdentifier) @@ -1209,7 +1266,13 @@ describe('Blockchain', () => { // G -> A1 // -> B1 -> B2 - const blockA1 = await mintAsset(nodeA, accountA, 2, asset, mintValue) + const blockA1 = await useMintBlockFixture({ + node: nodeA, + account: accountA, + sequence: 2, + asset, + value: mintValue, + }) await nodeA.chain.addBlock(blockA1) // Verify Node A has the asset diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures.ts index b6c432d38d..18f8aecf3d 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures.ts @@ -15,7 +15,7 @@ import { SerializedTransaction, Transaction } from '../primitives/transaction' import { IJSON } from '../serde' import { Account, AccountValue, Wallet } from '../wallet' import { WorkerPool } from '../workerPool/pool' -import { buildRawTransaction, createRawTransaction } from './helpers/transaction' +import { createRawTransaction } from './helpers/transaction' import { getCurrentTestPath } from './utils' const FIXTURE_FOLDER = '__fixtures__' @@ -223,6 +223,29 @@ export async function useMinerBlockFixture( ) } +export async function useMintBlockFixture(options: { + node: IronfishNode + account: Account + asset: Asset + value: bigint + sequence?: number +}): Promise { + if (!options.sequence) { + options.sequence = options.node.chain.head.sequence + } + + const mint = await usePostTxFixture({ + node: options.node, + wallet: options.node.wallet, + from: options.account, + mints: [{ asset: options.asset, value: options.value }], + }) + + return useMinerBlockFixture(options.node.chain, options.sequence, undefined, undefined, [ + mint, + ]) +} + export async function usePostTxFixture(options: { node: IronfishNode wallet: Wallet @@ -301,15 +324,34 @@ export async function useBlockWithRawTxFixture( sequence: number, ): Promise { const generate = async () => { - const transaction = await buildRawTransaction( - chain, - pool, - sender, - notesToSpend, + const spends = await Promise.all( + notesToSpend.map(async (n) => { + const note = n.decryptNoteForOwner(sender.incomingViewKey) + Assert.isNotUndefined(note) + const treeIndex = await chain.notes.leavesIndex.get(n.merkleHash()) + Assert.isNotUndefined(treeIndex) + const witness = await chain.notes.witness(treeIndex) + Assert.isNotNull(witness) + + return { + note, + treeSize: witness.treeSize(), + authPath: witness.authenticationPath, + rootHash: witness.rootHash, + } + }), + ) + + const transaction = await pool.createTransaction( + sender.spendingKey, + spends, receives, mints, burns, + BigInt(0), + 0, ) + return chain.newBlock( [transaction], await chain.strategy.createMinersFee(transaction.fee(), sequence, sender.spendingKey), diff --git a/ironfish/src/testUtilities/helpers/transaction.ts b/ironfish/src/testUtilities/helpers/transaction.ts index 22a172562e..032575696d 100644 --- a/ironfish/src/testUtilities/helpers/transaction.ts +++ b/ironfish/src/testUtilities/helpers/transaction.ts @@ -3,15 +3,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Asset } from '@ironfish/rust-nodejs' -import { Assert } from '../../assert' -import { Blockchain } from '../../blockchain' import { BurnDescription } from '../../primitives/burnDescription' import { MintDescription } from '../../primitives/mintDescription' -import { NoteEncrypted } from '../../primitives/noteEncrypted' import { RawTransaction } from '../../primitives/rawTransaction' import { Transaction } from '../../primitives/transaction' import { Account, Wallet } from '../../wallet' -import { WorkerPool } from '../../workerPool' export function isTransactionMine(transaction: Transaction, account: Account): boolean { for (const note of transaction.notes) { @@ -29,44 +25,6 @@ export function isTransactionMine(transaction: Transaction, account: Account): b return false } -export async function buildRawTransaction( - chain: Blockchain, - pool: WorkerPool, - sender: Account, - notesToSpend: NoteEncrypted[], - receives: { publicAddress: string; amount: bigint; memo: string; assetIdentifier: Buffer }[], - mints: MintDescription[], - burns: BurnDescription[], -): Promise { - const spends = await Promise.all( - notesToSpend.map(async (n) => { - const note = n.decryptNoteForOwner(sender.incomingViewKey) - Assert.isNotUndefined(note) - const treeIndex = await chain.notes.leavesIndex.get(n.merkleHash()) - Assert.isNotUndefined(treeIndex) - const witness = await chain.notes.witness(treeIndex) - Assert.isNotNull(witness) - - return { - note, - treeSize: witness.treeSize(), - authPath: witness.authenticationPath, - rootHash: witness.rootHash, - } - }), - ) - - return pool.createTransaction( - sender.spendingKey, - spends, - receives, - mints, - burns, - BigInt(0), - 0, - ) -} - export async function createRawTransaction(options: { wallet: Wallet from: Account From d32d9087f0e74cfe3d75c740fe073855bf8a9e50 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Wed, 4 Jan 2023 11:19:45 -0500 Subject: [PATCH 28/56] feat(ironfish): Update mint arguments to be consistent with pay (#2817) * feat(ironfish): Update mint arguments to be consistent with pay * refactor(ironfish): Remove un-needed null --- ironfish/src/rpc/routes/assets/mint.ts | 6 ++++++ ironfish/src/wallet/wallet.ts | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ironfish/src/rpc/routes/assets/mint.ts b/ironfish/src/rpc/routes/assets/mint.ts index 6f074693c6..c1f2444789 100644 --- a/ironfish/src/rpc/routes/assets/mint.ts +++ b/ironfish/src/rpc/routes/assets/mint.ts @@ -13,6 +13,8 @@ export interface MintAssetRequest { metadata: string name: string value: string + expiration?: number + expirationDelta?: number } export interface MintAssetResponse { @@ -27,6 +29,8 @@ export const MintAssetRequestSchema: yup.ObjectSchema = yup metadata: yup.string().required(), name: yup.string().required(), value: yup.string().required(), + expiration: yup.number().optional(), + expirationDelta: yup.number().optional(), }) .defined() @@ -63,6 +67,8 @@ router.register( request.data.metadata, value, fee, + request.data.expirationDelta ?? node.config.get('transactionExpirationDelta'), + request.data.expiration, ) Assert.isEqual(transaction.mints.length, 1) const mint = transaction.mints[0] diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 48ea42f14f..2c5ad8d5d8 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -701,14 +701,28 @@ export class Wallet { metadata: string, value: bigint, fee: bigint, + transactionExpirationDelta: number, + expiration?: number, ): Promise { const heaviestHead = this.chain.head if (heaviestHead === null) { throw new Error('You must have a genesis block to create a transaction') } + expiration = expiration ?? heaviestHead.sequence + transactionExpirationDelta + if (this.chain.verifier.isExpiredSequence(expiration, this.chain.head.sequence)) { + throw new Error('Invalid expiration sequence for transaction') + } + const asset = new Asset(account.spendingKey, name, metadata) - const raw = await this.createTransaction(account, [], [{ asset, value }], [], fee, 0) + const raw = await this.createTransaction( + account, + [], + [{ asset, value }], + [], + fee, + expiration, + ) const transaction = await this.postTransaction(raw) From fc67f55124d0c3d7066f4de3d3feca6000459324 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:31:57 -0800 Subject: [PATCH 29/56] adds chain state fields to balances datastore (#2792) * adds chain state fields to balances datastore instead of storing only a bigint with the asset balance as the value in the balances store, stores an object containing the balance and the block hash and sequence of the most recent balance update. now that we only update the balance when blocks are connected and disconnected from the chain the stored balance value corresponds to a specific chain state. storing this chain state alongside the balance will allow us to inform users of what chain state their balance reflects. a number of users were confused by balances while accounts were scanning during phase 2: their transactions would be on the chain, but the transaction wouldn't be reflected in their account balance because the account was behind the chain. - defines BalanceValue type to include balance, blockHash, and sequence - replaces value in balances datastore with BalanceValue - propagates BalanceValue through all reads/writes on balances store * renames 'balance' field in balances store to 'unconfirmed' makes it explicit that the stored balance is the unconfirmed balance. --- .../src/primitives/rawTransaction.test.ts | 4 +- .../src/rpc/routes/wallet/removeAccount.ts | 4 +- ironfish/src/wallet/account.test.ts | 21 ++++-- ironfish/src/wallet/account.ts | 39 +++++++--- ironfish/src/wallet/wallet.test.ts | 10 +-- ironfish/src/wallet/wallet.ts | 2 +- .../__fixtures__/balanceValue.test.ts.fixture | 30 ++++++++ .../src/wallet/walletdb/balanceValue.test.ts | 51 +++++++++++++ ironfish/src/wallet/walletdb/balanceValue.ts | 74 +++++++++++++++++++ ironfish/src/wallet/walletdb/walletdb.ts | 32 ++++++-- 10 files changed, 231 insertions(+), 36 deletions(-) create mode 100644 ironfish/src/wallet/walletdb/__fixtures__/balanceValue.test.ts.fixture create mode 100644 ironfish/src/wallet/walletdb/balanceValue.test.ts create mode 100644 ironfish/src/wallet/walletdb/balanceValue.ts diff --git a/ironfish/src/primitives/rawTransaction.test.ts b/ironfish/src/primitives/rawTransaction.test.ts index e604dfe0cb..7d5d7669be 100644 --- a/ironfish/src/primitives/rawTransaction.test.ts +++ b/ironfish/src/primitives/rawTransaction.test.ts @@ -29,7 +29,7 @@ describe('RawTransaction', () => { ) await expect(nodeTest.chain).toAddBlock(block) await nodeTest.wallet.updateHead() - const balance = await account.getUnconfirmedBalance(Asset.nativeIdentifier()) + const { unconfirmed } = await account.getUnconfirmedBalance(Asset.nativeIdentifier()) const burn = { assetIdentifier: Asset.nativeIdentifier(), @@ -74,7 +74,7 @@ describe('RawTransaction', () => { const nativeValue = valuesByAsset.get(Asset.nativeIdentifier()) Assert.isNotUndefined(nativeValue) - expect(nativeValue).toEqual(balance - raw.fee - mint.value - 1n) + expect(nativeValue).toEqual(unconfirmed - raw.fee - mint.value - 1n) const mintedValue = valuesByAsset.get(asset.identifier()) Assert.isNotUndefined(mintedValue) diff --git a/ironfish/src/rpc/routes/wallet/removeAccount.ts b/ironfish/src/rpc/routes/wallet/removeAccount.ts index 36802c5775..39a17cbbfe 100644 --- a/ironfish/src/rpc/routes/wallet/removeAccount.ts +++ b/ironfish/src/rpc/routes/wallet/removeAccount.ts @@ -41,8 +41,8 @@ router.register( if (!request.data.confirm) { const balances = await account.getUnconfirmedBalances() - for (const [_, balance] of balances) { - if (balance !== BigInt(0)) { + for (const [_, { unconfirmed }] of balances) { + if (unconfirmed !== BigInt(0)) { request.end({ needsConfirm: true }) return } diff --git a/ironfish/src/wallet/account.test.ts b/ironfish/src/wallet/account.test.ts index 55ca57de05..d253f8f6e5 100644 --- a/ironfish/src/wallet/account.test.ts +++ b/ironfish/src/wallet/account.test.ts @@ -11,6 +11,7 @@ import { useTxFixture, } from '../testUtilities' import { AsyncUtils } from '../utils/async' +import { BalanceValue } from './walletdb/balanceValue' describe('Accounts', () => { const nodeTest = createNodeTest() @@ -201,15 +202,23 @@ describe('Accounts', () => { const { node } = nodeTest const account = await useAccountFixture(node.wallet, 'account') - const nativeBalance = BigInt(1) + const nativeBalance = { + unconfirmed: BigInt(1), + blockHash: null, + sequence: null, + } const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const mintedAssetBalance = BigInt(7) + const mintedAssetBalance = { + unconfirmed: BigInt(7), + blockHash: null, + sequence: null, + } await account.saveUnconfirmedBalance(Asset.nativeIdentifier(), nativeBalance) await account.saveUnconfirmedBalance(asset.identifier(), mintedAssetBalance) const balances = await account.getUnconfirmedBalances() - const expectedBalances = new BufferMap([ + const expectedBalances = new BufferMap([ [Asset.nativeIdentifier(), nativeBalance], [asset.identifier(), mintedAssetBalance], ]) @@ -445,7 +454,7 @@ describe('Accounts', () => { } // disconnect transaction - await accountA.disconnectTransaction(transaction) + await accountA.disconnectTransaction(block3.header, transaction) for (const note of transaction.notes) { const decryptedNote = await accountA.getDecryptedNote(note.merkleHash()) @@ -499,7 +508,7 @@ describe('Accounts', () => { } // disconnect transaction - await accountA.disconnectTransaction(transaction) + await accountA.disconnectTransaction(block3.header, transaction) for (const spend of transaction.spends) { const spentNoteHash = await accountA.getNoteHash(spend.nullifier) @@ -539,7 +548,7 @@ describe('Accounts', () => { expect(pendingHashEntry).toBeUndefined() // disconnect transaction - await accountA.disconnectTransaction(transaction) + await accountA.disconnectTransaction(block3.header, transaction) pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index ee5950693e..729664706a 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -11,6 +11,7 @@ import { DatabaseKeyRange, IDatabaseTransaction } from '../storage' import { StorageUtils } from '../storage/database/utils' import { DecryptedNote } from '../workerPool/tasks/decryptNotes' import { AccountValue } from './walletdb/accountValue' +import { BalanceValue } from './walletdb/balanceValue' import { DecryptedNoteValue } from './walletdb/decryptedNoteValue' import { TransactionValue } from './walletdb/transactionValue' import { WalletDB } from './walletdb/walletdb' @@ -122,6 +123,8 @@ export class Account { decryptedNotes: Array, tx?: IDatabaseTransaction, ): Promise { + const blockHash = blockHeader.hash + const sequence = blockHeader.sequence const balanceDeltas = new AssetBalanceDeltas() let submittedSequence: number | null = null let timestamp = new Date() @@ -147,8 +150,8 @@ export class Account { transactionHash: transaction.hash(), nullifier: decryptedNote.nullifier, index: decryptedNote.index, - blockHash: blockHeader.hash, - sequence: blockHeader.sequence, + blockHash, + sequence, } balanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) @@ -177,15 +180,15 @@ export class Account { transaction.hash(), { transaction, - blockHash: blockHeader.hash, - sequence: blockHeader.sequence, + blockHash, + sequence, submittedSequence, timestamp, }, tx, ) - await this.updateUnconfirmedBalances(balanceDeltas, tx) + await this.updateUnconfirmedBalances(balanceDeltas, blockHash, sequence, tx) }) } @@ -249,6 +252,7 @@ export class Account { } async disconnectTransaction( + blockHeader: BlockHeader, transaction: Transaction, tx?: IDatabaseTransaction, ): Promise { @@ -320,7 +324,12 @@ export class Account { tx, ) - await this.updateUnconfirmedBalances(balanceDeltas, tx) + await this.updateUnconfirmedBalances( + balanceDeltas, + blockHeader.previousBlockHash, + blockHeader.sequence - 1, + tx, + ) }) } @@ -447,7 +456,7 @@ export class Account { }> { let unconfirmedCount = 0 - const unconfirmed = await this.getUnconfirmedBalance(assetIdentifier, tx) + const { unconfirmed } = await this.getUnconfirmedBalance(assetIdentifier, tx) let confirmed = unconfirmed if (minimumBlockConfirmations > 0) { @@ -482,8 +491,8 @@ export class Account { } } - async getUnconfirmedBalances(tx?: IDatabaseTransaction): Promise> { - const unconfirmedBalances = new BufferMap() + async getUnconfirmedBalances(tx?: IDatabaseTransaction): Promise> { + const unconfirmedBalances = new BufferMap() for await (const { assetIdentifier, balance } of this.walletDb.getUnconfirmedBalances( this, tx, @@ -496,12 +505,14 @@ export class Account { async getUnconfirmedBalance( assetIdentifier: Buffer, tx?: IDatabaseTransaction, - ): Promise { + ): Promise { return this.walletDb.getUnconfirmedBalance(this, assetIdentifier, tx) } async updateUnconfirmedBalances( balanceDeltas: BufferMap, + blockHash: Buffer | null, + sequence: number | null, tx?: IDatabaseTransaction, ): Promise { for (const [assetIdentifier, balanceDelta] of balanceDeltas) { @@ -510,7 +521,11 @@ export class Account { await this.walletDb.saveUnconfirmedBalance( this, assetIdentifier, - currentUnconfirmedBalance + balanceDelta, + { + unconfirmed: currentUnconfirmedBalance.unconfirmed + balanceDelta, + blockHash, + sequence, + }, tx, ) } @@ -518,7 +533,7 @@ export class Account { async saveUnconfirmedBalance( assetIdentifier: Buffer, - balance: bigint, + balance: BalanceValue, tx?: IDatabaseTransaction, ): Promise { await this.walletDb.saveUnconfirmedBalance(this, assetIdentifier, balance, tx) diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index 29eaa69801..ef8a7b274f 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -1088,7 +1088,7 @@ describe('Accounts', () => { await node.wallet.updateHead() const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceBefore).toEqual(2000000000n) + expect(balanceBefore.unconfirmed).toEqual(2000000000n) const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) await expect(node.chain).toAddBlock(blockA2) @@ -1096,7 +1096,7 @@ describe('Accounts', () => { await node.wallet.connectBlock(blockA2.header, [accountA, accountB]) const balanceAfter = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceAfter).toEqual(1999999998n) + expect(balanceAfter.unconfirmed).toEqual(1999999998n) }) }) @@ -1176,7 +1176,7 @@ describe('Accounts', () => { await node.wallet.updateHead() const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceBefore).toEqual(2000000000n) + expect(balanceBefore.unconfirmed).toEqual(2000000000n) const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) await expect(node.chain).toAddBlock(blockA2) @@ -1184,7 +1184,7 @@ describe('Accounts', () => { await node.wallet.updateHead() const balanceAfterConnect = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceAfterConnect).toEqual(1999999998n) + expect(balanceAfterConnect.unconfirmed).toEqual(1999999998n) await node.chain.db.transaction(async (tx) => { await node.chain.disconnect(blockA2, tx) @@ -1195,7 +1195,7 @@ describe('Accounts', () => { const balanceAfterDisconnect = await accountA.getUnconfirmedBalance( Asset.nativeIdentifier(), ) - expect(balanceAfterDisconnect).toEqual(2000000000n) + expect(balanceAfterDisconnect.unconfirmed).toEqual(2000000000n) }) }) }) diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 2c5ad8d5d8..86bbbcbf03 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -432,7 +432,7 @@ export class Wallet { for (const account of accounts) { await this.walletDb.db.transaction(async (tx) => { for await (const { transaction } of this.chain.iterateBlockTransactions(header)) { - await account.disconnectTransaction(transaction, tx) + await account.disconnectTransaction(header, transaction, tx) } await this.updateHeadHash(account, header.previousBlockHash, tx) diff --git a/ironfish/src/wallet/walletdb/__fixtures__/balanceValue.test.ts.fixture b/ironfish/src/wallet/walletdb/__fixtures__/balanceValue.test.ts.fixture new file mode 100644 index 0000000000..383b076f52 --- /dev/null +++ b/ironfish/src/wallet/walletdb/__fixtures__/balanceValue.test.ts.fixture @@ -0,0 +1,30 @@ +{ + "BalanceValueEncoding with all fields defined serializes the object into a buffer and deserializes to the original object": [ + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:BtXrlQrSx77ALa9nCiCxO+MMKkRqg3kO0gYLEp2bJCM=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:/TOL6Ie6D1ooqmdr3ZqlvIzpHSnJqt0usPlG3dzdomQ=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1671576478657, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAlDhxwugGoILLsEoGS1LvSIce7ctD9JZPrMpMMOvBgcCtofjR2k08gtjQl2G2X8S4I8dVR5DXPRAoXgTKShEUCRhjvdyc47BANbozLMMTxfaFGe71C7ZQFplKqTSkKfhriCJxJU5bu/iWzbBJK9lQ57Df+cOQfljg05iiDxQbiuEIc/GA21LwhXyz4LPANsX7yWdlIwZo1VteHt+ItVAcMr2aLVC4SRr2rcvIVg0/T6WVZaVsyccyA1WUDY6DusQYtluvBN8EWsYMJzZmovFzWEo+huQzaoAj7gaLDFC+RNtCENO3FbrfBy21dNVt3goSXoTLN1LMWeFWjXq7Havzlm3nH3lPTHMImzcDNkfhGoVS1niD0UVRkVM0vMOfWlQzeKocP4FF6j5OtGAxRTEHiST5ASX8I9iQGFlk0eV3ee0Cow2tnm0or2/fPGTyzuvj7XhDDV7JN6gtGcIqdG+MY1Uh6TDLskuoH2oHttlKUfDryvAXPFsq/yHIHJaQcWN8ifgTUEK7TClIO1w26ePProJigti1XKryb1i7S47mPDPhbtYzHzBFPMpX4aKmVdqnlVcfzO2UWm3nhHE0m9Ezm/OEZYw6izUhs3q189zSzmgoYDNL8/tDcklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwoNkyA5lOZCC0MMCT2uWjkoKYa7Zx98PWajey8HDq++7oo9w2TNNiHyEuZ6kUETNJyzNwE6YD85xGk1R3URT8BQ==" + } + ] + } + ] +} \ No newline at end of file diff --git a/ironfish/src/wallet/walletdb/balanceValue.test.ts b/ironfish/src/wallet/walletdb/balanceValue.test.ts new file mode 100644 index 0000000000..459b1b72a5 --- /dev/null +++ b/ironfish/src/wallet/walletdb/balanceValue.test.ts @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { createNodeTest, useMinerBlockFixture } from '../../testUtilities' +import { BufferUtils } from '../../utils/buffer' +import { BalanceValue, BalanceValueEncoding } from './balanceValue' + +describe('BalanceValueEncoding', () => { + const nodeTest = createNodeTest() + + function expectBalanceValueToMatch(a: BalanceValue, b: BalanceValue): void { + expect(a.unconfirmed).toEqual(b.unconfirmed) + expect(BufferUtils.equalsNullable(a.blockHash, b.blockHash)).toBe(true) + expect(a.sequence).toEqual(b.sequence) + } + + describe('with a null block hash and sequence', () => { + it('serializes the object into a buffer and deserializes to the original object', () => { + const encoder = new BalanceValueEncoding() + + const balanceValue = { + unconfirmed: 0n, + blockHash: null, + sequence: null, + } + + const buffer = encoder.serialize(balanceValue) + const deserializedValue = encoder.deserialize(buffer) + expectBalanceValueToMatch(deserializedValue, balanceValue) + }) + }) + + describe('with all fields defined', () => { + it('serializes the object into a buffer and deserializes to the original object', async () => { + const { node } = nodeTest + const block = await useMinerBlockFixture(node.chain) + + const encoder = new BalanceValueEncoding() + + const balanceValue = { + unconfirmed: 0n, + blockHash: block.header.hash, + sequence: block.header.sequence, + } + + const buffer = encoder.serialize(balanceValue) + const deserializedValue = encoder.deserialize(buffer) + expectBalanceValueToMatch(deserializedValue, balanceValue) + }) + }) +}) diff --git a/ironfish/src/wallet/walletdb/balanceValue.ts b/ironfish/src/wallet/walletdb/balanceValue.ts new file mode 100644 index 0000000000..a224fbe698 --- /dev/null +++ b/ironfish/src/wallet/walletdb/balanceValue.ts @@ -0,0 +1,74 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import bufio from 'bufio' +import { IDatabaseEncoding } from '../../storage' + +export interface BalanceValue { + unconfirmed: bigint + blockHash: Buffer | null + sequence: number | null +} + +export class BalanceValueEncoding implements IDatabaseEncoding { + serialize(value: BalanceValue): Buffer { + const bw = bufio.write(this.getSize(value)) + bw.writeBigU64(value.unconfirmed) + + let flags = 0 + flags |= Number(!!value.blockHash) << 0 + flags |= Number(!!value.sequence) << 1 + bw.writeU8(flags) + + if (value.blockHash) { + bw.writeHash(value.blockHash) + } + + if (value.sequence) { + bw.writeU32(value.sequence) + } + + return bw.render() + } + + deserialize(buffer: Buffer): BalanceValue { + const reader = bufio.read(buffer, true) + const value = reader.readBigU64() + + const flags = reader.readU8() + const hasBlockHash = flags & (1 << 0) + const hasSequence = flags & (1 << 1) + + let blockHash = null + if (hasBlockHash) { + blockHash = reader.readHash() + } + + let sequence = null + if (hasSequence) { + sequence = reader.readU32() + } + + return { + unconfirmed: value, + blockHash, + sequence, + } + } + + getSize(value: BalanceValue): number { + let size = 0 + size += 8 // value + size += 1 // flags + + if (value.blockHash) { + size += 32 + } + + if (value.sequence) { + size += 4 + } + + return size + } +} diff --git a/ironfish/src/wallet/walletdb/walletdb.ts b/ironfish/src/wallet/walletdb/walletdb.ts index 642b19416d..2e57e31b14 100644 --- a/ironfish/src/wallet/walletdb/walletdb.ts +++ b/ironfish/src/wallet/walletdb/walletdb.ts @@ -10,7 +10,6 @@ import { NoteEncryptedHash } from '../../primitives/noteEncrypted' import { Nullifier } from '../../primitives/nullifier' import { TransactionHash } from '../../primitives/transaction' import { - BigIntLEEncoding, BUFFER_ENCODING, BufferEncoding, IDatabase, @@ -28,6 +27,7 @@ import { createDB } from '../../storage/utils' import { WorkerPool } from '../../workerPool' import { Account, calculateAccountPrefix } from '../account' import { AccountValue, AccountValueEncoding } from './accountValue' +import { BalanceValue, BalanceValueEncoding } from './balanceValue' import { DecryptedNoteValue, DecryptedNoteValueEncoding } from './decryptedNoteValue' import { AccountsDBMeta, MetaValue, MetaValueEncoding } from './metaValue' import { TransactionValue, TransactionValueEncoding } from './transactionValue' @@ -58,7 +58,7 @@ export class WalletDB { balances: IDatabaseStore<{ key: [Account['prefix'], Buffer] - value: bigint + value: BalanceValue }> decryptedNotes: IDatabaseStore<{ @@ -139,7 +139,7 @@ export class WalletDB { this.balances = this.db.addStore({ name: 'b', keyEncoding: new PrefixEncoding(new BufferEncoding(), new BufferEncoding(), 4), - valueEncoding: new BigIntLEEncoding(), + valueEncoding: new BalanceValueEncoding(), }) this.decryptedNotes = this.db.addStore({ @@ -218,7 +218,16 @@ export class WalletDB { tx, ) if (nativeUnconfirmedBalance === undefined) { - await this.saveUnconfirmedBalance(account, Asset.nativeIdentifier(), BigInt(0), tx) + await this.saveUnconfirmedBalance( + account, + Asset.nativeIdentifier(), + { + unconfirmed: BigInt(0), + blockHash: null, + sequence: null, + }, + tx, + ) } }) } @@ -626,15 +635,22 @@ export class WalletDB { account: Account, assetIdentifier: Buffer, tx?: IDatabaseTransaction, - ): Promise { + ): Promise { const unconfirmedBalance = await this.balances.get([account.prefix, assetIdentifier], tx) - return unconfirmedBalance ?? BigInt(0) + + return ( + unconfirmedBalance ?? { + unconfirmed: BigInt(0), + blockHash: null, + sequence: null, + } + ) } async *getUnconfirmedBalances( account: Account, tx?: IDatabaseTransaction, - ): AsyncGenerator<{ assetIdentifier: Buffer; balance: bigint }> { + ): AsyncGenerator<{ assetIdentifier: Buffer; balance: BalanceValue }> { for await (const [[_, assetIdentifier], balance] of this.balances.getAllIter( tx, account.prefixRange, @@ -646,7 +662,7 @@ export class WalletDB { async saveUnconfirmedBalance( account: Account, assetIdentifier: Buffer, - balance: bigint, + balance: BalanceValue, tx?: IDatabaseTransaction, ): Promise { await this.balances.put([account.prefix, assetIdentifier], balance, tx) From 65b6b312a6705ef9f7b485355abf45d8f910663c Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Wed, 4 Jan 2023 15:55:19 -0500 Subject: [PATCH 30/56] Fix note encoding not using CurrencyUtils (#2821) All currency encoding should be done using CurrencyUtils.encode() and CurrencyUtils.decode() --- ironfish/src/rpc/routes/assets/mint.test.ts | 4 +++- ironfish/src/rpc/routes/chain/getTransactionStream.ts | 3 ++- ironfish/src/rpc/routes/wallet/getNotes.ts | 3 ++- ironfish/src/rpc/routes/wallet/getTransaction.ts | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ironfish/src/rpc/routes/assets/mint.test.ts b/ironfish/src/rpc/routes/assets/mint.test.ts index b2999ff113..9d6d31d166 100644 --- a/ironfish/src/rpc/routes/assets/mint.test.ts +++ b/ironfish/src/rpc/routes/assets/mint.test.ts @@ -4,6 +4,7 @@ import { Asset } from '@ironfish/rust-nodejs' import { useAccountFixture, useTxFixture } from '../../../testUtilities' import { createRouteTest } from '../../../testUtilities/routeTest' +import { CurrencyUtils } from '../../../utils' describe('mint', () => { const routeTest = createRouteTest(true) @@ -81,8 +82,9 @@ describe('mint', () => { fee: '1', metadata: asset.metadata().toString('hex'), name: asset.name().toString('hex'), - value: value.toString(), + value: CurrencyUtils.encode(value), }) + expect(response.content).toEqual({ assetIdentifier: asset.identifier().toString('hex'), hash: mintTransaction.hash().toString('hex'), diff --git a/ironfish/src/rpc/routes/chain/getTransactionStream.ts b/ironfish/src/rpc/routes/chain/getTransactionStream.ts index 3270bdc392..aa67df1c58 100644 --- a/ironfish/src/rpc/routes/chain/getTransactionStream.ts +++ b/ironfish/src/rpc/routes/chain/getTransactionStream.ts @@ -6,6 +6,7 @@ import { Assert } from '../../../assert' import { ChainProcessor } from '../../../chainProcessor' import { Block } from '../../../primitives/block' import { BlockHeader } from '../../../primitives/blockheader' +import { CurrencyUtils } from '../../../utils' import { PromiseUtils } from '../../../utils/promise' import { isValidIncomingViewKey } from '../../../wallet/validator' import { ValidationError } from '../../adapters/errors' @@ -116,7 +117,7 @@ router.register Date: Wed, 4 Jan 2023 16:06:05 -0500 Subject: [PATCH 31/56] Delete fees RPC namespace (#2822) * Delete fees RPC namespace This is part of the chain, no need to create another namespace. * Fix lint --- .../commands/service/estimate-fee-rates.ts | 4 ++-- ironfish/src/rpc/clients/client.ts | 12 +++++----- .../__fixtures__/estimateFee.test.ts.fixture | 0 .../{fees => chain}/estimateFee.test.ts | 24 +++++++++---------- .../rpc/routes/{fees => chain}/estimateFee.ts | 2 +- .../{fees => chain}/estimateFeeRates.ts | 2 +- ironfish/src/rpc/routes/chain/index.ts | 2 ++ ironfish/src/rpc/routes/fees/index.ts | 6 ----- ironfish/src/rpc/routes/index.ts | 1 - ironfish/src/rpc/routes/router.ts | 1 - 10 files changed, 23 insertions(+), 31 deletions(-) rename ironfish/src/rpc/routes/{fees => chain}/__fixtures__/estimateFee.test.ts.fixture (100%) rename ironfish/src/rpc/routes/{fees => chain}/estimateFee.test.ts (68%) rename ironfish/src/rpc/routes/{fees => chain}/estimateFee.ts (98%) rename ironfish/src/rpc/routes/{fees => chain}/estimateFeeRates.ts (97%) delete mode 100644 ironfish/src/rpc/routes/fees/index.ts diff --git a/ironfish-cli/src/commands/service/estimate-fee-rates.ts b/ironfish-cli/src/commands/service/estimate-fee-rates.ts index aa4d3f7299..55ab8f8171 100644 --- a/ironfish-cli/src/commands/service/estimate-fee-rates.ts +++ b/ironfish-cli/src/commands/service/estimate-fee-rates.ts @@ -61,10 +61,10 @@ export default class EstimateFees extends IronfishCommand { continue } - const response = await this.sdk.client.estimateFeeRates({}) + const response = await this.sdk.client.estimateFeeRates() if (!(response.content.low && response.content.medium && response.content.high)) { - this.log('Unexpected response from fees/estimateFeeRates') + this.log('Unexpected response') } else { const feeRateLow = Number(CurrencyUtils.decode(response.content.low)) const feeRateMedium = Number(CurrencyUtils.decode(response.content.medium)) diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index 16a3ccb758..5c02724403 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -63,6 +63,10 @@ import { UseAccountResponse, } from '../routes' import { MintAssetRequest, MintAssetResponse } from '../routes/assets/mint' +import { + EstimateFeeRatesRequest, + EstimateFeeRatesResponse, +} from '../routes/chain/estimateFeeRates' import { ExportChainStreamRequest, ExportChainStreamResponse, @@ -72,10 +76,6 @@ import { FollowChainStreamResponse, } from '../routes/chain/followChain' import { OnGossipRequest, OnGossipResponse } from '../routes/events/onGossip' -import { - EstimateFeeRatesRequest, - EstimateFeeRatesResponse, -} from '../routes/fees/estimateFeeRates' import { GetPeerRequest, GetPeerResponse } from '../routes/peers/getPeer' import { GetPeerMessagesRequest, @@ -370,7 +370,7 @@ export abstract class RpcClient { params?: EstimateFeeRatesRequest, ): Promise> { return this.request( - `${ApiNamespace.fees}/estimateFeeRates`, + `${ApiNamespace.chain}/estimateFeeRates`, params, ).waitForEnd() } @@ -379,7 +379,7 @@ export abstract class RpcClient { params: EstimateFeeRequest, ): Promise> { return this.request( - `${ApiNamespace.fees}/estimateFee`, + `${ApiNamespace.chain}/estimateFee`, params, ).waitForEnd() } diff --git a/ironfish/src/rpc/routes/fees/__fixtures__/estimateFee.test.ts.fixture b/ironfish/src/rpc/routes/chain/__fixtures__/estimateFee.test.ts.fixture similarity index 100% rename from ironfish/src/rpc/routes/fees/__fixtures__/estimateFee.test.ts.fixture rename to ironfish/src/rpc/routes/chain/__fixtures__/estimateFee.test.ts.fixture diff --git a/ironfish/src/rpc/routes/fees/estimateFee.test.ts b/ironfish/src/rpc/routes/chain/estimateFee.test.ts similarity index 68% rename from ironfish/src/rpc/routes/fees/estimateFee.test.ts rename to ironfish/src/rpc/routes/chain/estimateFee.test.ts index fa75f12ac0..baf6442e61 100644 --- a/ironfish/src/rpc/routes/fees/estimateFee.test.ts +++ b/ironfish/src/rpc/routes/chain/estimateFee.test.ts @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { useBlockWithTx } from '../../../testUtilities' import { createRouteTest } from '../../../testUtilities/routeTest' -import { EstimateFeeRequest } from './estimateFee' describe('estimate Fee', () => { const routeTest = createRouteTest(true) @@ -16,18 +15,17 @@ describe('estimate Fee', () => { }) await node.chain.addBlock(block) await node.wallet.updateHead() - const response = await routeTest.client - .request('fees/estimateFee', { - fromAccountName: 'existingAccount', - receives: [ - { - publicAddress: 'test2', - amount: BigInt(10).toString(), - memo: '', - }, - ], - }) - .waitForEnd() + + const response = await routeTest.client.estimateFee({ + fromAccountName: 'existingAccount', + receives: [ + { + publicAddress: 'test2', + amount: BigInt(10).toString(), + memo: '', + }, + ], + }) expect(response.content).toMatchObject({ low: '1', diff --git a/ironfish/src/rpc/routes/fees/estimateFee.ts b/ironfish/src/rpc/routes/chain/estimateFee.ts similarity index 98% rename from ironfish/src/rpc/routes/fees/estimateFee.ts rename to ironfish/src/rpc/routes/chain/estimateFee.ts index 0e0bc21304..904c312d9e 100644 --- a/ironfish/src/rpc/routes/fees/estimateFee.ts +++ b/ironfish/src/rpc/routes/chain/estimateFee.ts @@ -45,7 +45,7 @@ export const EstimateFeeResponseSchema: yup.ObjectSchema = .defined() router.register( - `${ApiNamespace.fees}/estimateFee`, + `${ApiNamespace.chain}/estimateFee`, EstimateFeeRequestSchema, async (request, node): Promise => { const account = node.wallet.getAccountByName(request.data.fromAccountName) diff --git a/ironfish/src/rpc/routes/fees/estimateFeeRates.ts b/ironfish/src/rpc/routes/chain/estimateFeeRates.ts similarity index 97% rename from ironfish/src/rpc/routes/fees/estimateFeeRates.ts rename to ironfish/src/rpc/routes/chain/estimateFeeRates.ts index 0ea8b822a0..1899c72d60 100644 --- a/ironfish/src/rpc/routes/fees/estimateFeeRates.ts +++ b/ironfish/src/rpc/routes/chain/estimateFeeRates.ts @@ -27,7 +27,7 @@ export const EstimateFeeRatesResponseSchema: yup.ObjectSchema( - `${ApiNamespace.fees}/estimateFeeRates`, + `${ApiNamespace.chain}/estimateFeeRates`, EstimateFeeRatesRequestSchema, (request, node): void => { const priority = request.data?.priority diff --git a/ironfish/src/rpc/routes/chain/index.ts b/ironfish/src/rpc/routes/chain/index.ts index 4b89f3799e..2876152b3f 100644 --- a/ironfish/src/rpc/routes/chain/index.ts +++ b/ironfish/src/rpc/routes/chain/index.ts @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +export * from './estimateFee' +export * from './estimateFeeRates' export * from './exportChain' export * from './followChain' export * from './getBlock' diff --git a/ironfish/src/rpc/routes/fees/index.ts b/ironfish/src/rpc/routes/fees/index.ts deleted file mode 100644 index da6be9cbfd..0000000000 --- a/ironfish/src/rpc/routes/fees/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -export * from './estimateFeeRates' -export * from './estimateFee' diff --git a/ironfish/src/rpc/routes/index.ts b/ironfish/src/rpc/routes/index.ts index 9ce0b2a81b..c27b3072ae 100644 --- a/ironfish/src/rpc/routes/index.ts +++ b/ironfish/src/rpc/routes/index.ts @@ -13,5 +13,4 @@ export * from './rpc' export * from './mining' export * from './transactions' export * from './faucet' -export * from './fees' export * from './workers' diff --git a/ironfish/src/rpc/routes/router.ts b/ironfish/src/rpc/routes/router.ts index 36cef7d0d2..2f22e6dec9 100644 --- a/ironfish/src/rpc/routes/router.ts +++ b/ironfish/src/rpc/routes/router.ts @@ -16,7 +16,6 @@ export enum ApiNamespace { config = 'config', event = 'event', faucet = 'faucet', - fees = 'fees', miner = 'miner', node = 'node', peer = 'peer', From c34523ba5103b7b21c3cdc65abcb90bdad3d245b Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Wed, 4 Jan 2023 16:37:54 -0500 Subject: [PATCH 32/56] feat(ironfish): Add burn method to wallet (#2816) * feat(ironfish): Add burn method to wallet * test(ironfish): Use fixtures for burn tx * test(ironfish): Use useMintBlockFixture * feat(ironfish): Add fixture util --- ironfish/src/testUtilities/fixtures.ts | 23 +++ .../__fixtures__/wallet.test.ts.fixture | 178 ++++++++++++++++++ ironfish/src/wallet/wallet.test.ts | 64 +++++++ ironfish/src/wallet/wallet.ts | 43 +++++ 4 files changed, 308 insertions(+) diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures.ts index 18f8aecf3d..d4f83263d7 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures.ts @@ -246,6 +246,29 @@ export async function useMintBlockFixture(options: { ]) } +export async function useBurnBlockFixture(options: { + node: IronfishNode + account: Account + asset: Asset + value: bigint + sequence?: number +}): Promise { + if (!options.sequence) { + options.sequence = options.node.chain.head.sequence + } + + const burn = await usePostTxFixture({ + node: options.node, + wallet: options.node.wallet, + from: options.account, + burns: [{ assetIdentifier: options.asset.identifier(), value: options.value }], + }) + + return useMinerBlockFixture(options.node.chain, options.sequence, undefined, undefined, [ + burn, + ]) +} + export async function usePostTxFixture(options: { node: IronfishNode wallet: Wallet diff --git a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture index 3419d23716..7831f04555 100644 --- a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture +++ b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture @@ -2582,5 +2582,183 @@ } ] } + ], + "Accounts burn returns a transaction with matching burn descriptions": [ + { + "id": "ee7a9916-753f-4593-86a4-9f36fe2e3099", + "name": "test", + "spendingKey": "78392760bb1c8ad7425428a647f6a2fa23a31aedbeb6aefa16d486576dc15504", + "incomingViewKey": "02a84ddec3992919648396b9a851f32c8dbc506c374aeb8a0c6854cd2c1cf803", + "outgoingViewKey": "c0cd654fefbdb1c2d715853c5a6747ead4fc85e47c657843d077bb92f8f00f6d", + "publicAddress": "117d08be80afae196e3d74802d56198050cb5a505d843021f3e5417ab2b03a34" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:gHB0fx8nidIrXNijI0PaUWWX/Xg3Ja8W44LgIgpvkWk=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:e3i+/slRhtJ1vfmYzLMBB2bH0GnMc274drNGrSNkcmQ=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672861954076, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAs/bcUC0wHa6hU4YNYgG6lHz8EP7awycLwdTIzQGWhUKSvMl4blL1ilmLLY2uzMxj/HKqKYNsFBkflqX9mo+1xMQp5h1ocuRmCn6fctknhayHQYv+CD4Sy5kE2nhifaHDubYE4brGnSlZV/HjcR68zCkGsfxu+pUBD7WDXWjFpC0WYGD6NxOFNxM5JOceBWab6vC6BrK7eVUM+LQWEN1BrXgwja0LwyeJvuv6rj9TnyiNZiS+sF/Txc8WPsaxeDUicmlvIHTtLopauVuPDYM6g84E+qNjBOrGVw+pyEQNBVomi/sYx/PkVCGFO+20ipYh/+YrzC/1ODvB/gXUgv4miIRp6qYZiax5UsbBCmkhj2K779cQmMRILsn4G+Vzll8ulmBAPS/CC/4aPuHvKG32SOtxd4uwJnjuDOG05xCoAi/gAwc+F1dqreCXS7lWut+KGtnfpIEY6wv3UGPS3H6NAuKKHNzhwQPvo9aoujcZqqr4Kuoe+VMwVyzpCXY1pVNKlYnM4pMbT9X3qmKiIufSWqx5Uqlh89+vG5kqo+NJVfQnFoNjj5fyzUStMAHpD6sHwixrNbZyjZrqpbDBzLaQvcqX/Fhw7+Q1LZZHPlXtN2gl5uN25+SDUUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUBTQTqFVYWzFiXKrT/caR9zSgHs9LbVc2rCW+KvzgbAj7t1zjToFKIxNRswsZoCP4IZWQbwyWH4skVJBE90XCA==" + } + ] + }, + { + "type": "Buffer", + "data": "base64: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" + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "AAD0762E1CD12284C4A0E2B975DA3986DCEBD03AD7ABFCD437280F3601B29D6D", + "noteCommitment": { + "type": "Buffer", + "data": "base64:3cV1xjaEqYc7NokeT19Q9A/mmet6enRwJMtn5rlaiiw=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:6Wjdi0b8tzVnmbySeFoSlH8gIwtMyA+elkIGZf7fJgY=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672861957149, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 7, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAIjLINe5lf3+dzGGb9l8j2YSowkRyXdCPDwcdOTg3RlWmaHNrb+GZr7uv5xJaWTeKhi3AY5/egtbCPbRAxjd8xXalmyimay96lvPk/NAYmq2OoarS4eMv1i6W2/ltT9xy1AgJ6rvL1ky4l9jvMVK0sbCh0M3TJ5FeRxArVRjLbooOQlXyWHSHwQo23/FbxPy0ZJVt94aHn5wyJ047axM+BMvAvhfvBCyZM1uD58QPTa6nIPwobvafrmLE09WmtwPIddbgmnpexJCw40fFmpSli+cNQwHbvN0sb7rUvr2Bd3JZsVubstqLXyBbxhXIw45ZNBLM81TeUrnUjOgDIiCnYMVFYDf9oFyU3mT2K5xCA5XbNBUY+hnn8P625BJDj1lU+fFCFLo0w49oGd0KH32WbccuBU1nj87DzLSQUScUU1a2Kkwa5m7cnrok5lSK9r3BpRJvS4iylbsReWBhHGccNG2nB3uJf70G6BCYKq+Wi8rp4KbRGFWNB981nv4ScYO/+NkOpCI8UjpXn5RQhl0sGtiYsqsMgSEVtzTTvb40I22Vk+jsjjMQRR2KvzjpBC8F4guOoOEqkPQ+GGpSs5Y0zqp+9z2zCGu1/I3Cmra5hvP3MyNJRUX9/Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwsSQM9xyFgHrWXe9Qvc8k9gjkKY2gY3QE+DuV08qYK44tu3ykaczl3BcmkoS5vi9/dI3Gh2uziBLwlU9gTCHRBQ==" + }, + { + "type": "Buffer", + "data": "base64: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" + } + ] + }, + { + "type": "Buffer", + "data": "base64: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" + } + ], + "Accounts burn subtracts balance for the asset from the wallet": [ + { + "id": "d9c9f045-724f-44d0-a8a8-0347c74d5cb7", + "name": "test", + "spendingKey": "bca5cae957662907b8ac69abcbefa7ee42e35a6d17757de6c99cba22bf8a8b95", + "incomingViewKey": "bd76d2911fd18d6fbadafcf57615eddd64fa29989c4866354107f873ca586206", + "outgoingViewKey": "b55bb92d021ffc9b481e2e9808f6c9528a9358d9e1eaadc4df59da38d4e9c7f7", + "publicAddress": "89c76352e60efd494698985f55b456f41d612bfc5a0047e049c3c6bf8461d4b2" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:BQ7l4ZUlcbNiRieGObFw/OAx0XLP2G1aCS6guR7hYUg=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:UeemxQloOmebjtsW/2Nup/B/iBLcnBfTPwOqmj7m/OE=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672861961236, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAAW6eQneAw1RnIdZpdx6n+kwEMOV48EHq7Gf6ROWo0rysUWed7jOZ/msw7Ny2Xf2dMlCWUdacf3a2JPhYk9Nko9EewiOeP7R+Ey5L6iVyRbiuZDJq7fdqd25jc9vXRto/SPTSlMDM0X0CFlAlVno2oCF8ILuHae9c/GLEkSXHGAMOlhslOpock9zCQjCsZBE49yCr5TfKlopGB0bR73lp9g2pTvgAsIifsbW97UbSMa6YXDKWW5KgbgBgRHTVEMa3gQlzuexQIuPE2xtjp7xKex6c8Q2EKzZ7Sju+KII6IyMbzHVvPZCLfO++Md8cOg+fZz0V0eojotzRYBSpf9lmV5qXZQpgiF9Rpch6dN1bSndrVwKzkm1PjSW+XjxTDwktTSjM0Bw5qZUecxKXPf0Y2Iu3DQQEWO1EDVdIz50KWExXt2Y6rPXD1OVZWm1KMzXffz6guAnJoBUDH+pXo3w0j5ZPzQ81vdGTxVbPPqXe515VkFo9f3eSdr19HDzDo2aAkRPHW4a22TH/g54JI4aAAN9TmnGl8j1YM9hPxAwlGc1ZFiWNJ+ST7QLjsU5cWbY3MQGWw6ZlvFHS+DQ3qB2BjDWTFG5vPgm7wSwiboh/eGaIAP94OJkv1klyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwb4j+au6pjdU33xK7k/7xnIR7DdoeHys0L9M+KFyy5okJwNSqqM0aMSodnC0s+AdHhtFPRaQ1lI2S2OpGCxUJBw==" + } + ] + }, + { + "type": "Buffer", + "data": "base64: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" + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "ED1D7310083B55D806DB7C3D0F7DE4F38E84D65F7166556843515DF434DC9E2F", + "noteCommitment": { + "type": "Buffer", + "data": "base64:7lMXOsnOLR8BpIoUbRAglpUgcXPyjhCEgoO08pfTBxc=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:Fa067OtyLHPmYIFZzoHrBI6RwAIe0BGwna8vOkQz5C0=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672861964392, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 7, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAASdc+JKZi3PMi+WOkb7dtTiVjm25Sc0yKObQ7Jr0md66GE5jTvYwVSw3+dUEzAWiwQTHPAVHOXfSuyGqAVIJnLVgAbG1T7Fs0NlGmxN+7Bqu5DlY924o7IQSjbPODm4U8zLt6oy8zuSU3C86AgVjfRq0JeCr1hBafycEyL/U/tUgD4rl1IbdtApgVtO2itO9dngNGrP+xHDxNJq/u9/xCQpGILUQ/McTxT/ivUTGQE2+R3CC4ppLmRZtZeuJH1+p7jikt48unQNC7BpqSowuyZQjAxh7JXbjgODyM3iqh+AdGK/DXzml+FuE9y090ZQynQ1zgkzYs/Ht6G+1tDfdcmI9ZOBCJO+vbWj+y+t3V+KsK4BxCHJ7mZeeU4XGdhn4QM+NRxwK4kVO4K5GTAXlmGq+wwTfhcaPaqhYDVdNC3XFTzwVIj/gY6WFysCneMDr1rkRMkksMnRAP6+GyL62vlUOOpIgzMGgnsmwX2tz/+PDQPDGrsxQ8pUEy04e5NK9tIr+MMqrwNnlfrJxWOLXFpNqICEw6MudBtU81pV4AImQ2jBfquFrXq1zz1l6mtsdsqRUgU4JOm2eg8KqAwJwe8i126LtjUG1Qzo7RHlbkowlsDNN/sej1yklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwyyvqa3zTRUlgvhSWj+3017QCgA6a1deZMWqK4Bfbg6OM28cjnIu0v9JBRU8J5+v9pn9epr+NgFcSGdFAhmBPAQ==" + }, + { + "type": "Buffer", + "data": "base64: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" + } + ] + }, + { + "type": "Buffer", + "data": "base64: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" + }, + { + "header": { + "sequence": 4, + "previousBlockHash": "823F49F17A7BC34698DB71D9A28D93CE4A20E3EE2ADF8F58F4FB7EF04AA78E04", + "noteCommitment": { + "type": "Buffer", + "data": "base64:DjmoMqOPgXPytV09TlEZG9A0yds5jmVUYDex2seuAFo=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:I+Odm5vVIoso3lX2WFdTD1FgPgYBjG88y+dfQstQGko=" + }, + "target": "878277375889837647326843029495509009809390053592540685978895509768758568", + "randomness": "0", + "timestamp": 1672861968457, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 10, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAa51NQ9g4b6kc9MQO0aansBx+PCC4NXXKhkZ6R4PTtiCmOvKK2GoWm0EneF/2RYz6raJ4OzKE6wfouCBJq982Rn+nIvfhP6IFO6JEzEvTBqC5neYNRGY8Pz16Jxx1aCH3PKmV8ibclA0znVQvobRoOIoPL7Jemojv5dWeNGOo438Ue/o8CTg4+zKftcs3Z3TLgzCiHbcdzTBDD6njj7KJwYwP1cbtotkWCg7ieG2sjGyR42ocPy+gulO9JG5+JcgDIsfLcFXC0j8Ha1dZ9QFHby76Kkxl4TxxFIggJnvbpiAeUl2L9YlqERIZ/JxWfyZF60tfybPFrVXbszvfIcaHBi3rVZOFQ4Mdq+JmgHXV4wzGS1ttZ3sUO9QDBBoJb31lUhuhjsT37SA+5Zmuitd7UlE5VpeE3YuGOa0ols/IdNeXrmQYXfjz0QbCVRHVdbRebmP87Ba09p3DNm8BG9JIMJeHVO2nFLo12GUNQQSNinuu7Yl8bh+1WAR9AY3XSHsZFixaFkiVCHQ/tAFevcVxgUESCXHeXjNp/DgVUisfFZZ+qpbWKnyOuKB/fuTUCtrLKgNS2OJe3wpGib4Ot50tObh2gHm4lXxfSdBTL7Vp37iAKh5YkkOGdElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwN6KLkiZiSxi84WO4r93lLiNPb6PlDRpxtl108FEdI1V5VoqMvRR59PN1wYYqUJXjGgZ6V8SKgTGM0jxOTtauAA==" + }, + { + "type": "Buffer", + "data": "base64:AQIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAKf2OSp7pJJ6RPQsQQf7obYWfzq/n1imlynBYSKw9gGSipqxMdqMhhdKF3SMwt5PzQZ2s7zzuUVg93q3dmXOkHYpaeKR7fb8IDTLzSGNWlDCulUVgO2u7cKTYsoI8YUfVZL8TRYAaso8FJjEdNcJXLTjkIY+GP8bhaMk40M79BbgONUUHmZpjjuJHIAsZj59DM1nV2L6lgNx2b3ObOa7iZeLDHu7IpqP1ZoBnHpqhwzezZUekfGho7IIakvsJfUg5MXRdRxSbJEoTY7RIi83nVMFLbaaTqMp6ZS9lRv/uhmCY0ng/23xIcQwXoY6N9oHPUEvwGjZIaNTCRetU0Ea7zu5TFzrJzi0fAaSKFG0QIJaVIHFz8o4QhIKDtPKX0wcXBwAAAO4fsr+s9PVvSWLs2Tft4GB4l2zaOFdzIXJkFTd2yYVFnDSOfy9jFqk48DUp5gA8RazTGiMBFRO3r6yDvuEvTsVrDgO0ZJHEnCR/zo9yW7BFlxdzE+lRLzZK5QR/Pt+GBq3WH1eidH8WsExgyrK2xxVUHqZkfduMjnvF5PfeXBsE1MVOIG4JGfJrI6mgZ0YY0Y7AxQcE2RiKdnGmHVFeeyfkmLw8cFEwSyBb7vGh96LiaZjryaZgqUi3QGumyen6gAsb5NeuRnlPKx+qzYJya/lSCLqPkkFoKyvDSIOGntlEgcrL/xtMBxDXT8DQnnglw4FMNRKAJG+PvnsHgK8ieZFjMgJnSR9lRYFaCso3yiL2DM2s7pbAZxbH13h5JPKgSc921E5hU9aw+LDi0CfPb7jOGrhIk9mLTh53OU1FLNG17lMXOsnOLR8BpIoUbRAglpUgcXPyjhCEgoO08pfTBxcHAAAAfbsFIdlz0AaDF0OiMRpajlM+HqXG8mVbkRV86YuqpPCIigNQF86HbCeV0km2wyyL0CwjImatnC1RC5ZltEWkj88xssPKwbxAlw+ZcD2Bl1YtIIOBX+J99nA9npNoKJ0CiD3eZzS1vSGIRkN3DUeBg4w95crFvTmrIvK5P5G3m2V6/yNcV2GEi8iyJXsblMCSjuHHitgiDydGPXdNhaJaWZRIoUiLb4sJSE8Llq2soio6ibX9QJTeqqEyztUnU504C++pHO5EjqUuvz1zcE3rOOJVZ4Fk9UJvSE+FZ5C2dc3Wtah6Z/lD5y3Ghuya6vyooRG7GlcmajLyPjKZF7td7DPwlFxys98Uqf3JwO7fkoUNrrI0/3ut4rf3gVpCI56Kc/0wxhXXq/vxhYaL36lGLbp16pyWfaCzQZdRvS5kgLvcWIo68O6wmcj/pRHvFk7b6LkhbYH6fXiZxkRHYK+JR14pZlf0dD8fgr86ueyK3+xOPR+FmZ/2JPDaM2Eiaq1cj15Bfv912IQ+ZqcSAYhRBdcqP8drbWPpRVWxVThGBi3EM3lA3bOP6cVsoZ6VfJDY01RWEWaivplcYub5CYWGMi2GH7xSYzyp5c4hWiJWLCySG8jatGBt6bXmsuiTqjk2SRbbJM3l/yO17osAaBG5GysoI7bUfQByalMSm3ZkmZMOo+Fb4Jp4Z9fN6wv8OK66DmWglGSgH/erZMo2zwzwgBw14Zf86O9e+20dTjglp9BdXzsAnqdhYjOsX/w6/dKcqW71TzuSnUr3KlN7x+p4+k02oWG3AFIrZYm8UacK8xF+4vMMaFuuk6wLj8cTcic/0hSyp28EV13O8l9RtxwDP4bfJhLU+5aGbrPn9xHcFB12KUV82govWqRVCe+qmTphMIMza8d6I2z36nWA4fpU1bFTjTpV66t0P72zxPV1HGMe38MI8lnx7wlV4x1kafcdfzp68icRM5JWbAAWGK/fgb4/zITGM9kPkFK4hKnD9cF2eMtNUrjGY4gT8Z8bckp/IuN7HL0XGTXhH9SfiyNlW81zjCcPszhS9x4OUUhP+dUBbyHYrA3mSs4h7GOymvtephpBm1ZTU5zcXaqpzRtkzP69xrCixGPY3EqvJWOeGFoKFTT175GKjA8SY547jf9NlsW3c+KvzhSMJGQ84dzdyo3MiCR6GjpmHgBeFACKv+YXg98uVWU4ldo+foC6pObecSUCCHEXXvJ50etJGNcdaC/WHXcjqwb39hU5AN+Z52ggEg9Eo3PVu3Jq39n5u51QD2mbLCjLo3Ria8ZtvyVPGpVMQ8DnzhNQylrQDEA772oJ3aus7f43uAd8/20rMavlAnG/PicQS1ViEPCq0TUrAnDj4EsF0dbe9bNEtf5QelMzLmI+UymX675fHlUA8DPbSfMPF00Cc1MVo5gsmOcuggO9OMyVl5MfDo+2qMQjm5kpnP27JfkfmZK5aRkr/myorlvG2NQkP9vi2Zr5Q5nPFrT60GupWftseq7VMKrnWsdiwZSCx/kGHFCcLa9GbNAZoS0p1xV+k+r9lEJqkd+FXgIAAAAAAAAAoG0JdYoX3pvgpBLqa9waIcVEczNhXe3EvGZyAr7VPhQVnAGTriagl/Kto5bf4q8cEKYlE431vMufEZY6sVNgCA==" + } + ] + } ] } \ No newline at end of file diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index ef8a7b274f..5ebbb3b1f3 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -9,8 +9,11 @@ import { useAccountFixture, useBlockFixture, useBlockWithTx, + useBurnBlockFixture, useMinerBlockFixture, useMinersTxFixture, + useMintBlockFixture, + usePostTxFixture, useTxFixture, } from '../testUtilities' import { AsyncUtils } from '../utils' @@ -933,6 +936,67 @@ describe('Accounts', () => { }) }) + describe('burn', () => { + it('returns a transaction with matching burn descriptions', async () => { + const { node } = await nodeTest.createSetup() + const account = await useAccountFixture(node.wallet) + + const mined = await useMinerBlockFixture(node.chain, 2, account) + await expect(node.chain).toAddBlock(mined) + await node.wallet.updateHead() + + const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') + const value = BigInt(10) + const mintBlock = await useMintBlockFixture({ node, account, asset, value, sequence: 3 }) + await expect(node.chain).toAddBlock(mintBlock) + await node.wallet.updateHead() + + const burnValue = BigInt(2) + const transaction = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + burns: [{ assetIdentifier: asset.identifier(), value: burnValue }], + }) + + expect(transaction.burns).toEqual([ + { assetIdentifier: asset.identifier(), value: burnValue }, + ]) + }) + + it('subtracts balance for the asset from the wallet', async () => { + const { node } = await nodeTest.createSetup() + const account = await useAccountFixture(node.wallet) + + const mined = await useMinerBlockFixture(node.chain, 2, account) + await expect(node.chain).toAddBlock(mined) + await node.wallet.updateHead() + + const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') + const value = BigInt(10) + const mintBlock = await useMintBlockFixture({ node, account, asset, value, sequence: 3 }) + await expect(node.chain).toAddBlock(mintBlock) + await node.wallet.updateHead() + + const burnValue = BigInt(2) + const burnBlock = await useBurnBlockFixture({ + node, + account, + asset, + value: burnValue, + sequence: 4, + }) + await expect(node.chain).toAddBlock(burnBlock) + await node.wallet.updateHead() + + expect(await node.wallet.getBalance(account, asset.identifier())).toEqual({ + unconfirmed: BigInt(8), + unconfirmedCount: 0, + confirmed: BigInt(8), + }) + }) + }) + describe('createSpendsForAsset', () => { it('returns spendable notes for a provided asset identifier', async () => { const { node } = await nodeTest.createSetup() diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 86bbbcbf03..d36ba42b33 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -739,6 +739,49 @@ export class Wallet { return transaction } + async burn( + memPool: MemPool, + account: Account, + assetIdentifier: Buffer, + value: bigint, + fee: bigint, + transactionExpirationDelta: number, + expiration?: number, + ): Promise { + const heaviestHead = this.chain.head + if (heaviestHead === null) { + throw new Error('You must have a genesis block to create a transaction') + } + + expiration = expiration ?? heaviestHead.sequence + transactionExpirationDelta + if (this.chain.verifier.isExpiredSequence(expiration, this.chain.head.sequence)) { + throw new Error('Invalid expiration sequence for transaction') + } + + const raw = await this.createTransaction( + account, + [], + [], + [{ assetIdentifier, value }], + fee, + expiration, + ) + + const transaction = await this.postTransaction(raw) + + const verify = this.chain.verifier.verifyCreatedTransaction(transaction) + if (!verify.valid) { + throw new Error(`Invalid transaction, reason: ${String(verify.reason)}`) + } + + await this.addPendingTransaction(transaction) + memPool.acceptTransaction(transaction) + this.broadcastTransaction(transaction) + this.onTransactionCreated.emit(transaction) + + return transaction + } + async createTransaction( sender: Account, receives: { From 8e56ee68c1cde820a09edd518e9e130a6077ca11 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Wed, 4 Jan 2023 16:46:23 -0500 Subject: [PATCH 33/56] Merge transaction namespace into wallet RPC namespace (#2823) --- ironfish/src/rpc/clients/client.ts | 2 +- ironfish/src/rpc/routes/router.ts | 1 - ironfish/src/rpc/routes/transactions/sendTransaction.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index 5c02724403..a076e1bb66 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -338,7 +338,7 @@ export abstract class RpcClient { params: SendTransactionRequest, ): Promise> { return this.request( - `${ApiNamespace.transaction}/sendTransaction`, + `${ApiNamespace.wallet}/sendTransaction`, params, ).waitForEnd() } diff --git a/ironfish/src/rpc/routes/router.ts b/ironfish/src/rpc/routes/router.ts index 2f22e6dec9..523cd379c4 100644 --- a/ironfish/src/rpc/routes/router.ts +++ b/ironfish/src/rpc/routes/router.ts @@ -19,7 +19,6 @@ export enum ApiNamespace { miner = 'miner', node = 'node', peer = 'peer', - transaction = 'transaction', wallet = 'wallet', worker = 'worker', rpc = 'rpc', diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.ts b/ironfish/src/rpc/routes/transactions/sendTransaction.ts index 59dfb88a29..26591a6346 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.ts +++ b/ironfish/src/rpc/routes/transactions/sendTransaction.ts @@ -74,7 +74,7 @@ export const SendTransactionResponseSchema: yup.ObjectSchema( - `${ApiNamespace.transaction}/sendTransaction`, + `${ApiNamespace.wallet}/sendTransaction`, SendTransactionRequestSchema, async (request, node): Promise => { const transaction = request.data From 362d51dc8de76d6f369bf142cb321bb8e3379236 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Wed, 4 Jan 2023 16:47:08 -0500 Subject: [PATCH 34/56] Upgrading oclif/core to 1.23.1 (#2824) This adds a fix I commited to oclif/core to fix the prompt return type released in 1.20.1 here, https://github.com/oclif/core/releases/tag/1.20.1 --- ironfish-cli/package.json | 2 +- ironfish-cli/src/commands/accounts/create.ts | 4 ++-- ironfish-cli/src/commands/accounts/import.ts | 20 +++++++++--------- ironfish-cli/src/commands/accounts/pay.ts | 12 +++++------ ironfish-cli/src/commands/accounts/remove.ts | 2 +- ironfish-cli/src/commands/faucet.ts | 8 +++---- ironfish-cli/src/commands/testnet.ts | 4 ++-- yarn.lock | 22 ++++++++++++++------ 8 files changed, 42 insertions(+), 32 deletions(-) diff --git a/ironfish-cli/package.json b/ironfish-cli/package.json index 20dae0cb0b..dcb536282a 100644 --- a/ironfish-cli/package.json +++ b/ironfish-cli/package.json @@ -59,7 +59,7 @@ "@aws-sdk/client-s3": "3.127.0", "@ironfish/rust-nodejs": "0.1.18", "@ironfish/sdk": "0.0.32", - "@oclif/core": "1.16.1", + "@oclif/core": "1.23.1", "@oclif/plugin-help": "5.1.12", "@oclif/plugin-not-found": "2.3.1", "@types/tar": "6.1.1", diff --git a/ironfish-cli/src/commands/accounts/create.ts b/ironfish-cli/src/commands/accounts/create.ts index cf8791b058..1de79637ac 100644 --- a/ironfish-cli/src/commands/accounts/create.ts +++ b/ironfish-cli/src/commands/accounts/create.ts @@ -27,9 +27,9 @@ export class CreateCommand extends IronfishCommand { let name = args.account as string if (!name) { - name = (await CliUx.ux.prompt('Enter the name of the account', { + name = await CliUx.ux.prompt('Enter the name of the account', { required: true, - })) as string + }) } const client = await this.sdk.connectRpc() diff --git a/ironfish-cli/src/commands/accounts/import.ts b/ironfish-cli/src/commands/accounts/import.ts index 5a24c3042b..c1c8e8e4ef 100644 --- a/ironfish-cli/src/commands/accounts/import.ts +++ b/ironfish-cli/src/commands/accounts/import.ts @@ -88,25 +88,25 @@ export class ImportCommand extends IronfishCommand { } async importTTY(): Promise> { - const accountName = (await CliUx.ux.prompt('Enter the account name', { + const accountName = await CliUx.ux.prompt('Enter the account name', { required: true, - })) as string + }) - const spendingKey = (await CliUx.ux.prompt('Enter the account spending key', { + const spendingKey = await CliUx.ux.prompt('Enter the account spending key', { required: true, - })) as string + }) - const incomingViewKey = (await CliUx.ux.prompt('Enter the account incoming view key', { + const incomingViewKey = await CliUx.ux.prompt('Enter the account incoming view key', { required: true, - })) as string + }) - const outgoingViewKey = (await CliUx.ux.prompt('Enter the account outgoing view key', { + const outgoingViewKey = await CliUx.ux.prompt('Enter the account outgoing view key', { required: true, - })) as string + }) - const publicAddress = (await CliUx.ux.prompt('Enter the account public address', { + const publicAddress = await CliUx.ux.prompt('Enter the account public address', { required: true, - })) as string + }) return { name: accountName, diff --git a/ironfish-cli/src/commands/accounts/pay.ts b/ironfish-cli/src/commands/accounts/pay.ts index a7668b63b8..a8b1b6facf 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/accounts/pay.ts @@ -87,12 +87,12 @@ export class Pay extends IronfishCommand { if (amount === null) { const response = await client.getAccountBalance({ account: from, assetIdentifier }) - const input = (await CliUx.ux.prompt( + const input = await CliUx.ux.prompt( `Enter the amount (balance: ${CurrencyUtils.renderIron(response.content.confirmed)})`, { required: true, }, - )) as string + ) amount = CurrencyUtils.decodeIron(input) } @@ -116,9 +116,9 @@ export class Pay extends IronfishCommand { } if (!to) { - to = (await CliUx.ux.prompt('Enter the the public address of the recipient', { + to = await CliUx.ux.prompt('Enter the the public address of the recipient', { required: true, - })) as string + }) if (!isValidPublicAddress(to)) { this.error(`A valid public address is required`) @@ -158,7 +158,7 @@ export class Pay extends IronfishCommand { suggestedFee = '' } - const input = (await CliUx.ux.prompt( + const input = await CliUx.ux.prompt( `Enter the fee amount in $IRON (min: ${CurrencyUtils.renderIron( 1n, )} recommended: ${suggestedFee})`, @@ -166,7 +166,7 @@ export class Pay extends IronfishCommand { required: true, default: suggestedFee, }, - )) as string + ) fee = CurrencyUtils.decodeIron(input) } diff --git a/ironfish-cli/src/commands/accounts/remove.ts b/ironfish-cli/src/commands/accounts/remove.ts index dd3e788592..37141f59c0 100644 --- a/ironfish-cli/src/commands/accounts/remove.ts +++ b/ironfish-cli/src/commands/accounts/remove.ts @@ -35,7 +35,7 @@ export class RemoveCommand extends IronfishCommand { const response = await client.removeAccount({ name, confirm }) if (response.content.needsConfirm) { - const value = (await CliUx.ux.prompt(`Are you sure? Type ${name} to confirm`)) as string + const value = await CliUx.ux.prompt(`Are you sure? Type ${name} to confirm`) if (value !== name) { this.log(`Aborting: ${value} did not match ${name}`) diff --git a/ironfish-cli/src/commands/faucet.ts b/ironfish-cli/src/commands/faucet.ts index 05a3d08fcf..b94df6168b 100644 --- a/ironfish-cli/src/commands/faucet.ts +++ b/ironfish-cli/src/commands/faucet.ts @@ -41,9 +41,9 @@ export class FaucetCommand extends IronfishCommand { if (!email) { email = - ((await CliUx.ux.prompt('Enter your email to stay updated with Iron Fish', { + (await CliUx.ux.prompt('Enter your email to stay updated with Iron Fish', { required: false, - })) as string) || undefined + })) || undefined } // Create an account if one is not set @@ -53,9 +53,9 @@ export class FaucetCommand extends IronfishCommand { if (!accountName) { this.log(`You don't have a default account set up yet. Let's create one first!`) accountName = - ((await CliUx.ux.prompt('Please enter the name of your new Iron Fish account', { + (await CliUx.ux.prompt('Please enter the name of your new Iron Fish account', { required: false, - })) as string) || 'default' + })) || 'default' await client.createAccount({ name: accountName, default: true }) } diff --git a/ironfish-cli/src/commands/testnet.ts b/ironfish-cli/src/commands/testnet.ts index fce1b09bcc..9f05cd2f08 100644 --- a/ironfish-cli/src/commands/testnet.ts +++ b/ironfish-cli/src/commands/testnet.ts @@ -49,12 +49,12 @@ export default class Testnet extends IronfishCommand { let userArg = ((args.user as string | undefined) || '').trim() if (!userArg) { - userArg = (await CliUx.ux.prompt( + userArg = await CliUx.ux.prompt( 'Enter the user graffiti or url to a testnet user like https://testnet.ironfish.network/users/1080\nUser Graffiti or URL', { required: true, }, - )) as string + ) this.log('') } diff --git a/yarn.lock b/yarn.lock index a830907a24..63b8ad8731 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3418,13 +3418,13 @@ supports-color "^8.1.1" tslib "^2" -"@oclif/core@1.16.1": - version "1.16.1" - resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.16.1.tgz#39663c903f859f8e37b375d7466b92b4394e1c8d" - integrity sha512-MfzgqcWzWymndd934pd52JAwy0RIgWWYnC0Ed7bxUVYWF4HFb3KmsE7x9/QBP9392Q14vxXi2GNLHboM/5vaDA== +"@oclif/core@1.23.1": + version "1.23.1" + resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.23.1.tgz#bebbbc4e02a4c1a4216d64165f892037f8a1e14a" + integrity sha512-nz7wVGesJ1Qg74p1KNKluZpQ3Z042mqdaRlczEI4Xwqj5s9jjdDBCDHNkiGzV4UAKzicVzipNj6qqhyUWKYnaA== dependencies: "@oclif/linewrap" "^1.0.0" - "@oclif/screen" "^3.0.2" + "@oclif/screen" "^3.0.3" ansi-escapes "^4.3.2" ansi-styles "^4.3.0" cardinal "^2.1.1" @@ -3448,7 +3448,7 @@ strip-ansi "^6.0.1" supports-color "^8.1.1" supports-hyperlinks "^2.2.0" - tslib "^2.3.1" + tslib "^2.4.1" widest-line "^3.1.0" wrap-ansi "^7.0.0" @@ -3562,6 +3562,11 @@ resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-3.0.2.tgz#969054308fe98d130c02844a45cc792199b75670" integrity sha512-S/SF/XYJeevwIgHFmVDAFRUvM3m+OjhvCAYMk78ZJQCYCQ5wS7j+LTt1ZEv2jpEEGg2tx/F6TYYWxddNAYHrFQ== +"@oclif/screen@^3.0.3": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-3.0.4.tgz#663db0ecaf23f3184e7f01886ed578060e4a7f1c" + integrity sha512-IMsTN1dXEXaOSre27j/ywGbBjrzx0FNd1XmuhCWCB9NTPrhWI1Ifbz+YLSEcstfQfocYsrbrIessxXb2oon4lA== + "@oclif/test@2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@oclif/test/-/test-2.1.0.tgz#e5a0ba619c890770782e48c82d18f5921e2d2b9f" @@ -10800,6 +10805,11 @@ tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" From d185be77d604d42053dc9bf9aac889caba921d35 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Wed, 4 Jan 2023 13:50:33 -0800 Subject: [PATCH 35/56] adds balance delta mapping to transactionValue (#2819) * adds balance delta mapping to transactionValue users currently cannot see how much they sent or received in each transaction listed in the CLI. the only way to present this information to the user with the current walletDb schema would be to load each note and spend for each transaction each time we look up the transaction. stores the balance delta for each asset on the value in the wallet transactions store. serializes buffer map as a list of key-value pairs prepended with the length of the list. keys are 32-byte asset identifiers and values are bigints. * addresses pr feedback --- ironfish/src/wallet/account.ts | 16 +++-- .../transactionValue.test.ts.fixture | 36 ++++++++++ .../wallet/walletdb/transactionValue.test.ts | 71 ++++++++++++++++++- .../src/wallet/walletdb/transactionValue.ts | 31 +++++++- 4 files changed, 148 insertions(+), 6 deletions(-) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index 729664706a..bf21db56d3 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -125,7 +125,7 @@ export class Account { ): Promise { const blockHash = blockHeader.hash const sequence = blockHeader.sequence - const balanceDeltas = new AssetBalanceDeltas() + const assetBalanceDeltas = new AssetBalanceDeltas() let submittedSequence: number | null = null let timestamp = new Date() @@ -154,7 +154,7 @@ export class Account { sequence, } - balanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) + assetBalanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -169,7 +169,7 @@ export class Account { Assert.isNotUndefined(note) - balanceDeltas.increment(note.note.assetIdentifier(), -note.note.value()) + assetBalanceDeltas.increment(note.note.assetIdentifier(), -note.note.value()) const spentNote = { ...note, spent: true } await this.walletDb.saveDecryptedNote(this, spentNoteHash, spentNote, tx) @@ -184,11 +184,12 @@ export class Account { sequence, submittedSequence, timestamp, + assetBalanceDeltas: assetBalanceDeltas, }, tx, ) - await this.updateUnconfirmedBalances(balanceDeltas, blockHash, sequence, tx) + await this.updateUnconfirmedBalances(assetBalanceDeltas, blockHash, sequence, tx) }) } @@ -198,6 +199,8 @@ export class Account { submittedSequence: number | null, tx?: IDatabaseTransaction, ): Promise { + const assetBalanceDeltas = new AssetBalanceDeltas() + await this.walletDb.db.withTransaction(tx, async (tx) => { if (await this.hasTransaction(transaction.hash(), tx)) { return @@ -219,6 +222,8 @@ export class Account { sequence: null, } + assetBalanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) + await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -232,6 +237,8 @@ export class Account { Assert.isNotUndefined(note) + assetBalanceDeltas.increment(note.note.assetIdentifier(), -note.note.value()) + const spentNote = { ...note, spent: true } await this.walletDb.saveDecryptedNote(this, spentNoteHash, spentNote, tx) } @@ -245,6 +252,7 @@ export class Account { sequence: null, submittedSequence, timestamp: new Date(), + assetBalanceDeltas, }, tx, ) diff --git a/ironfish/src/wallet/walletdb/__fixtures__/transactionValue.test.ts.fixture b/ironfish/src/wallet/walletdb/__fixtures__/transactionValue.test.ts.fixture index 02c8ba28ca..609ada5a84 100644 --- a/ironfish/src/wallet/walletdb/__fixtures__/transactionValue.test.ts.fixture +++ b/ironfish/src/wallet/walletdb/__fixtures__/transactionValue.test.ts.fixture @@ -54,5 +54,41 @@ "type": "Buffer", "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA2PxjMsnJOdxyoXP7wCuVs4iNzl8xybD6BMrsaAryvjSIaGz0mFeMMpo1PQqu6dX6iRUpN4L+JeoottzSwQl5TpYlrJ68SZdOdginmU9yfiiT9jqkvfqgYQwziXfOqcAAZ0tx7DxAeNjGckXNY2tQARi+9Gk/RGoynt9VmtgJn/8EBiwtIKZq1kitRTtf9iBiR8hs31kl5Jamis0Y40lwrZsMCg458bdpJsX8wrZ0tz+Jvzd7fZVMRK+lyvCi8UdvUJUKvqRNIWz/5/B9JnQG9m52j27SJHMdbXewSTB8lz1OmOuZ5cjnbe8Y0znY0nfOz5RpuApXarR89aTL3jsiQr+IeO/82+aZ45bgc1NJG1Wa0Lg9yRA9Zl6mfvUVI5wd+jRtyFCYqfz0KayEG/4kThSe5xUMqvwhMpbSd8q71dFIjnoyiYDkwLoz9R9tiFRHCcAQFdyPhAoaIYWOGP387JWVdGg+7csjERlx73UbSBVAfPhQQ/hxJBTyHfjEcssOluY6QzgeW+ut6sS6/vgYrJzJzRDJJDOyUVCcd2FDN+s0G7afq2AZo7lH5TWpd73Mr2QGLNC5LHeVCAaVJyuiyUYd3r1ewALVVxXvAxk7lA4vsSiUtYK7Zklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJCdU+RdC/U3PnObIPWTeUTdzvnEICH6F5mI5r62pVzKYjndmzwtMsRGPMY93SEnxK6oFPfM9br51dbMRKLR9BQ==" } + ], + "TransactionValueEncoding with empty asset balance deltas serializes the object into a buffer and deserializes to the original object": [ + { + "id": "377a8093-1e89-46f9-8117-2b36adf35aaf", + "name": "test", + "spendingKey": "b8064ef62085768208bab45257ae3c5d89ef757686ff9ded00e73ecbd05b2a8e", + "incomingViewKey": "a8405961b8f232b9ffe086bbe371f91edbe32396b586348cbc370681ab2bf007", + "outgoingViewKey": "2ae7d86a827d67c5f2a932af1d0980645939185d65b8068090dbcc7b8d3b74f6", + "publicAddress": "c3d8f3ca70b1cd44cbb5b43fa61b9fa3bb0f82e274e6532d23f8f9da7eda6937" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAY1bs09B0I+zOyItjRafyZ2gW6Mx9EIxfALwKY5yztcypJuMPE1p0Iw096CGbfLqgRk7mrPWFrK2rIPCIq2C3XhBjaq4w23qYtGaTuGt+O4OxFTpPncj6PAxRziF9VUh2pHy3uQ7Kt/XwFtwaQbLNSW7MKj9cNrrKpnCeX+oz8u4QgLckRLkTbTIHkp+0bGIh2/39QqgYv1HUrS0oF727eubGvmfhdX+PT2jZcXPtHrGQ0LipVKGSViWiMm6A+rESoKv55eJZidhD0UCQsCt34rGRLQCQLI/ZdIgqA6HTKBnyKH7VTQT79iZkXcyzXJwTs2RnkBHt+I492eMrvH5rbk+kBQUu3wKiK8efdQwbNp55LVQkV4Q0k9gUVdeIMJ8a/cv7mytkS37GisvyZacQtwjObvZKi1DNwOaLu2JL1939NboiA2pI9pI+mdq1tHcxRum8yQ0IGm4PM3HNa70QDQjJu5IqMzgbNe7VL5JfjhJKF2J+m7kFrS48XeXzSLIVWDT3oVDSnwKF9O/wlMXPcHzwuPc8fET3B5TFqtFWATw7iOyNTt8F3NChbf565yugzKvAhmghnJD2tygQDxIxaDTJwLYcV7ebhj/vYo6HKM8YTc50khdKrUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwifz/JcvXBq7pt1L5bARfVbwYyjBm3qyKoa4qlox5v9k0Bvc9jFNYJQuJFCwBuM1WnXLP44kdtAjC+VVeb1U1Bg==" + } + ], + "TransactionValueEncoding with multiple assets serializes the object into a buffer and deserializes to the original object": [ + { + "id": "b2dfa553-f14b-439a-8b6b-9b2d2f95b3d3", + "name": "test", + "spendingKey": "0ed7a54f5174692dac8daf8b33593dc5a322be00d3b6484a6f5e0d0c7c4fd7fe", + "incomingViewKey": "daa9f9697507c3bfb8e76447f781cf44b5bcac0fa91d2b4b547efbd7761b4b00", + "outgoingViewKey": "4c77edb7cdae92424ee4ce60033d77346410288fb43e5f669653258aef997309", + "publicAddress": "b2f5f661b39c366c6fc3ab34cecef7398a349da2773e490bac0abe1c490eafe3" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA9yg4HWbPJ2fA8IkCdg0tkOYpda9dJM8PZMHXOTTtGU+r6qyXZQYDMJ3sXprWhl0E579rkEy9YIzrh2mATdu4jaPs0nRRSP5k4crmQsYGKk6o7B1wTS2Ggl0OWRRR/2qiMf8qmM5fmPWAIb7jt4LULEUpu8OJgiG4LO2P8kOEP2cZKowtSHV5D6OcxXLURr6IkxTn2vBfBIEcJsxw0aINlOzlQ5ZpxKO91Sif7FjkAjysgsUUWocVv0cuOln7QekL94xllTdCdl7H69EbFnd6lfS6jwgRHGBwAqiQfQpOeX6ZaCE4BdvALm/T87b1ufdKQI19SP9p9dxZ61hDFzas7yQN5/cS2SbFB8C4LJjG1Q/lFpS09XiN6G/H4Yn+KC0iLd8VMdUWdKoeaHd7+mjGOcY2MYo8zGmU8VwlDT49gbDJqTgP7+gPPBaPg8BvZmyXYvaFqAVNzzCAxvCYAZBM3yoLAIttgDOZMT4jf5zG+xhfUbMVctsNAMxxkaC07h9CWP0WNyXzt2MnzfJXgOwMh3f+1IsrqH6D0HiwP86ICe3DfAOynkqTRweK49j5EU8huxFre3Tpn0E+TAWSqpEGrHC8qh7XKRlBoalBjHNazC0Q6eGkQcbRjElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwS0/71dq7rAPvVvDJ+AX6iR3zXu1J50RYTAXxBQ541h0q3pFey8mnFpPIXcLK9C1tvvqRCLhzbM9Tf0JnCmVLAQ==" + }, + { + "id": "c5fad861-1360-4519-8ff9-516d3e462829", + "name": "accountA", + "spendingKey": "61997cd8c92c3e7d69ef9598e3f27af53e0263c837dce646a75b02e386415ce6", + "incomingViewKey": "63adb6712398f2ea55fa63c8fe89dde2efa9c8536b4b80b3fd7c1733edcfd504", + "outgoingViewKey": "a6c2a21fb2c3258de10d4a64295bb02f41a4095349947e59643a0792c58974eb", + "publicAddress": "3211906ae1b270bb5e14fd24c5c093d0460bd9842543d0409904b2f1f20ec338" + } ] } \ No newline at end of file diff --git a/ironfish/src/wallet/walletdb/transactionValue.test.ts b/ironfish/src/wallet/walletdb/transactionValue.test.ts index 40277bcdd2..2da010800d 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.test.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.test.ts @@ -1,7 +1,9 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { createNodeTest, useMinersTxFixture } from '../../testUtilities' +import { Asset } from '@ironfish/rust-nodejs' +import { BufferMap } from 'buffer-map' +import { createNodeTest, useAccountFixture, useMinersTxFixture } from '../../testUtilities' import { TransactionValue, TransactionValueEncoding } from './transactionValue' describe('TransactionValueEncoding', () => { @@ -19,12 +21,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + const value: TransactionValue = { transaction, timestamp: new Date(), blockHash: null, sequence: null, submittedSequence: null, + assetBalanceDeltas, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -38,12 +44,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + const value: TransactionValue = { transaction, timestamp: new Date(), blockHash: null, sequence: null, submittedSequence: 123, + assetBalanceDeltas, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -57,12 +67,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + const value: TransactionValue = { transaction, timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, submittedSequence: null, + assetBalanceDeltas, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -70,18 +84,73 @@ describe('TransactionValueEncoding', () => { }) }) + describe('with empty asset balance deltas', () => { + it('serializes the object into a buffer and deserializes to the original object', async () => { + const encoder = new TransactionValueEncoding() + + const transaction = await useMinersTxFixture(nodeTest.wallet) + + const value: TransactionValue = { + transaction, + timestamp: new Date(), + blockHash: Buffer.alloc(32, 1), + sequence: 124, + submittedSequence: null, + assetBalanceDeltas: new BufferMap(), + } + const buffer = encoder.serialize(value) + const deserializedValue = encoder.deserialize(buffer) + expectTransactionValueToMatch(deserializedValue, value) + }) + }) + + describe('with multiple assets', () => { + it('serializes the object into a buffer and deserializes to the original object', async () => { + const { wallet } = nodeTest + + const encoder = new TransactionValueEncoding() + + const transaction = await useMinersTxFixture(nodeTest.wallet) + + const assetBalanceDeltas = new BufferMap() + + const accountA = await useAccountFixture(wallet, 'accountA') + const testAsset = new Asset(accountA.spendingKey, 'test-asset', 'test-asset-metadata') + + assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + assetBalanceDeltas.set(testAsset.identifier(), 1n) + + const value: TransactionValue = { + transaction, + timestamp: new Date(), + blockHash: Buffer.alloc(32, 1), + sequence: 124, + submittedSequence: 123, + assetBalanceDeltas, + } + + const buffer = encoder.serialize(value) + const deserializedValue = encoder.deserialize(buffer) + expectTransactionValueToMatch(deserializedValue, value) + }) + }) + describe('with all fields defined', () => { it('serializes the object into a buffer and deserializes to the original object', async () => { const encoder = new TransactionValueEncoding() const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + const value: TransactionValue = { transaction, timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, submittedSequence: 123, + assetBalanceDeltas, } const buffer = encoder.serialize(value) diff --git a/ironfish/src/wallet/walletdb/transactionValue.ts b/ironfish/src/wallet/walletdb/transactionValue.ts index 7edcbdc03c..25b21e07c9 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.ts @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { IDatabaseEncoding } from '../../storage/database/types' +import { ASSET_IDENTIFIER_LENGTH } from '@ironfish/rust-nodejs' +import { BufferMap } from 'buffer-map' import bufio from 'bufio' import { Transaction } from '../../primitives' @@ -15,6 +17,7 @@ export interface TransactionValue { // rebroadcast. This can be null if we created it on another node, or the // transaction was created for us by another person. submittedSequence: number | null + assetBalanceDeltas: BufferMap } export class TransactionValueEncoding implements IDatabaseEncoding { @@ -41,6 +44,14 @@ export class TransactionValueEncoding implements IDatabaseEncoding() + const assetCount = reader.readU32() + + for (let i = 0; i < assetCount; i++) { + const assetIdentifier = reader.readHash() + const balanceDelta = reader.readBigU64() + assetBalanceDeltas.set(assetIdentifier, balanceDelta) + } + + return { + transaction, + blockHash, + submittedSequence, + sequence, + timestamp, + assetBalanceDeltas, + } } getSize(value: TransactionValue): number { @@ -85,6 +112,8 @@ export class TransactionValueEncoding implements IDatabaseEncoding Date: Wed, 4 Jan 2023 16:57:13 -0500 Subject: [PATCH 36/56] Kill aliases in ironfish-cli (#2825) Now no command has any aliases. Review: https://github.com/iron-fish/ironfish/pull/2825 --- ironfish-cli/src/commands/accounts/address.ts | 1 - ironfish-cli/src/commands/accounts/index.ts | 1 - ironfish-cli/src/commands/accounts/status.ts | 1 - ironfish-cli/src/commands/chain/benchmark.ts | 2 -- ironfish-cli/src/commands/chain/readd-block.ts | 2 -- ironfish-cli/src/commands/config/index.ts | 1 - ironfish-cli/src/commands/migrations/index.ts | 1 - ironfish-cli/src/commands/peers/index.ts | 1 - ironfish-cli/src/commands/service/sync-masp-transactions.ts | 1 - 9 files changed, 11 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/address.ts b/ironfish-cli/src/commands/accounts/address.ts index b009546f1f..964148f9e9 100644 --- a/ironfish-cli/src/commands/accounts/address.ts +++ b/ironfish-cli/src/commands/accounts/address.ts @@ -5,7 +5,6 @@ import { IronfishCommand } from '../../command' import { RemoteFlags } from '../../flags' export class AddressCommand extends IronfishCommand { - static aliases = ['accounts:publickey'] static description = `Display your account address The address for an account is the accounts public key, see more here: https://ironfish.network/docs/whitepaper/5_account` diff --git a/ironfish-cli/src/commands/accounts/index.ts b/ironfish-cli/src/commands/accounts/index.ts index fc6a86f2f6..c32c2e1397 100644 --- a/ironfish-cli/src/commands/accounts/index.ts +++ b/ironfish-cli/src/commands/accounts/index.ts @@ -6,7 +6,6 @@ import { IronfishCommand } from '../../command' import { RemoteFlags } from '../../flags' export class ListCommand extends IronfishCommand { - static aliases = ['accounts:list'] static description = `List all the accounts on the node` static flags = { diff --git a/ironfish-cli/src/commands/accounts/status.ts b/ironfish-cli/src/commands/accounts/status.ts index 983fdd5cbd..bad820f963 100644 --- a/ironfish-cli/src/commands/accounts/status.ts +++ b/ironfish-cli/src/commands/accounts/status.ts @@ -6,7 +6,6 @@ import { IronfishCommand } from '../../command' import { RemoteFlags } from '../../flags' export class StatusCommand extends IronfishCommand { - static aliases = ['accounts:status'] static description = `Get status of an account` static flags = { diff --git a/ironfish-cli/src/commands/chain/benchmark.ts b/ironfish-cli/src/commands/chain/benchmark.ts index a6184a2700..6dff38e691 100644 --- a/ironfish-cli/src/commands/chain/benchmark.ts +++ b/ironfish-cli/src/commands/chain/benchmark.ts @@ -11,8 +11,6 @@ import { LocalFlags } from '../../flags' import { IronfishCliPKG } from '../../package' export default class Benchmark extends IronfishCommand { - static aliases = ['chain:benchmark'] - static description = 'Test the performance of the chain by re-importing data from an existing chain' diff --git a/ironfish-cli/src/commands/chain/readd-block.ts b/ironfish-cli/src/commands/chain/readd-block.ts index 6fefc51b64..f70a90392a 100644 --- a/ironfish-cli/src/commands/chain/readd-block.ts +++ b/ironfish-cli/src/commands/chain/readd-block.ts @@ -6,8 +6,6 @@ import { IronfishCommand } from '../../command' import { LocalFlags } from '../../flags' export default class ReAddBlock extends IronfishCommand { - static aliases = ['chain:readdblock'] - static description = 'Remove and readd a block on the chain if it has no other blocks after it' diff --git a/ironfish-cli/src/commands/config/index.ts b/ironfish-cli/src/commands/config/index.ts index 14ca2c3197..6001aa1778 100644 --- a/ironfish-cli/src/commands/config/index.ts +++ b/ironfish-cli/src/commands/config/index.ts @@ -8,7 +8,6 @@ import { ColorFlag, ColorFlagKey } from '../../flags' import { RemoteFlags } from '../../flags' export class ShowCommand extends IronfishCommand { - static aliases = ['config:show'] static description = `Print out the entire config` static flags = { diff --git a/ironfish-cli/src/commands/migrations/index.ts b/ironfish-cli/src/commands/migrations/index.ts index 215edcfbb8..0845878cf4 100644 --- a/ironfish-cli/src/commands/migrations/index.ts +++ b/ironfish-cli/src/commands/migrations/index.ts @@ -5,7 +5,6 @@ import { IronfishCommand } from '../../command' import { ConfigFlag, ConfigFlagKey, DataDirFlag, DataDirFlagKey } from '../../flags' export class StatusCommand extends IronfishCommand { - static aliases = ['migrations:status'] static description = `List all the migration statuses` static flags = { diff --git a/ironfish-cli/src/commands/peers/index.ts b/ironfish-cli/src/commands/peers/index.ts index df63883061..9d19d01f65 100644 --- a/ironfish-cli/src/commands/peers/index.ts +++ b/ironfish-cli/src/commands/peers/index.ts @@ -12,7 +12,6 @@ type GetPeerResponsePeer = GetPeersResponse['peers'][0] const STATE_COLUMN_HEADER = 'STATE' export class ListCommand extends IronfishCommand { - static aliases = ['peers:list'] static description = `List all connected peers` static flags = { diff --git a/ironfish-cli/src/commands/service/sync-masp-transactions.ts b/ironfish-cli/src/commands/service/sync-masp-transactions.ts index 13db644433..efbb2aaaf0 100644 --- a/ironfish-cli/src/commands/service/sync-masp-transactions.ts +++ b/ironfish-cli/src/commands/service/sync-masp-transactions.ts @@ -21,7 +21,6 @@ const MAX_UPLOAD = isNaN(RAW_MAX_UPLOAD) ? 1000 : RAW_MAX_UPLOAD const NEAR_SYNC_THRESHOLD = 5 export default class SyncMaspTransactions extends IronfishCommand { - static aliases = ['service:syncMaspTransactions'] static hidden = true static description = 'Upload MASP transactions to an HTTP API using IronfishApi' From 256bb9c1d9509ba13fe094381bf2f82d66c48801 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Wed, 4 Jan 2023 17:06:12 -0500 Subject: [PATCH 37/56] Move transaction routes into wallet folder (#2829) --- ironfish/src/rpc/routes/index.ts | 1 - ironfish/src/rpc/routes/transactions/index.ts | 5 ----- .../__fixtures__/sendTransaction.test.ts.fixture | 0 ironfish/src/rpc/routes/wallet/index.ts | 2 ++ .../routes/{transactions => wallet}/sendTransaction.test.ts | 0 .../rpc/routes/{transactions => wallet}/sendTransaction.ts | 0 6 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 ironfish/src/rpc/routes/transactions/index.ts rename ironfish/src/rpc/routes/{transactions => wallet}/__fixtures__/sendTransaction.test.ts.fixture (100%) rename ironfish/src/rpc/routes/{transactions => wallet}/sendTransaction.test.ts (100%) rename ironfish/src/rpc/routes/{transactions => wallet}/sendTransaction.ts (100%) diff --git a/ironfish/src/rpc/routes/index.ts b/ironfish/src/rpc/routes/index.ts index c27b3072ae..167802cafb 100644 --- a/ironfish/src/rpc/routes/index.ts +++ b/ironfish/src/rpc/routes/index.ts @@ -11,6 +11,5 @@ export * from './peers' export * from './router' export * from './rpc' export * from './mining' -export * from './transactions' export * from './faucet' export * from './workers' diff --git a/ironfish/src/rpc/routes/transactions/index.ts b/ironfish/src/rpc/routes/transactions/index.ts deleted file mode 100644 index 989a6fac4c..0000000000 --- a/ironfish/src/rpc/routes/transactions/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -export * from './sendTransaction' diff --git a/ironfish/src/rpc/routes/transactions/__fixtures__/sendTransaction.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture similarity index 100% rename from ironfish/src/rpc/routes/transactions/__fixtures__/sendTransaction.test.ts.fixture rename to ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture diff --git a/ironfish/src/rpc/routes/wallet/index.ts b/ironfish/src/rpc/routes/wallet/index.ts index b58b3f3d78..032b9e69ac 100644 --- a/ironfish/src/rpc/routes/wallet/index.ts +++ b/ironfish/src/rpc/routes/wallet/index.ts @@ -12,7 +12,9 @@ export * from './getPublicKey' export * from './getStatus' export * from './getTransaction' export * from './getTransactions' +export * from './sendTransaction' export * from './importAccount' export * from './removeAccount' export * from './rescanAccount' +export * from './sendTransaction' export * from './useAccount' diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts similarity index 100% rename from ironfish/src/rpc/routes/transactions/sendTransaction.test.ts rename to ironfish/src/rpc/routes/wallet/sendTransaction.test.ts diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.ts similarity index 100% rename from ironfish/src/rpc/routes/transactions/sendTransaction.ts rename to ironfish/src/rpc/routes/wallet/sendTransaction.ts From 54ee54e9ee912d1f26fc7399e9e5b47296f9540c Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Wed, 4 Jan 2023 17:19:45 -0500 Subject: [PATCH 38/56] Rename Wallet.pay() -> Wallet.send() (#2830) --- .../src/commands/accounts/{pay.ts => send.ts} | 12 +- .../sendTransaction.test.ts.fixture | 50 +++- .../rpc/routes/wallet/sendTransaction.test.ts | 18 +- .../src/rpc/routes/wallet/sendTransaction.ts | 2 +- ironfish/src/testUtilities/fixtures.ts | 2 +- .../__fixtures__/wallet.test.slow.ts.fixture | 216 +++++++++--------- ironfish/src/wallet/wallet.test.slow.ts | 14 +- ironfish/src/wallet/wallet.ts | 2 +- 8 files changed, 177 insertions(+), 139 deletions(-) rename ironfish-cli/src/commands/accounts/{pay.ts => send.ts} (91%) diff --git a/ironfish-cli/src/commands/accounts/pay.ts b/ironfish-cli/src/commands/accounts/send.ts similarity index 91% rename from ironfish-cli/src/commands/accounts/pay.ts rename to ironfish-cli/src/commands/accounts/send.ts index a8b1b6facf..ec78420bff 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/accounts/send.ts @@ -7,13 +7,13 @@ import { IronfishCommand } from '../../command' import { RemoteFlags } from '../../flags' import { ProgressBar } from '../../types' -export class Pay extends IronfishCommand { +export class Send extends IronfishCommand { static description = `Send coins to another account` static examples = [ - '$ ironfish accounts:pay -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed', - '$ ironfish accounts:pay -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed -f otheraccount', - '$ ironfish accounts:pay -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed -f otheraccount -m my_message_for_the_transaction', + '$ ironfish accounts:send -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed', + '$ ironfish accounts:send -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed -f otheraccount', + '$ ironfish accounts:send -a 2 -o 0.00000001 -t 997c586852d1b12da499bcff53595ba37d04e4909dbdb1a75f3bfd90dd7212217a1c2c0da652d187fc52ed -f otheraccount -m my_message_for_the_transaction', ] static flags = { @@ -55,12 +55,12 @@ export class Pay extends IronfishCommand { }), assetIdentifier: Flags.string({ char: 'i', - description: 'The identifier for the asset to use when paying', + description: 'The identifier for the asset to use when sending', }), } async start(): Promise { - const { flags } = await this.parse(Pay) + const { flags } = await this.parse(Send) let amount = null let fee = null let to = flags.to?.trim() diff --git a/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture index d3d6b55270..9c77fff588 100644 --- a/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture +++ b/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture @@ -39,16 +39,54 @@ ], "Transactions sendTransaction lets you configure the expiration": [ { - "id": "76e7c23f-ca98-442a-8faf-af198d28d0b9", + "id": "99ddf850-539b-45b8-bfb8-8e95d71710b6", "name": "expiration", - "spendingKey": "540175ed6f7bad754823793631a0430c6904cc5eb1dde119dff7f86cd93edf1a", - "incomingViewKey": "29fd678fb3652df9f385093d74f93888808ed9c238c92730d7c3f8a22c155e05", - "outgoingViewKey": "e6c9568e251c34d4f377b9d21c33990004a7792100ad89e20ecd832223938ac2", - "publicAddress": "ab16fa4e8f06d080eabc7419198eca3deab31c635f117ddc4d481d3a61e290d9" + "spendingKey": "f138147e8727c2ecdf8f4dc56c146cfeb7405fe42de698bc8ec2d21e55e82cfe", + "incomingViewKey": "4915d934ca2f08055110d701b2facb0d1125a4ac8744c509c455b84fe547e105", + "outgoingViewKey": "f8f157f95e68400aec1bac0b6c928612f9c9f8d63e922f0d09da655721059f7a", + "publicAddress": "c52dcc2b3ab2d020c92ddfb158fe517f132a8554271625b462b9a08856567dc8" }, { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAZNSIDX+0CxJ2wToT1u1xyEcPkCtZbWM2Qbx/11tDEUiD1bRlo1hFr/J3KTiVI3ld/6+eG8aTCOHlYiZ7LEgadKwurq5XcRCDBF7XMdZ2/pKDEYpXzYceiR+ZUEbIh07mcF9xm3Kb+7jtMfZ4jzWvyGVsvyjJ3H8pygqdXQd6rjQXwMWWxJ5dXm5e/M0OeWqzqb4bgHOBM9zPdNfFWaxA2DH42e6fZG+75ib/OE+/xAqlZj9oeuqsGbw1mmFbAENIPBKklYyDlo7plMyVeaU4EEshPgSs99SAZzzcMl7he0QD0EzffjrsGXwB9AIfOmJGhlXcHOkKlt3d3qbpOBt67lYTR4U5NqxhQgH7HSBhToc79xevGvrAvCK40Vh8IFlXgGGVAJYr32Aw+p1Nbet7zhucFG+YGG0M8qjTvgDmEcZEAzXAt3JkCjMIivDOi9oHkD4AeJZgr2KfANs3qLSNdCVBuHnIqawbPqjx7RE9s04TOG6Q71URy0pEegQk2ORnbXbo8AqPUhgq05tM6BMn2y5EsKGtPtkj3VXOf7F+rrwIfu8kiIsihsmrXFtf6dBINqmlbrfwsD5qLtX5/LFNXkl6e5PZgwF9zLI7cpD94Sm0mOBhLE66aklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2VW03n8VfIrXzwVRt3II6yL1EJoNhKliSF+ugkw8q54fPcmnOgLbeyMkQWflN8sYJFp3AIpTJRs1uruJAO6RBw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAyvfGhZt2ebKIO+loE/80dnntF9awCX3AeEhYzuXs77iIZZfGiQ51qkPSsdm9slIUsoII+96+pKvSgYabhhGS55ReOUnhsa17CS9W3c3+VjSBGX/8nx5khzq+033cIY3X4r2lANcv/6mfs4djgB7ICoDVDcwsKF3uKOuH1wqabTsDjhszH+f+HppjZ4i46tLzXYQezTo49lYUAjKLWjZ5UuJ2rfUdjN0MT3TdjI1XCTeSgqK1s/8J3yoHAQaX/GIzeiyU/ZSLzHnvW8bRU9iuwNROm0KMw+UJCtmXmXHBbi7pWCVbm7PGG4obcyErNTCCqL47dtd0DzkHe2v/0zOGWD8Uh/PY8zo9N0u3LRag6i8PseZGB68zzwzbLw2QAShVd/OwKHyiHSMT/gZTAoKgKWFkUfKs/BXX897mQe6Yus4QyxYVsSr6qlfnG87d44lTl619Dy8tHjPqt5Th0deM3MLoV0l/Y56vtDWXmrDqNuvaBqPC4fg+P79uMjsXjPZ0QtzgUe/HffIz15X4bamSruR3Rjx0NZ8QmJ3Rxah4PF/OyvI69cxAKWY4ej+hm+0cZdO8O5yifghGnw8bshPGTVPYL5A1yNNLO19tWTrKhxqXD7IMYu5ez0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwSKyqioJRbPDzC0V0ezBfsUwooeVS7J+6m+3xol0a2FAKHFwpqvukFrE9zMGUrYEjckoIY/MNbddNfORHP9hjAA==" + } + ], + "Transactions sendTransaction throws if send throws NotEnoughFundsError": [ + { + "id": "7769193e-79fd-4d3a-8d23-15fe8548f7c9", + "name": "account-throw-error", + "spendingKey": "a6a611374d5f544407ac6b125bad006793c530cfd7dcc6a2455d04e3d1fa579e", + "incomingViewKey": "3233e070d22c1d80253e464c66f60053834ad157634354a3282dc95ced92b004", + "outgoingViewKey": "684c81b731c2821a31397dbe9dba0a978086838e5e6bbfb26870694e18630ad5", + "publicAddress": "64189baa593ca54d702e89dd6bdaa931d4f4f18fc0fd4f8697d522c214014cec" + } + ], + "Transactions sendTransaction calls the send method on the node with single recipient": [ + { + "id": "01b77c24-8756-40ee-8585-9c76535662d4", + "name": "account", + "spendingKey": "14a25fcfa6a26aad264679c7cfa8a8fd06a80f92eba56a1b213e3d95d618ea6a", + "incomingViewKey": "3fb5cb935fbb48d97b45af3864532c20ce3d13c7312aa70727f8fd09c1954f06", + "outgoingViewKey": "f08fa65e6737a587aacdc0d91483ec949f0fc8a63837d3d6f078686cf5d84262", + "publicAddress": "37845d966536c4b2f9035389ff1e9d2c7ae05c6edd3877115f06b6fc98726adf" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAAcPYhuVB6orFDGQARnBFQRcOdwkjd/ncLycDY9T8LdSLV/aoq9iEfedQwXKYhZJvpEOQllWnYLu84CHkBlx57etVZejNrGgKcGpXlK6iJZ+WF3eDULHoQoZEYhdL78shJx8AztJgQF/7zMuL+MyJNa+DjvbPRqJTBJ5OGK60THUF4sl4MplANjGx3iCPifoGN689nzYmzrYr2KZ4KokME+sxu0HJ82ZxjoUQw7kV7lmv+akX1DzmOPo3Jt+IWTKZOK3ARjxl2sx490IRrNLYsPVqq2lnAazdURLQ6Y8jiMQSesCrUZGMa8tiCQbDZymca8R7/3m8tTtVuHowOemJKkDyn9XqxcG0DVtqEuUasfsL+P3gAhNiYEUfMbxnB1FKyueN0poWUgQz9OW2rwIHTFvOSFREa78YwFPV+yGczQLKQe2TndeojExJclLCQJBZNJilQnAFTCe52avcwO20A/t/EtzkxHJYRWC1myoLovFfDOpV3hEj1ajafC+dcA6onmp76tLM6ZTAUBDx+84lA4Od8gbvUEjSLEpGqPU5rGOtr6KN7sI1dfyXoiOrVy/PAOQobO1aczcreKZ4CZ7Oz7w9+Sm9FPjvBCN9t/ZexoQiXIumVdeOwUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAws6xxlFNTLDWtNgAZAcQB9x2fTjwUpq9bh/UMIH5Q6wWJ7t7JRfxu9iaJ0oXp84fn/VrAlkvbwEGZv6Wj/X9xDQ==" + } + ], + "Transactions sendTransaction calls the send method on the node with multiple recipient": [ + { + "id": "5033e474-6d46-4292-a807-97bfaf66347e", + "name": "account_multi-output", + "spendingKey": "76e7362107576b9686138b8f6742a71e464228b7f0f944c7a96cbc5555f5c3db", + "incomingViewKey": "b3957f6a09ef64c50c76933742eddfc0eb18fff4d8403a366024926d9144b203", + "outgoingViewKey": "c58551eea2017ae623ab906a9790d0dd89a5e347eb1a51838e66815e60673c05", + "publicAddress": "0a5dc0e872464c1717cbc279b2ff058b794ef556c2396c86e5e0c25f1085c56f" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAHKEb/AaMFIUJBdxw3/Z1CK/QPU8Nm/AAlUkIKLM9jjekgSFCfZ1ge8FjEsy5a3MnTwqrRJfzhP+u1nrZL/ohgBy8L4lFuk6pIsJxs8udkLiHhQhDGUfQwwLVLsgkSTnpR5SUl9JjBi4mxQd22b4iD6wz8KnSCDDBLwp6KfO8v34BKJGP6b7Jp4RIcTeRxLFqxHVFSQZHVLq0LNcXPIjXSA+z88TcS6Q8pMNbgWJK7saj+dYxxd1kKHk74kF0a9asMJCfcDo/CnEBq5jSXGMEbQ6EicLRQ9gQR6Lyr65EXlyugWjAtx5GqKwHZslR8r1xt4NNLiGCMTkAfbEGuA0GrwFj5OkDbCQ+gndub/A4z0Frzeb5I1H6ovEIgZzLBW5cWL1CHU0wpqXmA8O7rMeNhA4X3fi+qg4eZEmP6KYZ6O58IZ8Wv6/Mnb2+uWvsC9pyo1HeIiWvihSumf/0hZkdvB/oaUVqSRsoyilskoNGLaI+IZug2X3GwDV1hXf75wLHyoVmtbgVc2UMwp/uvzjcoVymb+vums7EJdmouEX7VYXUEqDC3gx1St6Nwndfh3+ltj5BYFUzCPChWSP2yoJkPXQlSw5EWtsSvcB5mSLxM8Kk2g3K9yj2m0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwh6/ogcpYD+uyw8aZXTp69ZtKxJFWBZF0i8gtz0vxrGKe6fGJR/26YWds4HGrGlfjqvCIrJHwX9kXG7Vq5gIZDQ==" } ] } \ No newline at end of file diff --git a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts index bd44fee166..ef86eb314c 100644 --- a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts @@ -135,14 +135,14 @@ describe('Transactions sendTransaction', () => { ) }) - it('throws if pay throws NotEnoughFundsError', async () => { + it('throws if send throws NotEnoughFundsError', async () => { routeTest.node.peerNetwork['_isReady'] = true routeTest.chain.synced = true await useAccountFixture(routeTest.node.wallet, 'account-throw-error') jest - .spyOn(routeTest.node.wallet, 'pay') + .spyOn(routeTest.node.wallet, 'send') .mockRejectedValue( new NotEnoughFundsError(Asset.nativeIdentifier(), BigInt(0), BigInt(1)), ) @@ -161,14 +161,14 @@ describe('Transactions sendTransaction', () => { ) }) - it('calls the pay method on the node with single recipient', async () => { + it('calls the send method on the node with single recipient', async () => { routeTest.node.peerNetwork['_isReady'] = true routeTest.chain.synced = true const account = await useAccountFixture(routeTest.node.wallet, 'account') const tx = await useMinersTxFixture(routeTest.node.wallet, account) - jest.spyOn(routeTest.node.wallet, 'pay').mockResolvedValue(tx) + jest.spyOn(routeTest.node.wallet, 'send').mockResolvedValue(tx) jest.spyOn(routeTest.node.wallet, 'getBalance').mockResolvedValueOnce({ unconfirmed: BigInt(11), confirmed: BigInt(11), @@ -179,14 +179,14 @@ describe('Transactions sendTransaction', () => { expect(result.content.hash).toEqual(tx.hash().toString('hex')) }) - it('calls the pay method on the node with multiple recipient', async () => { + it('calls the send method on the node with multiple recipient', async () => { routeTest.node.peerNetwork['_isReady'] = true routeTest.chain.synced = true const account = await useAccountFixture(routeTest.node.wallet, 'account_multi-output') const tx = await useMinersTxFixture(routeTest.node.wallet, account) - jest.spyOn(routeTest.node.wallet, 'pay').mockResolvedValue(tx) + jest.spyOn(routeTest.node.wallet, 'send').mockResolvedValue(tx) jest.spyOn(routeTest.node.wallet, 'getBalance').mockResolvedValueOnce({ unconfirmed: BigInt(21), confirmed: BigInt(21), @@ -210,11 +210,11 @@ describe('Transactions sendTransaction', () => { unconfirmedCount: 0, }) - const paySpy = jest.spyOn(routeTest.node.wallet, 'pay').mockResolvedValue(tx) + const sendSpy = jest.spyOn(routeTest.node.wallet, 'send').mockResolvedValue(tx) await routeTest.client.sendTransaction(TEST_PARAMS) - expect(paySpy).toHaveBeenCalledWith( + expect(sendSpy).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.anything(), @@ -229,7 +229,7 @@ describe('Transactions sendTransaction', () => { expirationDelta: 12345, }) - expect(paySpy).toHaveBeenCalledWith( + expect(sendSpy).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.anything(), diff --git a/ironfish/src/rpc/routes/wallet/sendTransaction.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.ts index 26591a6346..4c4a28ff76 100644 --- a/ironfish/src/rpc/routes/wallet/sendTransaction.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.ts @@ -142,7 +142,7 @@ router.register( } try { - const transactionPosted = await node.wallet.pay( + const transactionPosted = await node.wallet.send( node.memPool, account, receives, diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures.ts index d4f83263d7..6d2afb2afb 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures.ts @@ -151,7 +151,7 @@ export async function useAccountFixture( * that get added onto a block don't get handled in the same * way as if we created them, which is a problem. that's why * the transaction fixture uses accounts.createTransaction() - * and not accountst.pay(), so if its generated, and if its + * and not accountst.send(), so if its generated, and if its * cached, both have the same flow where we manually sync * them afterwards. */ diff --git a/ironfish/src/wallet/__fixtures__/wallet.test.slow.ts.fixture b/ironfish/src/wallet/__fixtures__/wallet.test.slow.ts.fixture index ff7d9ce6dc..b6f89dcd0b 100644 --- a/ironfish/src/wallet/__fixtures__/wallet.test.slow.ts.fixture +++ b/ironfish/src/wallet/__fixtures__/wallet.test.slow.ts.fixture @@ -1,28 +1,28 @@ { "Accounts Counts notes correctly when a block has transactions not used by any account": [ { - "id": "4085f91f-be93-4d3f-a0fa-7ec652009663", + "id": "d95bb582-1585-400d-81aa-ae71bc8225c4", "name": "testA", - "spendingKey": "7d0414fb1814b2d567948aff629bfe724b18a0f6086af8decd281da739b17313", - "incomingViewKey": "9cbd96d348159dbbfa1e63697ddfe8ac9b873e5b669bec7f06d7c492c5152805", - "outgoingViewKey": "bcb3c0d50eca3ff51636d17b1ee1e93a9dde5dd544130cb1838a95ff5b246580", - "publicAddress": "ebce0dffca4c3ccb2074250a21b02021a71be47b05efdbb12d32a9bc02c9840e" + "spendingKey": "21dfa82be10f20ca60433fbca49431ad051b1133a2e6a50a05d4bd0a0b317c3b", + "incomingViewKey": "23b6d448571cf4b361aea082e7d2c445a091c4e81c10a223e8944f2229b39503", + "outgoingViewKey": "2e7e16295fa8fff978f1691730af4a1639269a9ae424648e237bfc0e485664e4", + "publicAddress": "a1b9be72c2d4968ad96757a0f792bff0641568d3b60b69a33483e475bec22b25" }, { - "id": "b9204ba9-b669-4316-9357-0fc0092bb6a9", + "id": "0e85972f-a8e7-4cfe-9e99-970ea9c5589c", "name": "testB", - "spendingKey": "b85664e1f429bf7f4401cfbd2c54da7de799d1ba679fa911d86d766c56d8d581", - "incomingViewKey": "97b69025b40141f5407a2410c3c3d6d866a66c3e8070bbc8d30de30aef51cb03", - "outgoingViewKey": "49b97175b95b3672c6c3389f570c940b9f6e73534d20800b6c1e60e9da8c5bc2", - "publicAddress": "58db1b1b44e8a6deb72ef2fc34278c4594e4cd71d9fa0a0f2f6be6662c50e984" + "spendingKey": "6112cc37b1b9e0a75891943f36eabf3e857b19fd1e69374b0c60b8d64c82779f", + "incomingViewKey": "965029ec52ba25d9dc5485609131b0d2425b0939e35f5f9fbf0461f30457ae06", + "outgoingViewKey": "94f2e4152827ec69949e3b7f97556f1e073dc0ab9a6300000f065e7cfa6a5423", + "publicAddress": "f1f498c16260df0830e74d481663a03efcbeea14e63e445298cf3d95067ec92c" }, { - "id": "2fb0793f-3a69-4f2a-a7e6-c47c7166b134", + "id": "2ba2f4cf-5eaf-4082-bfed-dd9de3085306", "name": "testC", - "spendingKey": "4b67905e78b5b363ee51ee9196db29d49dab4f1f22a8d640d52dd4c0034281a1", - "incomingViewKey": "fdbe0059d303bd0053d6e108ddf5c84c1981c16bbf7f8ba483b4fb8812703303", - "outgoingViewKey": "87c1d98bf7af1219d4efc93d6b418468ea90cae3e61c902322be4cf56ac11f7c", - "publicAddress": "eb03e2e23511231931948ff147dda8e32cd821e8358e3f85eccd4dea516989e5" + "spendingKey": "4b636c618036128e247528c1e448e4d55b4e5b818ec0670c55d1d1c0f013c043", + "incomingViewKey": "2bd923e7ddcdd198da8047c1a62bfb9edbd2750c0e5c6361549773db1eb75d05", + "outgoingViewKey": "787eef767cb412e10ae6e8fca5952ff7b61a4747123b9fce5b5210eefcbd4177", + "publicAddress": "4056a274ca24e2df26df7b5f1351f10e4699b7e7a4884e8def6ba2d2b76ce30d" }, { "header": { @@ -30,15 +30,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:4KGNvrGEnnRlIlTuECxI/33Hc2JbvSteqorPYkOvCVg=" + "data": "base64:NPCTlVCEPQYoZe+iLdioLlSm5f5IdKXvjEe61c84alA=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:gmoftP6ZP8VFAWL9lbQlkeKaUHrRamFQIEtcGhum2bk=" + "data": "base64:1WLx+Ddrtdbo8xkyFaolqJEuQTtZS6YG/sWDhdbWQGw=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221831723, + "timestamp": 1672870266526, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -46,25 +46,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAH2HOrcWdmO16BhpP4vAXIUWtlflWwE4l4BADqdvHtguSxEi4ZhHEo4B4GoyZda88Tl/E2OSt1KgrwbzKVE7GUjITd3d6rTIyBH2bmMBPEtyD/VlJ1XpvUZiMkYA+Tsidag0UKWX9uyEpgCamLYGL72HLa/wFFyCRYcUvsMvNOlMKXO/yDoZeDbDTTws/qRkJIkdiDW2R+iFU8XI6cbjr9p9drJM3EufRgpONiRoj25qiZyJHnWy0qaHqkK6LRqngXbMS4rvkoBoCCZHuQ4ZRkjDLUurwblsbJmxwV2gMcH2GGkZn/b7zCMsZPclGHgPzze6DervycIvtaZhghToVCkYX2QxD9Q7Q648LBzZHdUPgohfVV3DK3GAFO/WpLNVJAPr/Xpqt91KTo3WrCNm2q1FEAIh8mf7ETnNEn6SocjEVoMEwEyHam0scoDCQfx2HF7Hqs23uhxrvwgAVXxcjeblhFltu9l8d/Y0UU5nZdUj5+gY1f9VdToj+FpnJGvP6jA2ppjhV/W1tYEsHUvPVyfDYaB1IO56sCjllfthCVnkToZA1hK/LATICTO171nNtk1PLidX34eMPQz0NmXltE73sYuSywI7sH2bNukS5tH6dYfh8gd2w7Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw0Q4hIE2eSibYRAxiICWqCPxJqU4aK44aNHIxpxUWaR2cbvaWP5MzqAH5EbV/n61F+2DEATwZmXh7RdwtGn/ZCw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAa/K+RB3HCwZwag/3A5vYO720eIxD76f3Mrn0E1S4kqSGyzT12IL97Ru4zF9sExtjdffG+S3zHhk11Xvw8VkjY+ayb8i1FGmnEPhV6pCih9OyZrmnHc3ZdNp+/lel9znHBBvAf3qdtVbISwk98hTnPkXkCkWE2i61qseHP4h59dMPGimwPLLIZw0cjjuZNCluI4pRZna4Myluj/54Z0wI4z+m611xAFtAqX3tDrAvMCOzL7vtWKVRqwxWp1e7UdmLAwAHYegGF2W/+MRAJZUDVwnvdq99OpS+h5/2gdI+Y3DBxgC32Rv+fMjK0gl/rXtqhqchy6SYc1UOQ5/sG5awR3FKfT1MoBNjLRDYlQ5zXBWfgJGkaSKNPgIe97ynuQ8sukqaiFIoO8UxGZlO9sdc5CXnKqpLIslUztEzTbV6TooPm8VvvuZ3nKNTOv7iSWH5U8UJRrNG2XTgKH2IapduYRnde5sd7lyJS5mmH6Kr1FxLkydXKeF0CG7CcIFXjcoYBheqxsUY5owNjy5VxRGUaCmEFGtS/D/K/twEa1ef23Yv3q3JNsaSN6iPBsSQEqmuM3/aYH3+/KyZhrowQD0Ah8Cc4ZwGLfXAQzFC4PvpU+1JJ02N4uX0bklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYQ+9tdWDGuKyC4zy2XFj+VOUiI5hNm1U7ZQSsktTIMPAs8ex6G3MufXI+OxUriHcxs5l0FVrXn/owblYcWhDAg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "670296CB69C2CE29FE14BD18B49C3F6653BD4BE378A3E879417A3D8DE9515F2B", + "previousBlockHash": "42E737F803673653A01E6FFC8FEF39727AD3C9DA115DBFFB36B898957E3DD6AF", "noteCommitment": { "type": "Buffer", - "data": "base64:x/HulJakZ5f5KHx6zyIqDmiEN7PWRlkiw1PjWn3XpDs=" + "data": "base64:yI8U+q4B5PM0JYjAuWjgW5RmH7U7DEn27DwJjS3z2GY=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:mJzxuirUpFd1ycloAY19de2kR4gWjJ9+mZt4GOiz7a4=" + "data": "base64:keTdyqihPKZTiZaliAmPd8B4Vol+/DXCWP5ILv1HHUw=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221833408, + "timestamp": 1672870268708, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -72,31 +72,31 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAAxvzTQBNs67Upw36S12R/LTrfdXibu16AqWG0N95JAx2AoS7gIDroB8aCNjTnDpegVY6azSM8GcY+qPXSPgXeY8egxZryMNmtGjeVhiHQu36UF8ka/Ua+VC67RR52729YSVmI78z1nyJElmZTfzRlHT3K7Z98c+hdhzRxMOp+j/4YBp2X3PXh9Csqsx1me/0k88Miltr+gubzB/IjrRcfnnBUkMssRA9fsE6f7evNfASD/+8o2biYSs4ihdW0olalvwFaeas2KF0l/w3PELjsnRD4cGkVBDODSNp2Sd7cMwCtjiCL+w5/tq76N0b+Wo/JmPx1tZ7fG35POh9iqzSpGnA+5qEGyiMG4RY5MGf3NtTLsOQAJk7bM5LY7XNcIvQ4yt2hNqywCn5J1OP0xpryX4hUXBk8eC88G+FYxHKpgMJL2I5PRv3yGJyjjqZ3V0HRGxuP+ewy0uCYVu9RUdJIGY1gf0amSYUmfFEekMF9ehZyzki6T6Llvm/fdEblQ+xYf1Zr9kVutc7bcrxx3ssGMViceoGFrfCNOkLxvU1PVGjqD39wiROxJnnW7u88l4MXZTFR7zO80OMc9mWC3z1st+Q0bVTIXwX5tvtmGhp/1ckSkzVkULuNNUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwFNl0vyWyCs0a5sYRdcTdfR0NTGc57XtMNu+v0fA9ZJOyezMknhTWoy2KbAbAFXVIylAHSt0vyccm7y24q4c0Bw==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2vKiP////8AAAAArNsY5tGNVXev7AHFF2evRkFQvYr5yLq7odtcypUmZiaF/sCV1KJIM/4DUlAuUZOLDqk/WvCAUv8Gh/x8K9z6WlAcjQ3bH8BkBT2OsUN98zG5bNAtj7lmaet1bX6xkUPOnuzgB4nAiTCPmodv2mhuCv0TgLTHA0QYCQjBGZu5Iz0CMZmuDaW/Uj+ixze7T2jVAnkEw2KjgXW5pEMAP5/TfD7EVaJgSoFl73DtmlkDUrmC26R/aR09GW+LZzwQDKt9EtQ7ePfeeL5gwkZ8sQL2IURqfjEBWs04Fryyg8w+WMqEjzeQq02K0kkVIeD+5UFVZCRsbpYS7NtoqEh7snp4kaImmAO566L4fP2qVUG7bM1n3Bw6ztUDNwa4gzTQc9pGocd+25c/z8/Cgad7NSP1nPtCs4kEck3f+57vs/AijdK8HlQUPSMyHC8rKFkFYi8tpzRbJnqSvAV4vFTtSguePcyi1/kVWnaLU4Vfe1U4WvU9QfdaHa5sWKXDn3pWFwyza3pybiGO5NndaixZFlYXuCuVVgN2Aun/rFu3lR8g+NpYd4ynRhm7ipHGV44prcIVf5D5f3T5YrapYBUQRA5tUSlpec1XP36GaIYJUnfLI606c+CRnNlYVElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwKc8H+PMZZgZm+ucGx/0aDpqEvAfJlpfZHHOd42UffVicg0p2PrSyP1lh/2qFGYDdP4nitoOXK9IyRvwcd58pCQ==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAny1gztvBC7+OCDjSyfjjU99vaNlIhRMf+wBDd27Ax8i0lNDyTZ2potZmkDHVn1/5A6GAC2yQzbrE8yHFLklcJ2gt/BWg/tP/YgTYk5Rlo9eviYwPmwMfmervKCBD6sGtzPllan8YS9Z0EJ2k0OHAmpR5XTEGM1HRiUrkeuU261sDBWwMG4lylJ+P9JL7r3FrAm7W+Uieqwcez2zPLougi2Yv2MlyW6hpdADMy5fD6tSDvtkPMyiKNXWEmyC/l/vBqz9oCLSPYCCsmEFkqx9YtiRZx5bwRolezf7IGhzkzPVtdRqp1k/5fkSN/ofEAAWn2t1YtOCrOzlWF4UiRasHOzTwk5VQhD0GKGXvoi3YqC5UpuX+SHSl74xHutXPOGpQBAAAAH4CsGRNUitdmVsPhftWfdmBt3h/poMcMC+OZI25suovnK0vl2j/e05YtTkpZeEO+4jEIsZFbNzwBDNIu6+1/cQABEDhf47emkKZNutPDRrh+0AvOLBUICCw4QMdqAbdAKmzP9SxPGrzqRbgrjgxg3ocgiDP2HCThQHM2xSUp9uop64YS5r3thkv8O1Ek9R0VoHPQ6HCj0mexqHhVtlmoBSdNC/L00fLTpo76Ac+0vr3CKXpfu85BK+uxUm9ywoSfhP+CcHY5WisBEs41Hj+fB407+kZBkhCBQHtmOmKyoen42uRtD8fxB6RKRGt24nefafXgE732u3ce0Sj1ADPKLk63eEx/4YEa/5KrWaVAbPu50K+SZBNYlFfPKukn8FvyBb6+rotu2X0WCgU94fJ/LRoZdgNPd8POBKZa5Jr5rBCY+hhlVmTblTJDtaOzdkpzrFvsFpdk1wYXRHQLrvocA1nlZSojwikjk/Ub+M8e550r5kqzuUpjMcsLSGFckL50TUbeTpMrpubhyvaJvJll/iZQJLz/U6GGzX6wRSslxJlD/1yta7xYz1bCKDA63MGfIa74h0rszK0SvneY8u6Ku/J+r/ZeN2w++Pi7fNOAfpC2wktUIRnNspcwZlfsJMSUN745bDEfH54VZAh+n8VtLUC5DGtiE2FuHGSJ+MPHeznNbDPQsnjjGtBs+cOJpZO64WQshrCTraznqfg+mjTugon/57j1RAdd0YVevY5H4mbxxy6wbWRExB7j1PvwZdMTPv7miaafXj3egmoLlXXvP9kIhBVxneiTZPeSbatQ64vxboxfnxFsfqo2Zk6LuXzGV99czspmhLDno6DBoMkN7NBNDa75IxzAFLYwTWaCTWdFdNAlRLkCMuHfwgbH3zWMjhV3MHkSu3OnFHNW8b7vuNfM45k78jdFgspSbeKmZ/0dRylIpsRYrUQQNtyyLSBA0XYFm7nkEKD4TQZrRsuJeIZUnzWyIPJudxd1dyNhXaG40LbjSDYqMGhvArISoNfh2wKjAXcEapiMFj5uv+pLvpRi3SU9kWC1ct9ssYHih0oCcE2hvsXxA8Av5WsAJxHb2SXu+EJK1u4wh4pBCN5WpwlOxVuWKVCbHT7CZjVq1n4Wc9wFwlFixbLzNuV5aNvlyafMB/V7uBzy0d9Sq2p4tn/m94Bi4Q9ZxJ4TzpvOGxaX+4XIiptOlg9vsgaR9xmz1lGNmY3IEGHS++ml1Izde47ZCIV1edZJDlNI4K+9AwoqLzZBpxJP0Yrtm20NaJPILUnllvzhDhrZgpvw0ZNRnIIDOmLhrUBXPS5lg1b2349AKPksVWRGvbj1S05ILeLo11x5x9+uBD1OHwyuayT+Q+1XXvhv5XSxJaUpLr+GihliKKgSupkofC9PQUTl5kXZNzn+4cgO1nuECjRcCKLvHWd50MZC9pmRXE+vAINfknlRuQL7LpPJrfpsRCGZuHCmoByxQR0bdjJJ7ZVYuRJC4BultKDOv9Zhyjx/5BYCjCvT2Or3oEpf0f2sH4R/8RbRRfGcS0/IW/gf8VEdyoGYb0ZK5xhn0Z2cGp0eAPr6mIl88T2JCHbEeNYwgDYJcC7AQ==" } ] } ], "Accounts Removes notes when rolling back a fork": [ { - "id": "adf7031d-4eec-4434-800e-06168ecc2bc4", + "id": "96012c36-bc28-463c-ac77-5357793b53c5", "name": "testA", - "spendingKey": "afff46a5a5ea2b50f356d60443dca9c68e51c9776adaffad9e7a17b6b9b813c2", - "incomingViewKey": "14c98d58d8695d2105a522b7a4bfbd4ac75afb516631422c8adc70e065122a02", - "outgoingViewKey": "c0ed27ea35772a1f14a69bfca8a905bfebf388ac85ca21d38a728b7258d3aabf", - "publicAddress": "0e764f7be8bfb481eda4e229d34b6c41b1868b442a2db3ee358e5e773a70cecc" + "spendingKey": "51d6507d218079901a774dfa33cf86336b7e89e64ae3d98d67e82b46b8c4343e", + "incomingViewKey": "9556caaf77e5f2bb14a036be9c2b438a546f0eb6dddaf1b50386d2c78a387207", + "outgoingViewKey": "d79975286a32c3030904e4baff4361621dd7d5936a91f2f75f49e223fae7531b", + "publicAddress": "08b0e3ef8fb39b353a46bb77a30f6a011963098cc0435e90e9e436428fb47ce8" }, { - "id": "ef49ea16-f1a4-4842-a836-7f92d2c55f05", + "id": "9073ac74-6bab-44b1-85ba-2bbc2017a830", "name": "testB", - "spendingKey": "3dcdcda027cc62d535ac537a57b87a17a30851e99a2c91a5d6a01b04e91541bb", - "incomingViewKey": "f2eb29a3fa4d01931701e9175d5bb10f83e3953d312809e0fee280c5b0e59a02", - "outgoingViewKey": "9b9dcdf1d1be89df842e45d6d0667d265acd9812841c17b2f5093844c95f0520", - "publicAddress": "d071b8be1898663acc97c41398951f2ff91a4b01c3ab60da1bfeeedf4391890a" + "spendingKey": "3f3bc18d1689980d2fcd865818a2ba91a489f7d45472450fcb9f793c53873977", + "incomingViewKey": "eb59e588420fb3d2d4ac80b90d21c868e069ad2c8c69645f12f2715fe669b306", + "outgoingViewKey": "39c69b5369fdb0d4f2243686a3b7bf65348b0a5429fc26552a964480b39604cd", + "publicAddress": "d2da43dcb9e3a7ef4575322b164e69a2e06cf79b831b62a3e4b58587437e7230" }, { "header": { @@ -104,15 +104,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:76bvjSDTKM9ZLaABDpCgGgCH2xoBM+R4QpAS2H3HVWw=" + "data": "base64:Caa2QfNjwBOGdiIA0hPwssO1LshB0ByAw0GC2UjRYjQ=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:Bib6yTJgqzRY92jTj3Bn5OTlqAhZjwe6rHDmi/F6hQM=" + "data": "base64:meS1drYxdU4iNSrNB2vPB76OPPOqM/nfZC5fLEkMdYE=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221835172, + "timestamp": 1672870269189, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -120,7 +120,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA8ZFenY7Guts7IGutQ2v73+X//JG1SurSrMIvlDh1LKaIqUCT23JW+nNKQWvo3RB9qmWtpYGfI3k9Us2+hcfiuSDhbg5s2hLS03i/kHGou/alxpMStLcjYo/HIopCm7tXxxfuSR84LbmVMrTlOQEbXKQMgLXoFehGg1QmBG3hZfUTBjAGn3F7K3MhRsyTn90Oa9gUJOQ7T9SMaVYlef0FVLsOU+z3zdKO16hm0VCxiKeQACudKIcGlOSZfG9dbqgPSv8aFcHBs5AED6K+nPfXS2KWbF9ihRXHKHHWR6cfTKvpl9GdRis4ogNz+aWdeHjsdvymPy8b+vwyCKlgS5F5Twc+hmSp4YKF1Pfq21zbdoteD5eOHWT2G7TorFM5+zURPZTQxMTZKG/XTAS8L5qm7oKUJdt2/V2XQh+23aEZeG6EMSjc2Jvh4ou2nWOI/fdwG1e6Gmfn1PBh4p8B8Eait8wJmNkFWy7+uVZTg/MHkOpzF7uCQRpUK3V7wrfEEPB7XzG+vXe6dPfgGf4vgItaRvX6E8yNyGfP+0JBDRyrQ710wlYvbeKLoxgjI4u/EtbOmKYA995c94SghluDzA/c4+n+94ymGzI5/6iGoboo7kyEwZW6sNYDbUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2QYxIRXMhaiAVQgxiU0leU5g+gcj06mMSv1zcZJdEF9MM6bNhp+IsCdOiixnlKdmqtvI0q8tbHDpPLr/DhLACQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAQ1Nen5eZuteq6nc9twRgi4agyAhaC3lbiRnTrKJcz7azsRAVyeR6Jm4utUfvIVRl+K1dFkerqNmSH33bd/YSxo1PKgjl4gNuL0mxFqUfgfaKDkuaE2o50KB8vVUHD5LHXJhah0+g3ncw2dCr3P44tkz+Zbf+HkLr59JSdJ3WYy8Nou3iV2QTKRoUP+Jzkbub9/EDHCPnpXLcZAAbmLO0KNMNbo/tCFdafm3LhpTdDdi4JftwYnsVsrgUp3nw21vjOAL242Ery8hd6r/rJ6SRZmfw1YPoAsZrlB5R0wjJwKnejMOMRHXSJov3NfV3zQ+RTQc0DDx5m+QL/8dDQxYFD7tuWMQxz224SXFYGFTMbK47xM3laV6VNJ9XkzcRjCcTJqTzzEy+9VnvH0ULeaGim0KhuL2UwdUrF8EUc+eJL/KP1QaK+BwvqkVsELH1Btc/2K1eM3SxJAqq9oGR+ZpIIaIfyV6lRaFacNRsyzwRcbXhbdQ/RTR92DLmnU1kfALnMQDCctT1C8f//z7j6z7OtyKcd7GeGPNkQUVqhcp4XZ0NXOou9cbc8FmK1wSyspuFarZ3pLEsANIlAYwQ57LLHzI2lwMI3HWuud9lvEjsAKo9aGk+KfQF4klyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2W34tom5OD+5kx3haMPPtlnyW9/p5anUvT7hUoUvhh1hd4USZqiHGfhwK0Yet4i08zTU5vswcYLIewzFEuT/Cw==" } ] }, @@ -130,15 +130,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:NSnJeG/OkCDgKasSMCc4fV/4ScCdRoAEDUinWLRN7xs=" + "data": "base64:wed4WjYa1rqjwD+1go+hEouL6iMQlsshr607RwEkoks=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:BkNAH4c8fy6lYIE+pwgzcJh89scsacmhgpC3CPgwmh4=" + "data": "base64:wbOoAcEJSC9C6Ebq99zIDCCc5/lNDM1Oik7HM02h3vU=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221835489, + "timestamp": 1672870269536, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -146,25 +146,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAKGI+T1ux2XiyuS/MYEPaKO7zMMlp6kDAoEBExK2fHdyIJz6bhLYaTxH1QU7VfRZawlLPBWbFjFBa9Wch3CcYflwHvnZAlXe7ynkQxNoPiD6XMDxsRCkmiiQgSvVi0F3IGGlYtT81FkAnUwfCH+mSUaTAoichLSTwA390Sg2McmwAG7nczskMQml9moqOBHzIszalDiYVAWxIRUOVDiCunyUPtGOaXbt8Ct9FTF+JEkaJSOMxvclBHbcsuP5Gw4vxofTMg+O28VrSADr73Hkd5TThQBDMzjRTHzgeF5dih5tSKe6Pni2eRo76ECqLLWdz27/QkWS3qzf3+FMIoAPvtd6PhPMnZzSOOVkcBPYJ9InOWabr4MyWluqS3zZSJpARZUasYLDMNA3ECODsGAXgeVrDsdWdHDVA54YIpWkSLLBZ/0C1AMZ2FScEb58UxcTIi9TN2NReFDWqQSRGaJwzzytsg2U2az1nywSzEn9G6LD/cN+cH8k4CN/ODbxMIeDrbH1yWi3T7EjwQ/PWx0ZvDU116RSpPSXfFAHbjBXQJFJ44TCMNVKqaH31MWKO1Pcluuh2/ehIDtH7rna6opJurSz8/og2O/K2aM38OLvaIviigRXkCMaM5Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwnFQVEYoTJiidsvGJpe+uC0tlUZQLlsOJBm3svr0pxEc1NotUaShJzXuTrPW0+bRWZNqnqAMoz6iexskuZtHLAA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAeygLbHNGu+Fkg1Rmb03IbdLPrlgLLoDlSeIDJUgJIhuhX9AvFnwB9b9Q5yx2tj6XTvTyW0qGdAAhBLMdaPQv/Y5YsS7V+czdH80tOO2A+FG1XGz4QZ+RZrJQ6z2RpzAg3J6SiROmmzvH15v8DNgeptyGpv+GaCMX0zZZi2nUfHYPU9B5n8YIPBBCzv3DkdSrs0Xqhn+BKJ1PPQbO8YL77lCVuGsqHF/t/XQKJyV615yRQaKFBUm7LbvQnL7GxEc12w7Q6SLFOAtHZvKol2/Emja15NN6i5fRjWq7Lb7zxKCSe1gJADm6TPgStfgGsQcvbtGeXtXHsYJbiuNGtOzDx1cUJlwi4y91mILGwnX9V++X6MmMOWGi84pqaL0UHZRjamW7H36fMlm7Ekb7bgQhkp85Vk0T7SEmATvqUjXtRtInqmz5BBmAWGdPEOHQJA/2Lgrz2bZY0hVMd5Au1SSVslsT2aMpnt4lfPd+sBPA4Kxutf6Tgj2uX6Dt05Y0vg7dJQ8Z7xlTmKk76nnDNHYNjovWgg76y2YozcuIBli9dCzVjiUjCv38XK6aPY4whfCE4vaQ6wEWBLPeegIKCY1xQUIayJgkeJWNXb5tb3Yh2xjMgbujqlPaAklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwUy1SXfNDCHbO488uTRQb8P0ipPq8b2JjDPDsQZgtc9zSzkVLIenCGWF8D12EZ42pCc2Z0bE1iVxbhQJ0DBjnBA==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "939694EA86D1299AE4CFE2F61DBB5D79C9D1A112D02E223806307F1704A3BE59", + "previousBlockHash": "458B3B3C03A0823A32E2B1839EA3D4D8175527063B7F9D8FFE7FB057DE6F62E5", "noteCommitment": { "type": "Buffer", - "data": "base64:5mTYav55OipgK5OxzxiEkoW5Z3894wkl7wwhDyqUeV4=" + "data": "base64:A97EFAPxF0iHS9+InlDP1DfX8KShEXQJ/uvKvkLzVB0=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:WtYL1MWRjphyBHg9jUQcTEJcogNg43bXy2WykH0Z9Xg=" + "data": "base64:EACi1Z0AW0k/AoHrgPRNvHT9EPtwEA+MFUVFxqw1ynA=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221835793, + "timestamp": 1672870269879, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -172,27 +172,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAkGENEJYq2LmHXTyl9Wk82lekOXUZCZuxsxgj5cEkumylpLlwiZxpYzjH9p/Su7/qRJeIa+1YG3xpNu5fUe2TGh3+MDkZaFefhEVmcyCJ/oWYDhqHKzx3opTx+KMEtbM9XVuHI8W7Oe+76m2N6tabKMSSUgyKjNzSojAK7GXaryIAccaVWf7Uzpbf6C7nDmjrcujL2D+SMWFWyMMU5owL8XXlps0nN+macLUvXQh5tSWwk6ly+L9yr6VGb5EiBCvdEdKUc+ZydXWHVMjfgMPeWbGv4VcO1QWOEvv2D4ehBJH5nEYK62DLifvtihn1nkHh0Mdhn7gQSg7OGi0yQOobHcVBs0v/na029nG10tiaO2Y0tRzwaJoTZY1d7RbvpLtl7hsDj0A2D9oWVEtrxqQwkVDQSGi6ZvhdT3pje9+ZWOd3HzWYsqQ4ZQ5rZ+ci5rQt9SQHuWp77MXG2JGKCTcIP3znr/FF8cAr1r5BF0xQrfdqP8MlX99Mrx6oRsStYBqJIcpWYJtBcdwSzKo8NMokfX8nZ8WkGlNYqRLupqxfglLQZeOkIK8ckmnV5xyxP0MVdnlx95VlzO4hJzW/1CFinqysgBTXgmXegfwhkgU5CuP+gqh9raz4UUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwssGl+bfVcf3xMgI85nG+Uyj7/MWqkzZquyRnVRS+K6cluzxZwIjw6I8wsp7oFnEN3WsGcBdkzGUTGIc7GiSEAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA0nNYVEy562e0C45UpAe1hpJ8gSe3c4gny5B74nJDXQaSNoCxoxl9iXK0Mue7MQjEyekC3WjJyyikbWNc6o8lD6kFlf9gztaKhdIBV5LODyKkcHbhOryzVAFbRlLMzrUmn6pnStOntF8+TT3TLttm1LBHJh3YOUOy6uspRq3U5jUBfkzeZ1kQaRFx7HJxLPN/x2t1854UpT+u7bs/KknuNnHhJEPWivF0ld0hyE3J5VuwjQoz1GbYNYqCixVB8rcQ+ZKgcoTdoe2pzao/lh35LqwWY4b6RagP0kzc+eCP5hDoOKcqpxlLnc+U5HChnScGB1EpnJeQcH7h2e6lvjIQQHaycARWh9TORdtlt2Iy+tgrGZYgPbcU63opAGcQ3olsU0j6leJw6/GJzsm6jmkF5TRFVsb49lUBXDrCpyQFlmZHPuRLVSDt5hSpdJ+NX9TlRiuf/vTN/peibMqV6tn2QrPJXJcgqLnlpOiXQAS0hbE5nGFQgHQZVzbMh3t0kdcSj5VCY2PRw5vxxcKcKkBK6Fjmlw8krbpTJVjJYVULaiTDI8pdQ6znHtmqb4wdZzwWYiF1Tqd8yAjx5jAti41ZL8pCdxjF6W+jXNSJ45QrjttQx20NKMFTZklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwc7578sFzGkNrMDrDZFG7ZrQ5e35XUlmzdzsdKgmiTEI98yOF3vRNO2Xd6DUJ9aB8ikshe4chb3EVAvhZ3sfyDA==" } ] } ], "Accounts Keeps spends created by the node when rolling back a fork": [ { - "id": "f909a37c-d21a-41ba-8479-7973887c310b", + "id": "684ca211-cecd-43ad-9a6c-b51715b14282", "name": "testA", - "spendingKey": "142cc1c0dacf596903c33023ce0695383566603365cde4cbaf793211382bb8db", - "incomingViewKey": "9f9f8027edfd5df27e0795c5483536b59f5046781bdc20d343e6d7e1f0906903", - "outgoingViewKey": "c89add49c98410d61a22ad86d29b3855afff0a929aa9d8cc2e755ba4c4ec5d38", - "publicAddress": "a9e3b2b0f24c65eef3df25d2d2581bbb8fb49f79daf0e368ec5500fa01610032" + "spendingKey": "a8963163096f42840e61927c826644732c1e94142d2f19379df4941ba3b0d432", + "incomingViewKey": "1e0decb520e8d00b9d8de635e30f474015c52df754c44ac14584a29e2d248707", + "outgoingViewKey": "cf665b6a1d5ae1dac5eee9b68b40186abee15ffa046b139a12acf8845558cdea", + "publicAddress": "2908b57abb8173a1ad3cb7c480d3fc63e1e9109c0f69799c41e1087c15075f8f" }, { - "id": "8a2924de-9acb-463f-862d-8c40cf4814f9", + "id": "5b00cb36-b7ee-4df8-a329-565e4219bcc8", "name": "testB", - "spendingKey": "7c7bed10935176341140ef52d66825b39656afa2ed54ea85111ba13ebc1c3544", - "incomingViewKey": "7fd7bcecfe87a65da9a80146db5aefffc23cec60d7abd1111b182c5936931201", - "outgoingViewKey": "11283383929cad162fe34210f54efea286ab166c93c9f3ddee70892a41e78263", - "publicAddress": "c72fa4acf94170ff1ceb5daeff2ef030a3113657a578cf40ae802df4ed5ee4b6" + "spendingKey": "83af65fb5a9c8774149d019848d0705227e731373087a45d6ecaabc85e3040ae", + "incomingViewKey": "22f1ccea7604d93e6d19baf5ad863760fae9ec70dd1c70ead8ce56cdf9d3d200", + "outgoingViewKey": "5b227576bb269c0d09d29aaadbaac230e4eca660deece8acf7c9a9d81c209b3b", + "publicAddress": "c2f56c557c07f993d92ac7e1c8730370c0d0d94cdfc4f5169710d6b3ea28f863" }, { "header": { @@ -200,15 +200,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:a0sVis6R404+Y5XWav/GBosRaHZrbB0/b4haJTfxTCE=" + "data": "base64:Ir5zIad6P+HLDH82YCkT1EWZZU9ZS+IkxmGT4c3kdmA=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:0iBmNjaPTHXW8NuSTN3gIZhrVXI08JxK1D1tD0wnHyc=" + "data": "base64:Tdc8sJK9xI69c3FeWj9DuOmx14iHRUeEy9Dm0ek8TIo=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221836228, + "timestamp": 1672870270392, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -216,25 +216,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA+k0Wh4DpT9jlciNqJq5d3PtmIew9U5A5KtE2x4BxaLyttGWfMEaRAg1VEB2dNAih+WzMDAr6pvy1fqCiRIHxXPDCod6r4w8YDBl3SJPR+e6ZrVRi/6bem2clze3dFSi3Nqb8ym/+IOu+uoizyfs5p2IK+FHv/TUeW9YWFEA0iYoXIdBLc8TDWx6v2g48UVsAFUhJWbbbl+ed0i3n2qU/J2tIKPzCdE8YeFaZpWPHATG4OqymRh3NJc8MUpbzEML3t1GENSWMQ66ZOvQwWiDxwLSc4I9IEgFa2LdI7LP5My3OhFvgvORFtbXHs/dhAGs0/Jrh32G/HAzW2TOwwAmYXsHP80ZWYil4WtzB2DbZB9vCW+uMg5ChJK4Tg2YHaZlLRPgVsXLNgNP5X12I9gd3iSAUCHRexQTSlvNblgW7sRgFTCTyt2lM3qBfjuRSYR+xH8ElsjLGos6Ira9AOgOFnvB8MNE7eRMfxbz2pn4SsFhucFMMSWsYNvAWJ1nssSd9nLwP4w1/bjAZgl/vPQGeIfuvSQRmOIZ7+GCxTFS8NBQ4lbTaXFPmvUyWHH6gQlfU2l49TIoZe731wVykTH1QXyo7avMPwa/BewBkMk8Ei+GVOTQTIcsS2Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwapUDZoM+ctmjBAPxgoIdqj4dOEJ8JzKp+Fq0pPpLEF8Jo5EREY4S+2kKZmjyNg/jl/7Q0skLL9vVQUO+kW6YAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAbU6qUG5TQPj5uaM9T54y3Rb+Y1X2+U2nG1OUA8ZF/jGxhtZ7ssMIaoYYUkkvc1xNtm6fmneaN3uYmUgAS0ypkvkiBIfP2UhjsyK1MEa86q+1LjtDWdbijCQOLzKvGoOcIyhvOD3zwOHPzZ+mSVfUGYXrwujhXE5K700pvrAFDgwDkDETk5IL2XcnPw8RcVvn0pdIte5iGILvSaFehZS7gcUIdk38Zb4OtRr4NXbY95KtE4ka7LRhXb2Ln6kBrthfPvlsyCx5+xBMVqNC84EakpfMONjgDC+CF6axuzl9cRs7+ONGsILjFdN33QnfxJ8Gx+3skJBB7k1Zsa8UqlZfODLC6j0yBGNxB3aP2No4GIODrKnBLimjaJns4FMdAQZQU9w9tRL9H6iVZ+QvrZNY76CeL1l9dQC0xBCBbpMVnu5cMrm3RUCZ3sDdHsnGUuii1KB+y/qk4j9i2V5xhkLT+IstxMMIaOWfSBlUJOw1gwayDA+ak2iJ+VZrOvzMsypAuIOx8c6Bl00R1VKzMyUVeBX0ntyjTVJordvMQgQrtw0LQX5UFMhuglVXS2UZTfavzxnlwZ795YGskA5JQrz75Hu9tcQ5O9e8kPCUE83SJkwOSogOk5fGJ0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw6culkLNejfpKfYcuAuA83Icg0Rm/KuoJUnrrFQf2j4DuLuVz750KD3ljW8SdegPm2NH2zrDAfVWXrdgYpBRsAQ==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "934DF0D655DA624EE87D36EB222B0DD4A780FAF9EB1701E403EF1E19E63B40D5", + "previousBlockHash": "D41752C8A47105D08E1B266255DA8C956780409330B7EDBFA478D432EB8DD9D9", "noteCommitment": { "type": "Buffer", - "data": "base64:MFHd1NhL76KXut4DDyEdir2oThHxx49uiARTUz5ryCs=" + "data": "base64:HXCstmcsinz6OjYp4FZxGYPaowbcAY0VIgO1azJ4dQM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:fS/mQaOL9QMmCmJy2gNajyz1iZhMGVaEYM08Z0NAYvQ=" + "data": "base64:QZQ/XiRlAz7WC2Uae8/aX5O3PW9zL78tWsYXwqatp60=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221837919, + "timestamp": 1672870272448, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -242,29 +242,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAk+XJO6W9vpidU2oGAU3XvdqKXw/QhuaH03SI/goQNF+MfuBhjKhFeaKIXHMNRzrg8t4oX2uM0eN62/heo/Pq1tkWuV00S3SUnOC1jSDw7dOAfToleEaTsY3tH2KWRDo2wKKdjZumVXjc4me0MdCGNizuWHWv5xkHvmUL45KQo6cGePgWrc2SUCoWqLozDJDN6yFJMasEy6c/UrM5/GfN//CZ0lHSa4zIRAuNm7w4eCmtS73jYFeYrAb7Ze6lgPdSHx9WAdJXoqcbxVPS6K4rHgMbssmfEvbfZTVuBm7iBh9oJGIoxhzjzO5zACbbGHZX7n3kh7xFnfoSQFeJ4CYvEqWe+ihL1YcPByaog8f+JlVwtQZiyJ8y9srrKcSo+L874qLqnL1G37Cjopo1dtGCVS+B5vx9zFocLYDw4FINq09csLh9fo21i0F55CUT6nRH3nn6N8aQzyTemxuEJzYeiRm1RlD6J2SrBoq3dkLoaq1ywHOromGqTQxwZdnmAeJYqJOxYxaRQkbZiUdqihp7xexjC411cdOk1aGI59jYftCuGQ85VujEwEfQaQt34NNfMk/46vWodPWtD0u89fkfJO7INiV17H74Uj4Uy0FJlT6d3HbRsMuzUUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAIs0cYzPy0hDFsnBmH6V0Cvu6qA/ubzSj8yitl9UIkxa1dPF6OocPvjHOvocFk1VhbwkFyw/NJoDVB/okTA0Bg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA05fQIloI+byliiqLN6pUCF/jXwKwF3tG4gTvXXD9e2qqglzg4z7tOOOuhUumgGqVRncN5O5YH/ug7eBFw+y46mAnx5BB4pWdTY25DQSVTC2ZdgX8OaTpLUHPX+LJ0D1R2xxu8HVUi74nvsP14w8+c9JbJtD4EFvKXZyj9HP8zUYE+KxvyZG9LSz/nSNg2cqLrO4MToQVjYcyowi5cnNI2CyzHOwo19G0bT/nqAdL16qVFcsPFQp9yuJb09ZAWibN1AIvlJfy/SJ8fr+ItFaYjSIittVEgSLKzSLQcdLBy2zJXzP1T7RE2WhUrt1XMyRhcjqYC6M9jZ5RAp585klkGAzdOAyr/DjBesGcMr8HOuJB1kwZdatDOImSOBfqGKUZ7nDo1AM9E2G4XzUpmDIq4otnsUZBvuglISCZDTDHdOwJgoS3wrpiCZU9wGaEX3VYKWxaZTFI/TSxlLgn2N1JkYhvoHCEvNMnlPUllOsLmsRT+v0xIJUVqr25jJHB8Y87rUtr/2dscdusNVf02zKgPHBn4HS7lP10yobv2N5C5Iiu6BAmMu04fnZC3wK7bghspLeqkZZ5bkgLeqLWZdAzweFPXujMus6sELLo6ANITXqak7O+S+DRRklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwh/3BywZupdQj54vuNKgPuIVygwdg3x3mqJukQMQbWidagMG0fU0L9MkVIDq6cYGFOtOgpBDKY3x6j6YpMTbLAA==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "934DF0D655DA624EE87D36EB222B0DD4A780FAF9EB1701E403EF1E19E63B40D5", + "previousBlockHash": "D41752C8A47105D08E1B266255DA8C956780409330B7EDBFA478D432EB8DD9D9", "noteCommitment": { "type": "Buffer", - "data": "base64:HODoDMJ3Duhro7xF9yLXZLQNFtW/80UvC/Grg12mVWk=" + "data": "base64:2Iv/2UNo2ZB1PnWj2u1f/zZnpzoGhvYJ9vfUQE8cg1Q=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:xZ7DqZz4z8UUZ2oCQ+ZOnuBl9Lqr4QQIYG6v4ZC0Ipg=" + "data": "base64:eCAMwbgvFnT9jbRRYwdb49Szx4qXKZd+nx19zhepDAo=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221838234, + "timestamp": 1672870272801, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -272,25 +272,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAqFyXvVqdhczgfjZLHTlo7/58REYIhJI4U7RUAR9bQM6pg5HyQKZVmDy1auskFByBVooHY3018rji3WSU5SYL1q5CiIfrEfUbndJHxvu8VIOMFF8AajEpHP7mVM2Ll+hj4Z1CT6sRmJXE/yUZKUwp9dBEIX0y6T02yZTocFFAi2oUaubPIv/5u9xEvrJnjkKSgRJaqrQ+TEb7ksR85Mmo4S8ZbQYuQ0ka/8OR+0y2vV2y/RwRZSv0+uvdNhiJ/lPCwlVfksWaJxntir+wDu/IwsFvFwK/YvqueRaggTlTkZboTuHuhjXG2DiWMbdPVp09PfHvM1b3s38Xymzqag69IZNgrPUOER5P6g4hs5mihT4z6f0tTS41skiiYR7uoN5GGzbWTacHeiNrU2agmRS+QJ2RbyipRogq+yV4rJ2x5XGOutzwC4BfjAKyrv1NOswwFv4LaO1A7ntMESVeahI35eRHmb020ocpKvsLz+rs+iQUbQliV+Av5dOc/03cDZah16Y05TB6Aocdf6K8w9j95sHoKi3QY08j5AS2XY/hODC9RwuoqM5VsDHX1yYRZvl2cQ875fRYBnfMItfrFwuft3PEyMuo8A4KNuX4dAq0Ejuq6AcfYoAJvElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwwWP49k/y/VtrF6xScmq0mBLz4cV1hRCtlconwqaZrUdBhtrX8O3i+8mtoBvaz1trUS6ReK4bsnOr5xfJ90azBQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA/FR8NGyv18HJuG0fV1PxFE9kXF2y2tBsCuoOU3Rr6m2Lz1WMR03iQ3gVvrgy2+SCUJ/PFRMn0kOQjc7BBuO5HjXDvp4rOwWpgaBJAwkwbE2C+gvYDitd+dy/Z1shZWHg5phHqBsLguJBBifj1Kxt9SlgeFd9jKhL61Go9uwnm+EEKLP/PkSV2JPh9hGO0H9W854bxsonN6GHMiKiRmDgN3uBWVI2Wy8kZ9aJCNPOJQCxDE57SFSNBUCpJwmwo3B9wdxNkneykIgMq77QK4IcBUufqqqINysDfwkAvwM131eIdy6TeBjdpaqA8jgHbctfn/9sTzgmyHN0LkyKmd6IWCDgAKjzXkPL0JM5+ylhrz0flkPT5HHA2M1MATR+PUhEuonKJ687UjkVIinX7sSnEQ+r5YNuwUUIFWyhLTrBFT80d8ZI435SDf6AY6OFNpKZThKndbs8qaBKD+y6Tdz3JiTiCY/LO/3yeU/wT4ZTQZJOdHa2J5PWwMNrgZRq1zKIdIcTnAVrC4GShcMWSnWclkAq7avxnb/9SibbK9Qn2XV4563tTYe2dcCQWLt7MHaH4txCUA3FRDDojDocSkaevcLdxjjWN5NEyrN1AiaXLeKivlpqCLHzqklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw60ylh1IU0M3lFiZm2wP4Rwekl/7L47k+5O6m+Au5vuBSfJyAcG+IhwmWDJaCTp2rizDbxiEo0Dvx6xJM7Ti3Bg==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "93D668054DC90FE071669F18E0B9C33A8BD8B604227BEF6F15C9A1A11CEE4D48", + "previousBlockHash": "D3DA7E63CCF96B8B024097E56BA1A0AD9FCFE966FF9FAF4A10B151814C62A986", "noteCommitment": { "type": "Buffer", - "data": "base64:UKLOjlcIwnDoW1wMPjDqhlRpzpQ3DIyYIknmYeywvy0=" + "data": "base64:jsJ76rrrL3DxsrICnk3LSAH7ProFw87xzPMtcG0zPTc=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:5aiZA5R+b07g3fp0YZJG+ULa51ePDD+vx3TEQHDsc+s=" + "data": "base64:8vZTzSyL0Tnw1ky3kvWRJZuZxq3TD0tBY8dTSsNhn2s=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221838530, + "timestamp": 1672870273186, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -298,27 +298,27 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1G90US8yVrgz2fWs5fXk6A0s87ATgRQYLPLrSYvDrIqGowE2JoUyqELyws2MTrVQkzT/XuHwQJSWmguFDXb28gvkVzh7Zz8/D32y4FCyYMuPUyEQazvVTOs+pXtbwN1+T/tftGNvn6x78FQyLRkMZJXf/UB71yXP1I4N/Ikr4wYOK0rOJrL4/WvMcsb4jDKN7/0+JwwjwOR5+kJzxdFprqyn5uTHMRZ8jNoAkw1I9MKunWQ4ThP28TgabL0HFhgS9NKshkhU6mI0kxB0znfXW+M0IGOhn9W6u5IG1OC0gNhzkitD2F4Q0nasdDBb1HNzAefZ98xg4JvqhXxka5xtsvHuonYLnRqcOfvdapPVaDfQrQl+jpG9Ynnq4i3cyEtMNW7CJXL5U1dzWHIFoKdo9wosbGJ/DzThohVINQtSQfIZ+GdIgld4vHpTIAoFeV5QL5PvdRl1crtYKzy5G3EnHnCeihSQPp/DPjpwzk0DtKNqWJmT0vbiRLz/810YCJ9ZRrVnFrdhauOEgm+qVHo1+EgNg008q33WbxTtnJmZYtqt57fqef6Qvpcnm9C/2Ry+xQK3VYzkk3IaBGtjAT5f073mihkVeqgAnWUJhNo/zH5GKpWmBrRtlklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwhDCW8dVs0TnMXScGiJH2T5tLcsjC34qBmYfTdpTk6zneN7XcLIM4olSA8BJtecGLCag1nULNz4c9e2Z4A5ZMDA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcqLQSkI9VNlmmMGyKNHJWbXM+wn5u6Uuf+ulOJbZFQ+xC9uFI+GowN1g0NNsmor7SewkOwd5lUWalwN6Kf7H6BL3Zj8lBHrI0ZqngFArtXuztc2Y052sj2SLT6RVpAcj+CoEFUZ2+RsQGtYMrtfisVsxos2bWHAbCfH6SOaglPQQD8vIk6tSLqto5lYfcKWd8bY7qqsp66D9rQm4Mk5BnOqs7ueC68BCjtDHY34tSf2VAHvOzlol/yru/7q17Znq3JUrXfCFqjOynZLWNb853CC0F6ylVLnbktnc65Hxs1A8ARGRbrWASkAMstbzZ6m0QPnotZ5A+zuFc8iPn0lwRu4n4q8A22FwXhS4xXwyFHy86hWbIO+0JkfThmV9KQltRHK1vFQDcNn6XOz9kTrcgYWJNaIFAl5iPwG3RYdF4WJQjQ5IE8BUIVzr++ZdeuX0wJjw81PdxKVl2/kD2ys/8z7mnPl6R5zKTuCd5c23uzSQlL6UUGKWzdLrNdZgZchuKKYZWafKY0evOyEODslMlQYMYICK/Rh3nMoAKxrH0DOtOgfy8XeburIsGShVWRXssjzTwaJe/cgG4/BE+4PuVDICzOgOKT3bql4Z5HIkFhnzAAOIgUXzDklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwzp4wTaPUBO87gVDF7byxwNsw9Xxt/w2WJZ5ohWlBGpJlbomm+M7nJ9vg2eyzHHKjKZDq+DzFWXWLI1K2GYKxAQ==" } ] } ], "Accounts Keeps spends created by another node when rolling back a fork": [ { - "id": "65d8f7d2-45dc-4834-b77f-4f28576d975d", + "id": "26d0d991-0cc4-4ea8-914d-e8d47e32d841", "name": "testA", - "spendingKey": "2677b5d6992d990a7e9fc9de18fd898489178dc13f9aa390d7e5075382d673fd", - "incomingViewKey": "be61eea5ea4a94bb03bd8584d378a37d014b569e25c09a63a85ef55b265ddb04", - "outgoingViewKey": "b0be9b00847f01f31b86bfdb546c9b3e88027597f6d0dad409d30da99657fc6d", - "publicAddress": "7d4e61b162c1f7385d6fa0ecb9d62b58b6a41fd9450ae107239382824f44bd12" + "spendingKey": "3d39ec9e0a97c5722c5ac8cf9a63863416b7640c91cc1dfb5216629e53170a81", + "incomingViewKey": "3dad63eeb222079e2e36c91887e264a2e831ace48c47dee15c51e971cff62207", + "outgoingViewKey": "7a13f0818151b535cead68753c942b1f1cdeb8e45ef45c031b24d8ff8512c868", + "publicAddress": "c41e30c298deb033da7f96ef3c48f1d2720d658c94a9d734892c81e76ecae8e9" }, { - "id": "4b6c8a02-913b-4929-b422-0014f98d6c7d", + "id": "8d060097-62b8-4563-9933-a6abddc1b6c1", "name": "testB", - "spendingKey": "6198548fb9852ced04165c7e16becc0d196ad128d53476627bef93996c5ad991", - "incomingViewKey": "134c10f8434c5ff1c7f596d4fafea8723e703bb12ebbb8717aef8ba00e748503", - "outgoingViewKey": "28ed8f5131566579f08493ec248b380512f7a2bb4c492633e87d4a5b81a204c0", - "publicAddress": "35a8896c46b2ce36a730d9376f475f256b0ab361937ba369f15fe55e003d964f" + "spendingKey": "df6c27be2d46edacf1004aa483798dbc42ea754e9e1557ab197a7499514b4b92", + "incomingViewKey": "4a65ca6ce79818794501d05749b7998c42a7cf38bfcf4f2a8477544780c11e05", + "outgoingViewKey": "47fbc47cac2a792e6c937cd106437a03f8d7f237fa7b5983979a16e85b8fd9cd", + "publicAddress": "36b4cd2b40b6cba9336f5545389fe77c8f3bf98dc940ce1f79ec24880c646007" }, { "header": { @@ -326,15 +326,15 @@ "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", "noteCommitment": { "type": "Buffer", - "data": "base64:scCiSYw3ndcGW4aTi7ETXA5KDC1iaIRn4011+P1J4zQ=" + "data": "base64:YJsgV1U4Wv4N1vC4knIDAcINBVktO3u5K3m/+PdMsQE=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:n8kaRF2hNJbBmXcpA9EPY9mT8kb1jwbF87LOoE2llRk=" + "data": "base64:gCmpU8v0wW7RFGkWHKM6Y45GLCR9IvRDpjnBMpDk7+c=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221838960, + "timestamp": 1672870273737, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 4, "work": "0" @@ -342,25 +342,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAVIM1jm99MaG5Gpuu4TY8cL5eymChFQ3pAaUN6yd8zfKNV+mbhObHRaucXHa/+L+cQMvhQBsHN91YzhIOOTiNFjNmG788Sjc5oaLUr/+tuP+U3Dz+kko+s+f8kM+9N/PyyoqKamlCrjSeWb0LEAT70eo5GOS7OzMr+y/F49oQahAYL5ZwUg6A/Fv4UMjml9KShTT3eQFSM+InwPoLjvsPlGKoxr0XieRGpSrhvNC/cS64IrpJpLGLbemVi8NMYF9hVfEah/PVKvoq44r2VJOS5Ix8iFNxwr5s3Nzs5WNyaAXN121b6pdyl0IPFUMO4AedYWsB49Bu7ZID5vfrUKLxbiVdcIGjS25/Sd9kQgDn6Cp+E/qpQbiX9io03Jp2OGIbL2zwFTtkEJbrP/x21qTW6T9nwejoV89vp28hJCT4eQqW97Ocad70arYvn/gvrA63v82keV62EJxMIs5sjeInl6uMW7yMT4wdeiRIVYYywO0v+1ns2rO11bb9SUCSx+MZL7lObBVGbjX9zLj6xV+GZwB5Bwacz/T+LJKE9kNWPw7dPSfVagmRIH77tSJ1qfQmhbL5sINK9U+9QBBBPWY5LbKyQcsWirNr9sbpLFVKQXsxgdkJh5dkGklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw6S1O+tv6+j5p5WaJ9zljvr/BuG52zRW3nxZ7iBw457SNbzr7u3/s8jbntLum1m43s2pnCppRfu3tgngurQibBA==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAdAb4cRkVPzRGkdnYjgxCXMC1Yb6sMCOyNe2K/1z1xlakdGIdFsYVKmXmiNIHW4IP8x8Zq3tmfce8rw4Xr4MiAmfUflGIAqGsGMkO2sEPUkehMHSn3EKROGoNZhRuGVG0j/6uDcfad/il9GUsSMWNfZztRmm1MbI1fuFIQVVQdHAQpoUwdu9LkzOE3ec3w/48pUz6dObYz1LxaoXKPEoixcyG20hIPKxDgqlEqn2PQhKXVfMTLsu9oGyTGVQptn7SRsadp1hdkqzPxh+LKsbhXk0HVTUaxQ0R69zXQuyAzVt5T5+yNjrEvrbMg+kSY1eIjORc1tfhMSLHWAxJQar3kCosNdEl9ylaCDm/qWgMh6qhqceAqmbqILDQxsLZa4sBmw7kkUh7NR7hYV+O1Q+MzsfDqrUxCl32Bvp24P+xqC3QBOVog0SKPjCdoubZjboLFwte6PIxR5xbHj71zmqfyU9EIF2xJ3NN4aGFVQf2aQCwBB7UAn41X4Ifydzfn+Zls47QDVr7ekD8kU2xGqZcRzKRXtULvx1Xu7qmz++qHNECfolqqRPANEaOO3zkY5+Bh5gav8PLfRZZVJg346uN/KpGtr0VJmaAxxRmMPMSVEOOBPI7D8bPWUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw0oi91PS+Q8EdNZO4wYIa6igcWeNF6xcKjVI7ctIzBtHtBXIAhSgvbepDdmE5kUF+7JUA8QOFRPP33xYAsnvMBg==" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "6C65DB5D9104740BA8ABD733ECA82C6D61AFE4A87D48B857D598EEE92CD86048", + "previousBlockHash": "F7934519340AC2E14616259966464F73D3E497D244465C4C27C63D6561E9FCB9", "noteCommitment": { "type": "Buffer", - "data": "base64:W3LuqAX4kf+mVJqkJ/ItbEIkMif4Pp2h95tuQRmCp0s=" + "data": "base64:3OCN/gbx3cEfHyaGyWDUeC/W0B0IjaYqMRMI3btxkz4=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:q7lBMtdg9+oFgO8PTsqVjH49gFXNqkW/uDdsOJL1qUY=" + "data": "base64:qLWAR4JrrhtXU+aVBq/teebna8eiv5tjwWGs4nw+d/U=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221840645, + "timestamp": 1672870275787, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 7, "work": "0" @@ -368,29 +368,29 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAS0vkDyVB1PvIuDDzYA4/Bz2X+x1PgnlET/9jwL5dCaKmI8V/GCJknYT+CzsNwezyHqXAhWP17//M8utDF4QhHRWMA0gdg768hE0yL1lK0XqJau4U51B91SPwwd9z166h032aov6aELAcfXzQH4+jD3sAaZ/ND4kiTKmki048irkAp3kI+Hn+NY0auyySsnfL/lPPKPJzUPR0BrDwMXaL3HNnQqPXfP5yfD8OD0gapzKxy26zu5oa+QBt1OqhF5mts9kzVqu4DxXZYrELXLWb9jtXAjfAh43bvi19JBxTQGZrxunCPD2LM2/42oPAQ4c4gnyTh1yYiRDr5SS8dD1+qp+RYCrGIEjqYKG/MfNwwYdcEsJjG5WA68YWKieFqNhi7j1yXFgo7wYomPILaWLO0ipxan2ru0eln1OYbuO+NtgVeTjfHci2HfsfNyGTnj7wSZU3fm1lsrIco9FDgbuwPhHfv2kwB8EvIkuv0/jAYFLcwoTFAb25stEVgJctrOBx7TqXPrwvc3qA6tAddBhM22+FjKczmp4eAATSfNqRypAIuj0nN5g44WvX26Gus702GPU1LK4OIXN9aSf6mEmwrE5ya9Bn1xwPZ5DGyKF2n8wONrA2sCQ7cklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwC0IcJ8M1VP0Cqg1CWBaV2cDuflTcUsDAIgQf4yCdm6VLstc8sRKtjjtmZFQLyiiSr2zCngsdBhYBzXGlksezAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA7j+CJiX0T8HSOCcD+Rlzkgi30wirH8Cmhdrss/xkiqGh2LrhS5pdz+2U06vbuKTFFrgIK0Ts98s+j7olo8Rm1T7VFFMCV9Dljlyia9vLU6mNmz4aat9n5+27Xy4aa58xL1Xn4AweGO6LGybUIC4I6/bBzbh8FPtbzVzKJPy18HsPs64fqg4rwakR2NNxeEsYaOnU8JtRjsGZoSre+UrKGnE4rRO65ex3Nz/c/5I93/iBDyAMqsqsy57dMzenaGVKXuQfhbEhaP1s9RL+IV2n3U+TzVg8noSFBgIiuPQyR1HLPRfweboAumlgatBAu2wMI5IDVhG5o19OXb+7+5GJV+UDzLozYUiK9mitbp6y2E7Zgt4Ejg5kOy/LhoHjm+E25U/KcECMtROgopLjAbYOIcL1g6X1II1HNlFadfi+jchMeNeZCE5LBpr2oiN5tQ1akXiaHBXrqQAT+rZIKWlfD+eeJWbRMY/+YKhsxs06mG25UqE0GssldBJTxS+JYILt0KRxliZwByyvy2WEkO9qBvCKguneE16OpYqZ2Q5/sdNkbbYBngjx+Bt0LhUjeAnQwWA3uWAWdnwXUtZHm1CTgbu8BlI7GsvUaLhxhvU5HLXcJdF5S20zO0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwQzOUc0fOE7dq+1bhVSYqeGzSX6UlQ7yiOCdqoLNPkVtkKU92chayI5PEErG/gvLvLA/ZTgKtGd7erRER+hJpCw==" }, { "type": "Buffer", - "data": "base64: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" + "data": "base64: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" } ] }, { "header": { "sequence": 3, - "previousBlockHash": "6C65DB5D9104740BA8ABD733ECA82C6D61AFE4A87D48B857D598EEE92CD86048", + "previousBlockHash": "F7934519340AC2E14616259966464F73D3E497D244465C4C27C63D6561E9FCB9", "noteCommitment": { "type": "Buffer", - "data": "base64:BXqZAtsuW0NhELA5K61l9i1rOHl9/2L5x8TJwKsz4mo=" + "data": "base64:eZupYddBlcvWPUkzdsFjzA6KGmlg2qk/DWIyr6xDtwM=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:ACqpz5joK+jpengqLGCMuzhZvgeQ8Uvo68/nljIK3to=" + "data": "base64:PKJVvN8bopx/XWFeQFKxfHUdMXVeMso1aXGylN186tI=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221840961, + "timestamp": 1672870276135, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 5, "work": "0" @@ -398,25 +398,25 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAwIKGEhCJbo50gRhLNrIBnD0JYm4ykHu2O6Y+m0EJltKver2QmpOdQng664w6VdOI1IE1x1jQjRUClhrixciVkBLr5Jx44DJPZe516mYIKIKq1pqiPo5iEF4t2DNInEu6bS+NzRJ4qtw+E/HnVHGXg4vckAwAQWHjklWe0DTqH3QF4MsQsiPp6+2DgohOCgKhKZTYJnzggpfs171657NI7Uwva3ZfqbAdtSFqIXOEWdGEyYyFYf80TjrtzHV17/ZRxzbL3ByqeyCiFb0N7PkbK/mna8dlRLjss5cC90edlJZWwi6A1vhlv+843Im25Fygb/pFjFPVzCidFqD0p+303oOTkDFv+r5NE+3exQf/P2Pvn/upO6WQ2QOWSfCncJJdhUbV3ufb7lCm8uanJetjS3btAOM18BsFIwtmBuweVOAUsLly3a7x5UOSBR9uo3zroqLEUzsBPhZ/l54JHWBPRyqG40BykANjS69nYR6+/DWAMcKUsz5s+YD0m1vszQ5TOK+KormBXcOWt/HrDBRgahnYolsCl7+NvlJ4kBP3ggpbjA02FC472VyQ34jWjL36gExqYxSiooUC9b+wCV7iZmCMdT/bykOgzhdlwmqlTqdhJvhNj7HEFUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2y9LQLi3qgivpT/bEOXVtHCXUffvxTmkM3QD02357xaVX2DFmvWFzJgfoisrIO5XLqCyKlaFh9fkgWcvDysaAQ==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA+MkQe6I8858kVJBRCrkztVCZIC29KHxKJkHtQ87zvqquvchuuWbAmoNsKeXgt33XPWxlm0nxV1M09kRQ7iuZyiwey/TnAPyXI6z2cJrVbd+pLVnlBzQGEw/6b+5hLtVTAqemw0UbBx4B24c9YXE+7AeVCQHAm08/9G89fUrafG8Y3sIvxjmqa77/03HC0OxgvJ5TQrnivtx1nvK+VNt549khMSAN2ZEEtnnBzZA8UnCXomhAalp3phfLlEktPa3psMsmqH3hl/pdpio40A0/7aM45nUKwjVPHix3Q4V/XhKIG75JrQ5wbK1IMK04i9VxPclFcjL05GPYZ4s+BYDVqXnIHtQ/gV/fePz1waOawbNPUyL0lEnxoMtlqkjYYAUEE9qkUBgzxpGkuMeyOQLpJDM7wqDZqnbhKYoX4KtRHyUHxB0f8qMD6vTkeMUzELx2shEu2jNkIh72b2isvBTZlEgoRyiyQ5r2XFKqmsl2UfTSs9+nXmrkQIqJoesPEUzKvULwYLD5e04NbO6xBlhMcnxoep3pcUOutzwoQ8ICG9FVOdGM4VMWcC25FdEVtJ925x62i2vG/UI8PM2RUdtEsyzR3OXS12cqezO0sk6Zv9tEAkyoDlZ+Uklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw18F8Kekhuf9loY4oIYsHDf/WTTue/iWwY6DfVlVp3TOkV2o//HeY43MpH0Bil6j8T+vWSJBEb91XTGdIroaGAA==" } ] }, { "header": { "sequence": 4, - "previousBlockHash": "1A4AC3FCDB52AD069EC0DFEAE631C361C62319745A4A603E690BD912E2BC11D9", + "previousBlockHash": "BD9AC8A260204ECE7B8C49DDD72D8CA352EFD107BFC88602207721BF9649661E", "noteCommitment": { "type": "Buffer", - "data": "base64:/y3qAPLgRNt0KASpFmQWkZ8slMgU5sNfP/L7TNOeZ0A=" + "data": "base64:vpLd4euUV4WBpiWT2ipegFd7b7IUV7JJ3a2WrcXLS2o=" }, "transactionCommitment": { "type": "Buffer", - "data": "base64:2v+oO2HNMNLUEGjlXpPuZ68at7a6gvci9v/UFWuPbso=" + "data": "base64:yR/GtyfQKc1ysu93c+yMLlQ4nBP/dNtAU9x2XYMIrtc=" }, "target": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "randomness": "0", - "timestamp": 1671221841262, + "timestamp": 1672870276493, "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", "noteSize": 6, "work": "0" @@ -424,7 +424,7 @@ "transactions": [ { "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA682LIRrSz8djeH0RCWmvH8eifdlnChj1cNOLCSME4tC3t15grKC3ef2WmdGZAdWHMl/1D2gYySlMQGNU3H3C2GX2r0Q+TNt9KMdGfRB6ARyoFGDOYvVETYwmWI5yKXlwh9vabn4cYFz/USqm8dt5dlad9l8HbHmTV8/dB/kre0AOeVAHcDzRZ91zVgGaNGyFfp8y2/mrQa4nJ9mIWicibRG04h+QrhIrDLqF+M/AdIGRQPOj8vfi9C+Uk9uw1LCE75SMYge61DIdlr+pgkzENh4aAd4uvNOnd2vvJPT4AzwAnw8d36L2CFUfo1gY1MLi9BIkj/3iY+MzeBQ9lbEXHlusThX/9ENLD3gu8gDe1cgw9b950bKKknOJZuatw60LzAROVUshsEbmhwpmOxFQV0jhZQJ3jOY3jy2GLkZuR6Cw4I9kIkmhwMcAR+y0XJbjFj8kEKchkhSFK80UiOThE0mvw7Q3XU0yFuXgorVqL0n3yu37G/67nUW6J92uu1maDgfAvwl47kdnYn1YWbghfnepxFjZt7kTXgZK2Kpq5FeQPMNnn1VMzPTNLU8468uBois9SExa0Y3qIkt0i4IYyetGZP9H+IlznslwN9Q+SE8UnGq+0SKbc0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwXgoh9QVNlzKcRvlomOh5ti2ZWHo+uhV0WvybO4bguZR4UE0gwxyl3BKiY4ysIkVXPlsHu5iH6cH7LjHCa7tWAg==" + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAi6RPgTRf+iFkUiIfn4Q+rkWGz4+DKLX5Lt3ncOR+dFmEuExKqR1fLSaC8fHP/c1OmusDa8T4XCJxvdMW70a0OqN2/wgCLJ0ozts6J2mqdGeYH11QELf6jw1TsQ3CF9AHELqJ0T1UlgodbUZl6ch2GnuNmWcgRqouVD/zbNQwqMsLJMFzVALn/Ya64JpKpmvVZOoY/0QroOFAD4wM5+s8T8mw8V48a44JOydIC4dBYEOMJBxZYZqwIuHn1H3nZnqBiCRAAKolRrpQSiV7AX8244uXjSdXWH/acuKw08ssHtCYvcI1UyGiO3eGJ2Vh5PuTzCaSimPs/h2OM+s9MTDAUDnY9vc4zfqs6SfYcDetHBKgPUXSGUr3NlPHiZ9hjTpc8P56frk5B+smKWD0fH1xypEvYVXy6tTNHoywQtb7AA8EP/uSp2KY55FPAOpVOBRFyMKruFv6p3U2a71OEsnvWpbikCR8yLAf1YMVcs5fSu8LWQiauGW23xhvIfrmPm6dMN8FRm/LRxjWevb7venon7hTcrzJxDmnOvAOCAjDushJLF59z5bBetvXYW4JuH8y+d5b4yzxxjDv2FVwqrB614Zudkqjkh19aobZdg4h5bf+OHzxcFMZeklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwyoP9AmC8zF5IUAfC8AUEw9UvboEr5PbSuVtVTSOLuFRiXJmbRp7cRThHNPd74CfQVWZQr+zfpaEG9rDyxyODAQ==" } ] } diff --git a/ironfish/src/wallet/wallet.test.slow.ts b/ironfish/src/wallet/wallet.test.slow.ts index d72b6aa720..a9e34cbc86 100644 --- a/ironfish/src/wallet/wallet.test.slow.ts +++ b/ironfish/src/wallet/wallet.test.slow.ts @@ -76,7 +76,7 @@ describe('Accounts', () => { }) }) - it('Lowers the balance after using pay to spend a note', async () => { + it('Lowers the balance after using send to spend a note', async () => { // Initialize the database and chain const strategy = nodeTest.strategy const node = nodeTest.node @@ -117,7 +117,7 @@ describe('Accounts', () => { }) // Spend the balance - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -194,7 +194,7 @@ describe('Accounts', () => { }) // Spend the balance - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -273,7 +273,7 @@ describe('Accounts', () => { unconfirmed: BigInt(2000000000), }) - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -330,7 +330,7 @@ describe('Accounts', () => { // Spend the balance with an invalid expiration await expect( - node.wallet.pay( + node.wallet.send( node.memPool, account, [ @@ -392,7 +392,7 @@ describe('Accounts', () => { }) // Spend the balance, setting expiry soon - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -491,7 +491,7 @@ describe('Accounts', () => { }) // Spend the balance, setting expiry soon - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index d36ba42b33..2b63533433 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -646,7 +646,7 @@ export class Wallet { } } - async pay( + async send( memPool: MemPool, sender: Account, receives: { From 3171679c3c1f9cb15753ad6b24e50767b6ac0f56 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:00:43 -0500 Subject: [PATCH 39/56] feat(ironfish): Add RPC route for `wallet/burnAsset` (#2833) --- ironfish/src/rpc/clients/client.ts | 8 ++ .../__fixtures__/burnAsset.test.ts.fixture | 50 ++++++++++ .../src/rpc/routes/wallet/burnAsset.test.ts | 94 +++++++++++++++++++ ironfish/src/rpc/routes/wallet/burnAsset.ts | 78 +++++++++++++++ ironfish/src/rpc/routes/wallet/index.ts | 3 +- 5 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 ironfish/src/rpc/routes/wallet/__fixtures__/burnAsset.test.ts.fixture create mode 100644 ironfish/src/rpc/routes/wallet/burnAsset.test.ts create mode 100644 ironfish/src/rpc/routes/wallet/burnAsset.ts diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index a076e1bb66..3f7efab8cd 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -82,6 +82,7 @@ import { GetPeerMessagesResponse, } from '../routes/peers/getPeerMessages' import { GetRpcStatusRequest, GetRpcStatusResponse } from '../routes/rpc/getStatus' +import { BurnAssetRequest, BurnAssetResponse } from '../routes/wallet/burnAsset' import { ExportAccountRequest, ExportAccountResponse } from '../routes/wallet/exportAccount' import { GetAccountStatusRequest, GetAccountStatusResponse } from '../routes/wallet/getStatus' import { ImportAccountRequest, ImportAccountResponse } from '../routes/wallet/importAccount' @@ -334,6 +335,13 @@ export abstract class RpcClient { return this.request(`${ApiNamespace.asset}/mint`, params).waitForEnd() } + async burnAsset(params: BurnAssetRequest): Promise> { + return this.request( + `${ApiNamespace.wallet}/burnAsset`, + params, + ).waitForEnd() + } + async sendTransaction( params: SendTransactionRequest, ): Promise> { diff --git a/ironfish/src/rpc/routes/wallet/__fixtures__/burnAsset.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/burnAsset.test.ts.fixture new file mode 100644 index 0000000000..92b28bcde8 --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/__fixtures__/burnAsset.test.ts.fixture @@ -0,0 +1,50 @@ +{ + "burnAsset with valid parameters returns the asset identifier and transaction hash": [ + { + "id": "07210445-d121-40ca-bf2a-678170b499b9", + "name": "test", + "spendingKey": "2f50950811943dadfa359934a79977fe99c3e227421565311768b680805de071", + "incomingViewKey": "0b6929dc90fb97c4809038eda9f7745fc0e130c5c729ca036b4e4cd9e8f83904", + "outgoingViewKey": "7540f7af0b729e28dd62f97a5a3e518beea9ce075309f512e0010f4294631b77", + "publicAddress": "8c56075e9efc0b0478bcbbac3cefc061f295c9073c9fc064537ce1560e65c10d" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0KtSTnDjsxRZdSHJGVZb2V4KqBXs68sJsPc67/G9KwC49mprvp04g7fOgjVH7AER3XQ7vGV9DL+XCC0Y4IyoBfxHnT3z9tDT0EQnsG4v49mke3k/0Eij/04FgduJSM+Jexv1GUvTQhgTfZjBEiXhLlIXvWpP3FPFQsJ9VhLTKZgL3qI3xmCxcilai4NSCay+Z1BFQyueeArQ+aBaSyh8kAxwqU/zaHz9X8bRR5wNxCqp30j9pgnrkd2GkTYuoqxmdPZclQPKOkItUPFSavXFn42XLM2QuLwNU+Ki8JGVA1WSpqvWmyc7ZbYbU7ro/c/RzHJFZMAnwR1y8qvd8wT3Sg3Lqu0Bq7Ht1UcwOvYDfUhj688GWaBhEykb89y1Metf8wqC60adSCuFaU8ACgEcIeweDMMIi/G83t7nyUkFgN7Kx/X4E4SOUEr+cyshwKRTaF/lp0FoNGjwLFsu4yhETIjjxnmX5pRiacsyNpOQdty38sgkQZ/V8iCKvKLlexqL+J7YuVM1fFSNbVpQkv68EIMEpXaotYn6/yLAVvG8m0jJx4+TId1byjD6RfMjOvedp4iHuC//dD+RTOkgYfaxFURtsIhD+B8gOzvdsUEQB9mJE1V+MU579VZN6Fu5Tgrrhw4MCGsa5ok3RX1r9QR2ds+CMaiuE1ax5uiVq8o6lB1X8fu3YTDkqrbhQLN8G/euQ7W3CcykA/SJJg696qHc33LWVF9NDNnihWopMSms4sT1zXnaRz15eTcDY7YW9kN2DQy6hqbfAy6EL0SSxqnJ31YobE6aRJKqgp0xYDzJFF2tzVPmcm/evQixLAYtiaHRIyMr88Qhzpusd+WCk12hf8wU7VpDWmK0DZHT3QWrHb6ltd4+TxRD0vVI/1wl8tpYHMbR4dH6+BNJo1+oFPO6++Tc/QG9AcYLjDtyWWyBy+EEFKkFRDftcSsEwpvINbUq8G3O7YXq8buqFYhY9b4k+lcq1tCw2GFCjFYHXp78CwR4vLusPO/AYfKVyQc8n8BkU3zhVg5lwQ1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCgAAAAAAAABu6XEfAZD4jGjPygQ9aKPnXybOeJJ4czWS0qCTDZpgsw7ggTYg+NjbbjAplUr2Pl2YQ8xTBR44juImh3FOe2zyDAMUro0Hrv5PFhXAw8BtxvFnHrFAIHMkDTazqYERCARgenltyTCblpQYNG2Z0SKhfMHfHVid3NmF/nDRMkn9WdIm6NKNsYGdBHvQxvBbPQy2ZBiOLCbaB4VQUBdeXo0H" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:/tQzhhH4pR+gXRHBB+4UKRom5cKAxOvgmA/+KyuCEG4=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:H1/rMpnnVEPBDixR0Ocu+HAcr9DDGjNzL06cHovIFks=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672929665631, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcWKRqNyhA3M8hv1ehyO0KXTPDo9RwpXENNRyiyIZ3tiV7idoSQhfXkmZoCfnZzOl+SHYj543IMkmGyz0OVdD0uKyRPOG+mjeQrfNE3h7dsmLfCHCIfSwoRZvulK9zWfb+VDLgehrIfHVlA+wpRCvKvRibFTVDTBQfimB3qsicQoIe9cONM8NMYT6mTHAFB9W9GMhgxa2zytVuSyc4RocEOoTp/j7TXUdAiWexZgTERyG9guG38XD9y7hbypxJbj1rnRShDo2t1VlJka8YWKCMKCq+3lDdOGOUX5n4VfV9xqany+ZdD/tv9bvzFMfNQd1HNrq+PyOcreDYdMV3cS9b0gRTofZHpc/FE8xurilyDNqjb/Fnn2iYUHxkAUcdp9cJ0qcjf2Rk15DnIfnxVHa9ecQwvW+53uP2DRJr60xHxWyOp98mSFdzTjn4QA4ywqz7nGLnBibAc2zy4yoSXtOwJZrnLpb2AxjKiuCRB4pEQxcMEI1HsYVk/sdpNduA+X3xdLgpQNGT8i2nmVSHTXvy4u8Qiv4ZSHW236v0W1LJnostd8VsZTFalwoyROMHqXNtFzW4GDFgZwC8M+GJu6uHP2Odqzv/aYTyhFTNyN46SvA4aCI6FDxWUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwtpJYkpZoOBvtaSkt9rmAn6Y3ZsRuq5sk1UVLsTfOB8jXySQF06DfsctvFVurbOPDgEW5sU85ZuTzYJgZXVgPAA==" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0KtSTnDjsxRZdSHJGVZb2V4KqBXs68sJsPc67/G9KwC49mprvp04g7fOgjVH7AER3XQ7vGV9DL+XCC0Y4IyoBfxHnT3z9tDT0EQnsG4v49mke3k/0Eij/04FgduJSM+Jexv1GUvTQhgTfZjBEiXhLlIXvWpP3FPFQsJ9VhLTKZgL3qI3xmCxcilai4NSCay+Z1BFQyueeArQ+aBaSyh8kAxwqU/zaHz9X8bRR5wNxCqp30j9pgnrkd2GkTYuoqxmdPZclQPKOkItUPFSavXFn42XLM2QuLwNU+Ki8JGVA1WSpqvWmyc7ZbYbU7ro/c/RzHJFZMAnwR1y8qvd8wT3Sg3Lqu0Bq7Ht1UcwOvYDfUhj688GWaBhEykb89y1Metf8wqC60adSCuFaU8ACgEcIeweDMMIi/G83t7nyUkFgN7Kx/X4E4SOUEr+cyshwKRTaF/lp0FoNGjwLFsu4yhETIjjxnmX5pRiacsyNpOQdty38sgkQZ/V8iCKvKLlexqL+J7YuVM1fFSNbVpQkv68EIMEpXaotYn6/yLAVvG8m0jJx4+TId1byjD6RfMjOvedp4iHuC//dD+RTOkgYfaxFURtsIhD+B8gOzvdsUEQB9mJE1V+MU579VZN6Fu5Tgrrhw4MCGsa5ok3RX1r9QR2ds+CMaiuE1ax5uiVq8o6lB1X8fu3YTDkqrbhQLN8G/euQ7W3CcykA/SJJg696qHc33LWVF9NDNnihWopMSms4sT1zXnaRz15eTcDY7YW9kN2DQy6hqbfAy6EL0SSxqnJ31YobE6aRJKqgp0xYDzJFF2tzVPmcm/evQixLAYtiaHRIyMr88Qhzpusd+WCk12hf8wU7VpDWmK0DZHT3QWrHb6ltd4+TxRD0vVI/1wl8tpYHMbR4dH6+BNJo1+oFPO6++Tc/QG9AcYLjDtyWWyBy+EEFKkFRDftcSsEwpvINbUq8G3O7YXq8buqFYhY9b4k+lcq1tCw2GFCjFYHXp78CwR4vLusPO/AYfKVyQc8n8BkU3zhVg5lwQ1taW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCgAAAAAAAABu6XEfAZD4jGjPygQ9aKPnXybOeJJ4czWS0qCTDZpgsw7ggTYg+NjbbjAplUr2Pl2YQ8xTBR44juImh3FOe2zyDAMUro0Hrv5PFhXAw8BtxvFnHrFAIHMkDTazqYERCARgenltyTCblpQYNG2Z0SKhfMHfHVid3NmF/nDRMkn9WdIm6NKNsYGdBHvQxvBbPQy2ZBiOLCbaB4VQUBdeXo0H" + } + ] + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACfVtF22Kie38DzxiKcr0WS+Msw6KWmPhP8f88mkQH4uptTeBct9A9lDTj4kyGlScl7FEgVAnnoaRqXv68sNMWavOceEp3QC9J/89pQp0+FanKVqa80xVK52he2lZzDFbE0VQPR0CMvOIW3vZUwxBSjEFS6ZXWF6GxY+pKOrzBkgP/BvYNBl1Ta3WKUmSB092UNVBFtWiTcofL+Tn8SDfcOthcz1N4n/IRHNXSJUupDO4rnCc1xWyl0zJIHcvpO7yViwyKuvNU5pOjbSBWLLUlfMY0/32pBjGqDfu8B27m+5O/DNvsk/p9iq/8zU/50bf3G0eHRyGR+pZfxoEWAq4XP7UM4YR+KUfoF0RwQfuFCkaJuXCgMTr4JgP/isrghBuBQAAALaqd7TND39v8U1J1VtdPmAuDp0fg98eTLn2llQ8ojOKzY7s/HMdVtv5VkC2U8Ei4dGh9sMK9YPspEzOkRtrZnHvXQOT41ne9O+rDG72znMpsJTV3hdjsg7xashKiOmfB7N46E/9feg6/qlmYzdZZoj/kevF2yvr00lxvgnBvrux5eNZ8GzyoJPHXI2QZM32yK+YJIHYWX04wCaUcDlOAgBX9O8wayCXAhGC4KVjLtT0q7tsFSq4AFmcFvK+TTXbzAKZT/dbREa48RNwu3rQXNvFc0Qe7YuM16jvTFdn+tiXE9SdVCaFONky+r0Y0HIbLYFwIJKxAjYcT5q2bEIckNwJ9cyPr2t14C4Zgw6Wxp098rMC8hiyzCVtuX0uww9UaQDvdBHrqkOHzh/nosxeKQPzEF7X6aokPCckoFHFYaZQS2lWmuNi7VIPRZ6ZSJm11Uea46DdUb76cF8Dk78uhjmN950dY3S/R3dZyfCMxsDrI0wKqbqaBLNeHODn3YgJxygc5r8Ctn4Lfb8WJS1JQCcEVb9iJfw6sSRgQck7HBAUjNIUgZxVhi8mqRCbcItOtx8v39Emm3wLONzSFD/gJWx0RB2T+0Xb8AnOCq397U+ngMMq/UPFUAXzWLNYJyrEtdacugDHj1O+FJLxYbu1TuIQukxKNE7SMf/ubbi3NgbdJTbsQu5oNGNpCsMSnZKuK/vVrSa3fvzPqpo1FTFVfspTL9fk7cQj4CIKanRp1KN4Y6z9nSDZABez3PPWSc+uPMDGABkKgL15gNopTD0ZElkKVjuXXr5RIWEsHAOnq14fqQZL1L2y9Au3QtVkNS3Ssrk5A1hrmwbiBs/oNwuoQit+BkKzR5Vb5AIAAAAAAAAAYWdUElOrxgoMgU8M0sP/32Rin2LWkN0k/+nv396cDB9m/c7CB8EVylJhEQj8a0qEHstULXl80pEjoac94/1yAg==" + } + ] +} \ No newline at end of file diff --git a/ironfish/src/rpc/routes/wallet/burnAsset.test.ts b/ironfish/src/rpc/routes/wallet/burnAsset.test.ts new file mode 100644 index 0000000000..a5654b40ac --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/burnAsset.test.ts @@ -0,0 +1,94 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' +import { + useAccountFixture, + useMintBlockFixture, + usePostTxFixture, +} from '../../../testUtilities' +import { createRouteTest } from '../../../testUtilities/routeTest' +import { CurrencyUtils } from '../../../utils' + +describe('burnAsset', () => { + const routeTest = createRouteTest(true) + + beforeAll(async () => { + await routeTest.node.wallet.createAccount('account', true) + }) + + describe('with no default account', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.burnAsset({ + account: 'fake-account', + assetIdentifier: '{ url: hello }', + fee: '1', + value: '1', + }), + ).rejects.toThrow('No account found with name fake-account') + }) + }) + + describe('with an invalid fee', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.burnAsset({ + account: 'account', + assetIdentifier: '{ url: hello }', + fee: '0', + value: '100', + }), + ).rejects.toThrow('Invalid transaction fee') + }) + }) + + describe('with an invalid value', () => { + it('throws a validation error', async () => { + await expect( + routeTest.client.burnAsset({ + account: 'account', + assetIdentifier: '{ url: hello }', + fee: '1', + value: '-1', + }), + ).rejects.toThrow('Invalid burn amount') + }) + }) + + describe('with valid parameters', () => { + it('returns the asset identifier and transaction hash', async () => { + const node = routeTest.node + const wallet = node.wallet + const account = await useAccountFixture(wallet) + + const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') + const assetIdentifier = asset.identifier() + const value = BigInt(10) + const mintBlock = await useMintBlockFixture({ node, account, asset, value, sequence: 3 }) + await expect(node.chain).toAddBlock(mintBlock) + await node.wallet.updateHead() + + const burnValue = BigInt(2) + const burnTransaction = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + burns: [{ assetIdentifier: asset.identifier(), value: burnValue }], + }) + jest.spyOn(wallet, 'burn').mockResolvedValueOnce(burnTransaction) + + const response = await routeTest.client.burnAsset({ + account: account.name, + assetIdentifier: assetIdentifier.toString('hex'), + fee: '1', + value: CurrencyUtils.encode(value), + }) + + expect(response.content).toEqual({ + assetIdentifier: asset.identifier().toString('hex'), + hash: burnTransaction.hash().toString('hex'), + }) + }) + }) +}) diff --git a/ironfish/src/rpc/routes/wallet/burnAsset.ts b/ironfish/src/rpc/routes/wallet/burnAsset.ts new file mode 100644 index 0000000000..3e02837c6f --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/burnAsset.ts @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import * as yup from 'yup' +import { Assert } from '../../../assert' +import { CurrencyUtils } from '../../../utils' +import { ValidationError } from '../../adapters' +import { ApiNamespace, router } from '../router' + +export interface BurnAssetRequest { + account: string + assetIdentifier: string + fee: string + value: string + expiration?: number + expirationDelta?: number +} + +export interface BurnAssetResponse { + assetIdentifier: string + hash: string +} + +export const BurnAssetRequestSchema: yup.ObjectSchema = yup + .object({ + account: yup.string().required(), + assetIdentifier: yup.string().required(), + fee: yup.string().required(), + value: yup.string().required(), + expiration: yup.number().optional(), + expirationDelta: yup.number().optional(), + }) + .defined() + +export const BurnAssetResponseSchema: yup.ObjectSchema = yup + .object({ + assetIdentifier: yup.string().required(), + hash: yup.string().required(), + }) + .defined() + +router.register( + `${ApiNamespace.wallet}/burnAsset`, + BurnAssetRequestSchema, + async (request, node): Promise => { + const account = node.wallet.getAccountByName(request.data.account) + if (!account) { + throw new ValidationError(`No account found with name ${request.data.account}`) + } + + const fee = CurrencyUtils.decode(request.data.fee) + if (fee < 1n) { + throw new ValidationError(`Invalid transaction fee, ${fee}`) + } + + const value = CurrencyUtils.decodeIron(request.data.value) + if (value <= 0) { + throw new ValidationError('Invalid burn amount') + } + + const transaction = await node.wallet.burn( + node.memPool, + account, + Buffer.from(request.data.assetIdentifier, 'hex'), + value, + fee, + request.data.expirationDelta ?? node.config.get('transactionExpirationDelta'), + request.data.expiration, + ) + Assert.isEqual(transaction.burns.length, 1) + const burn = transaction.burns[0] + + request.end({ + assetIdentifier: burn.assetIdentifier.toString('hex'), + hash: transaction.hash().toString('hex'), + }) + }, +) diff --git a/ironfish/src/rpc/routes/wallet/index.ts b/ironfish/src/rpc/routes/wallet/index.ts index 032b9e69ac..9305f7a160 100644 --- a/ironfish/src/rpc/routes/wallet/index.ts +++ b/ironfish/src/rpc/routes/wallet/index.ts @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +export * from './burnAsset' export * from './create' export * from './exportAccount' export * from './getAccounts' @@ -12,9 +13,9 @@ export * from './getPublicKey' export * from './getStatus' export * from './getTransaction' export * from './getTransactions' -export * from './sendTransaction' export * from './importAccount' export * from './removeAccount' export * from './rescanAccount' export * from './sendTransaction' +export * from './sendTransaction' export * from './useAccount' From 70c37c421ec570b4409c1365106fc06354a562e0 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:12:29 -0500 Subject: [PATCH 40/56] feat(cli): Add `wallet:burn` CLI command (#2834) * feat(ironfish): Add RPC route for `wallet/burnAsset` * feat(cli): Add `wallet:burn` CLI command --- ironfish-cli/src/commands/wallet/burn.ts | 104 +++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 ironfish-cli/src/commands/wallet/burn.ts diff --git a/ironfish-cli/src/commands/wallet/burn.ts b/ironfish-cli/src/commands/wallet/burn.ts new file mode 100644 index 0000000000..5b11c8efa1 --- /dev/null +++ b/ironfish-cli/src/commands/wallet/burn.ts @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { CurrencyUtils } from '@ironfish/sdk' +import { CliUx, Flags } from '@oclif/core' +import { IronfishCommand } from '../../command' +import { RemoteFlags } from '../../flags' +import { ProgressBar } from '../../types' + +export class Burn extends IronfishCommand { + static description = 'Burn tokens and decrease supply for a given asset' + + static examples = ['$ ironfish wallet:burn -i "assetIdentifier" -a 1000 -f myaccount -o 1'] + + static flags = { + ...RemoteFlags, + account: Flags.string({ + char: 'f', + description: 'The account to burn from', + required: true, + }), + fee: Flags.string({ + char: 'o', + description: 'The fee amount in IRON', + required: true, + }), + amount: Flags.string({ + char: 'a', + description: 'Amount of coins to burn', + required: true, + }), + assetIdentifier: Flags.string({ + char: 'i', + description: 'Identifier for the asset', + required: true, + }), + } + + async start(): Promise { + const { flags } = await this.parse(Burn) + const client = await this.sdk.connectRpc(false, true) + + const status = await client.getNodeStatus() + if (!status.content.blockchain.synced) { + this.log( + `Your node must be synced with the Iron Fish network to send a transaction. Please try again later`, + ) + this.exit(1) + } + + const bar = CliUx.ux.progress({ + barCompleteChar: '\u2588', + barIncompleteChar: '\u2591', + format: 'Creating the transaction: [{bar}] {percentage}% | ETA: {eta}s', + }) as ProgressBar + + bar.start() + + let value = 0 + const timer = setInterval(() => { + value++ + bar.update(value) + if (value >= bar.getTotal()) { + bar.stop() + } + }, 1000) + + const stopProgressBar = () => { + clearInterval(timer) + bar.update(100) + bar.stop() + } + + try { + const result = await client.burnAsset({ + account: flags.account, + assetIdentifier: flags.assetIdentifier, + fee: flags.fee, + value: flags.amount, + }) + + stopProgressBar() + + const response = result.content + this.log(` + Burned asset ${response.assetIdentifier} from ${flags.account} + Value: ${flags.amount} + + Transaction Hash: ${response.hash} + Transaction fee: ${CurrencyUtils.renderIron(flags.fee, true)} + + Find the transaction on https://explorer.ironfish.network/transaction/${ + response.hash + } (it can take a few minutes before the transaction appears in the Explorer)`) + } catch (error: unknown) { + stopProgressBar() + this.log(`An error occurred while burning the asset.`) + if (error instanceof Error) { + this.error(error.message) + } + this.exit(2) + } + } +} From 84e37b7af63431b1c334d849ae7383e6332063d5 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:29:59 -0500 Subject: [PATCH 41/56] refactor(ironfish): Move mint asset under wallet namespace (#2831) --- ironfish/src/rpc/clients/client.ts | 7 +++++-- ironfish/src/rpc/routes/assets/index.ts | 4 ---- ironfish/src/rpc/routes/index.ts | 1 - ironfish/src/rpc/routes/router.ts | 1 - .../__fixtures__/mintAsset.test.ts.fixture} | 0 ironfish/src/rpc/routes/wallet/index.ts | 1 + .../{assets/mint.test.ts => wallet/mintAsset.test.ts} | 0 .../src/rpc/routes/{assets/mint.ts => wallet/mintAsset.ts} | 2 +- 8 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 ironfish/src/rpc/routes/assets/index.ts rename ironfish/src/rpc/routes/{assets/__fixtures__/mint.test.ts.fixture => wallet/__fixtures__/mintAsset.test.ts.fixture} (100%) rename ironfish/src/rpc/routes/{assets/mint.test.ts => wallet/mintAsset.test.ts} (100%) rename ironfish/src/rpc/routes/{assets/mint.ts => wallet/mintAsset.ts} (98%) diff --git a/ironfish/src/rpc/clients/client.ts b/ironfish/src/rpc/clients/client.ts index 3f7efab8cd..b5f16afb70 100644 --- a/ironfish/src/rpc/clients/client.ts +++ b/ironfish/src/rpc/clients/client.ts @@ -62,7 +62,6 @@ import { UseAccountRequest, UseAccountResponse, } from '../routes' -import { MintAssetRequest, MintAssetResponse } from '../routes/assets/mint' import { EstimateFeeRatesRequest, EstimateFeeRatesResponse, @@ -86,6 +85,7 @@ import { BurnAssetRequest, BurnAssetResponse } from '../routes/wallet/burnAsset' import { ExportAccountRequest, ExportAccountResponse } from '../routes/wallet/exportAccount' import { GetAccountStatusRequest, GetAccountStatusResponse } from '../routes/wallet/getStatus' import { ImportAccountRequest, ImportAccountResponse } from '../routes/wallet/importAccount' +import { MintAssetRequest, MintAssetResponse } from '../routes/wallet/mintAsset' import { RemoveAccountRequest, RemoveAccountResponse } from '../routes/wallet/removeAccount' import { RescanAccountRequest, RescanAccountResponse } from '../routes/wallet/rescanAccount' @@ -332,7 +332,10 @@ export abstract class RpcClient { } async mintAsset(params: MintAssetRequest): Promise> { - return this.request(`${ApiNamespace.asset}/mint`, params).waitForEnd() + return this.request( + `${ApiNamespace.wallet}/mintAsset`, + params, + ).waitForEnd() } async burnAsset(params: BurnAssetRequest): Promise> { diff --git a/ironfish/src/rpc/routes/assets/index.ts b/ironfish/src/rpc/routes/assets/index.ts deleted file mode 100644 index b16a573275..0000000000 --- a/ironfish/src/rpc/routes/assets/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -export * from './mint' diff --git a/ironfish/src/rpc/routes/index.ts b/ironfish/src/rpc/routes/index.ts index 167802cafb..ad3d630a6f 100644 --- a/ironfish/src/rpc/routes/index.ts +++ b/ironfish/src/rpc/routes/index.ts @@ -1,7 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -export * from './assets' export * from './wallet' export * from './config' export * from './chain' diff --git a/ironfish/src/rpc/routes/router.ts b/ironfish/src/rpc/routes/router.ts index 523cd379c4..9db651a8b8 100644 --- a/ironfish/src/rpc/routes/router.ts +++ b/ironfish/src/rpc/routes/router.ts @@ -11,7 +11,6 @@ import { RpcRequest } from '../request' import { RpcServer } from '../server' export enum ApiNamespace { - asset = 'asset', chain = 'chain', config = 'config', event = 'event', diff --git a/ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/mintAsset.test.ts.fixture similarity index 100% rename from ironfish/src/rpc/routes/assets/__fixtures__/mint.test.ts.fixture rename to ironfish/src/rpc/routes/wallet/__fixtures__/mintAsset.test.ts.fixture diff --git a/ironfish/src/rpc/routes/wallet/index.ts b/ironfish/src/rpc/routes/wallet/index.ts index 9305f7a160..c38586b69a 100644 --- a/ironfish/src/rpc/routes/wallet/index.ts +++ b/ironfish/src/rpc/routes/wallet/index.ts @@ -14,6 +14,7 @@ export * from './getStatus' export * from './getTransaction' export * from './getTransactions' export * from './importAccount' +export * from './mintAsset' export * from './removeAccount' export * from './rescanAccount' export * from './sendTransaction' diff --git a/ironfish/src/rpc/routes/assets/mint.test.ts b/ironfish/src/rpc/routes/wallet/mintAsset.test.ts similarity index 100% rename from ironfish/src/rpc/routes/assets/mint.test.ts rename to ironfish/src/rpc/routes/wallet/mintAsset.test.ts diff --git a/ironfish/src/rpc/routes/assets/mint.ts b/ironfish/src/rpc/routes/wallet/mintAsset.ts similarity index 98% rename from ironfish/src/rpc/routes/assets/mint.ts rename to ironfish/src/rpc/routes/wallet/mintAsset.ts index c1f2444789..540554b524 100644 --- a/ironfish/src/rpc/routes/assets/mint.ts +++ b/ironfish/src/rpc/routes/wallet/mintAsset.ts @@ -42,7 +42,7 @@ export const MintAssetResponseSchema: yup.ObjectSchema = yup .defined() router.register( - `${ApiNamespace.asset}/mint`, + `${ApiNamespace.wallet}/mintAsset`, MintAssetRequestSchema, async (request, node): Promise => { const account = node.wallet.getAccountByName(request.data.account) From 57e335a0a026b9dea7b0c9fecb39c064375e5b75 Mon Sep 17 00:00:00 2001 From: mat-if <97762857+mat-if@users.noreply.github.com> Date: Fri, 6 Jan 2023 09:32:43 -0700 Subject: [PATCH 42/56] feat(rust): use `checked_add` for `ValueBalance` (#2840) Right now, its possible to add enough value to a transaction via mints or spends such that it would overflow the `i64` type in the `ValueBalance` struct. By using `checked_add`, we get some cleaner error handling around this logic. Note that this doesn't functionally change much, it's just more explicit error handling. As a future improvement, we could use an arbitrarily large value type for `ValueBalance` like `i128`, and change the logic on `Transaction::post` to loop over the values and create multiple change notes, allowing value transfers of greater than `u64::MAX`, if we ever needed to. --- .../src/structs/transaction.rs | 28 +++++-- ironfish-rust/src/transaction/mod.rs | 34 +++++--- ironfish-rust/src/transaction/tests.rs | 28 +++---- .../src/transaction/value_balances.rs | 81 +++++++++++++++---- 4 files changed, 125 insertions(+), 46 deletions(-) diff --git a/ironfish-rust-nodejs/src/structs/transaction.rs b/ironfish-rust-nodejs/src/structs/transaction.rs index 63f26ca611..6400f36d4b 100644 --- a/ironfish-rust-nodejs/src/structs/transaction.rs +++ b/ironfish-rust-nodejs/src/structs/transaction.rs @@ -169,19 +169,27 @@ impl NativeTransaction { /// Create a proof of a new note owned by the recipient in this transaction. #[napi] - pub fn receive(&mut self, note: &NativeNote) { - self.transaction.add_output(note.note.clone()); + pub fn receive(&mut self, note: &NativeNote) -> Result<()> { + self.transaction + .add_output(note.note.clone()) + .map_err(to_napi_err)?; + + Ok(()) } /// Spend the note owned by spender_hex_key at the given witness location. #[napi] - pub fn spend(&mut self, env: Env, note: &NativeNote, witness: Object) { + pub fn spend(&mut self, env: Env, note: &NativeNote, witness: Object) -> Result<()> { let w = JsWitness { cx: RefCell::new(env), obj: witness, }; - self.transaction.add_spend(note.note.clone(), &w); + self.transaction + .add_spend(note.note.clone(), &w) + .map_err(to_napi_err)?; + + Ok(()) } /// return the sender of the transaction @@ -192,9 +200,13 @@ impl NativeTransaction { /// Mint a new asset with a given value as part of this transaction. #[napi] - pub fn mint(&mut self, asset: &NativeAsset, value: BigInt) { + pub fn mint(&mut self, asset: &NativeAsset, value: BigInt) -> Result<()> { let value_u64 = value.get_u64().1; - self.transaction.add_mint(asset.asset, value_u64) + self.transaction + .add_mint(asset.asset, value_u64) + .map_err(to_napi_err)?; + + Ok(()) } /// Burn some supply of a given asset and value as part of this transaction. @@ -206,7 +218,9 @@ impl NativeTransaction { .try_into() .map_err(to_napi_err)?; let value_u64 = value.get_u64().1; - self.transaction.add_burn(asset_identifier, value_u64); + self.transaction + .add_burn(asset_identifier, value_u64) + .map_err(to_napi_err)?; Ok(()) } diff --git a/ironfish-rust/src/transaction/mod.rs b/ironfish-rust/src/transaction/mod.rs index c453a317f0..b44268dd04 100644 --- a/ironfish-rust/src/transaction/mod.rs +++ b/ironfish-rust/src/transaction/mod.rs @@ -133,33 +133,49 @@ impl ProposedTransaction { } /// Spend the note owned by spender_key at the given witness location. - pub fn add_spend(&mut self, note: Note, witness: &dyn WitnessTrait) { + pub fn add_spend( + &mut self, + note: Note, + witness: &dyn WitnessTrait, + ) -> Result<(), IronfishError> { self.value_balances - .add(¬e.asset_identifier(), note.value() as i64); + .add(¬e.asset_identifier(), note.value() as i64)?; self.spends.push(SpendBuilder::new(note, witness)); + + Ok(()) } /// Create a proof of a new note owned by the recipient in this /// transaction. - pub fn add_output(&mut self, note: Note) { + pub fn add_output(&mut self, note: Note) -> Result<(), IronfishError> { self.value_balances - .subtract(¬e.asset_identifier(), note.value() as i64); + .subtract(¬e.asset_identifier(), note.value() as i64)?; self.outputs.push(OutputBuilder::new(note)); + + Ok(()) } - pub fn add_mint(&mut self, asset: Asset, value: u64) { - self.value_balances.add(asset.identifier(), value as i64); + pub fn add_mint(&mut self, asset: Asset, value: u64) -> Result<(), IronfishError> { + self.value_balances.add(asset.identifier(), value as i64)?; self.mints.push(MintBuilder::new(asset, value)); + + Ok(()) } - pub fn add_burn(&mut self, asset_identifier: AssetIdentifier, value: u64) { + pub fn add_burn( + &mut self, + asset_identifier: AssetIdentifier, + value: u64, + ) -> Result<(), IronfishError> { self.value_balances - .subtract(&asset_identifier, value as i64); + .subtract(&asset_identifier, value as i64)?; self.burns.push(BurnBuilder::new(asset_identifier, value)); + + Ok(()) } /// Post the transaction. This performs a bit of validation, and signs @@ -206,7 +222,7 @@ impl ProposedTransaction { } for change_note in change_notes { - self.add_output(change_note); + self.add_output(change_note)?; } self._partial_post() diff --git a/ironfish-rust/src/transaction/tests.rs b/ironfish-rust/src/transaction/tests.rs index 49428d0a2c..eaee113da0 100644 --- a/ironfish-rust/src/transaction/tests.rs +++ b/ironfish-rust/src/transaction/tests.rs @@ -59,23 +59,23 @@ fn test_transaction() { let mut transaction = ProposedTransaction::new(spender_key); // Spend - transaction.add_spend(in_note, &witness); + transaction.add_spend(in_note, &witness).unwrap(); assert_eq!(transaction.spends.len(), 1); // Output - transaction.add_output(out_note); + transaction.add_output(out_note).unwrap(); assert_eq!(transaction.outputs.len(), 1); // Mint 5 tokens - transaction.add_mint(asset, mint_value); + transaction.add_mint(asset, mint_value).unwrap(); assert_eq!(transaction.mints.len(), 1); // Output 2 minted tokens to receiver - transaction.add_output(mint_out_note); + transaction.add_output(mint_out_note).unwrap(); assert_eq!(transaction.outputs.len(), 2); // Burn 2 tokens, leaving 1 token left to be put into a change note - transaction.add_burn(asset.identifier, burn_value); + transaction.add_burn(asset.identifier, burn_value).unwrap(); assert_eq!(transaction.burns.len(), 1); let public_transaction = transaction @@ -155,9 +155,9 @@ fn test_transaction_simple() { let witness = make_fake_witness(&in_note); let mut transaction = ProposedTransaction::new(spender_key); - transaction.add_spend(in_note, &witness); + transaction.add_spend(in_note, &witness).unwrap(); assert_eq!(transaction.spends.len(), 1); - transaction.add_output(out_note); + transaction.add_output(out_note).unwrap(); assert_eq!(transaction.outputs.len(), 1); let public_transaction = transaction @@ -193,7 +193,7 @@ fn test_miners_fee() { spender_key.public_address(), ); let mut transaction = ProposedTransaction::new(spender_key); - transaction.add_output(out_note); + transaction.add_output(out_note).unwrap(); let posted_transaction = transaction .post_miners_fee() .expect("it is a valid miner's fee"); @@ -234,9 +234,9 @@ fn test_transaction_signature() { ); let witness = make_fake_witness(&in_note); - transaction.add_spend(in_note, &witness); + transaction.add_spend(in_note, &witness).unwrap(); - transaction.add_output(out_note); + transaction.add_output(out_note).unwrap(); transaction.set_expiration(1337); @@ -278,8 +278,8 @@ fn test_transaction_created_with_version_1() { let witness = make_fake_witness(&in_note); let mut transaction = ProposedTransaction::new(spender_key); - transaction.add_spend(in_note, &witness); - transaction.add_output(out_note); + transaction.add_spend(in_note, &witness).unwrap(); + transaction.add_output(out_note).unwrap(); assert_eq!(transaction.version, 1); @@ -318,8 +318,8 @@ fn test_transaction_version_is_checked() { let witness = make_fake_witness(&in_note); let mut transaction = ProposedTransaction::new(spender_key); - transaction.add_spend(in_note, &witness); - transaction.add_output(out_note); + transaction.add_spend(in_note, &witness).unwrap(); + transaction.add_output(out_note).unwrap(); transaction.version = 2; diff --git a/ironfish-rust/src/transaction/value_balances.rs b/ironfish-rust/src/transaction/value_balances.rs index 226daa3485..a57e287f9e 100644 --- a/ironfish-rust/src/transaction/value_balances.rs +++ b/ironfish-rust/src/transaction/value_balances.rs @@ -3,7 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::collections::{hash_map, HashMap}; -use crate::assets::asset::{AssetIdentifier, NATIVE_ASSET}; +use crate::{ + assets::asset::{AssetIdentifier, NATIVE_ASSET}, + errors::IronfishError, +}; pub struct ValueBalances { values: HashMap, @@ -18,14 +21,34 @@ impl ValueBalances { ValueBalances { values: hash_map } } - pub fn add(&mut self, asset_identifier: &AssetIdentifier, value: i64) { + pub fn add( + &mut self, + asset_identifier: &AssetIdentifier, + value: i64, + ) -> Result<(), IronfishError> { let current_value = self.values.entry(*asset_identifier).or_insert(0); - *current_value += value + let new_value = current_value + .checked_add(value) + .ok_or(IronfishError::InvalidBalance)?; + + *current_value = new_value; + + Ok(()) } - pub fn subtract(&mut self, asset_identifier: &AssetIdentifier, value: i64) { + pub fn subtract( + &mut self, + asset_identifier: &AssetIdentifier, + value: i64, + ) -> Result<(), IronfishError> { let current_value = self.values.entry(*asset_identifier).or_insert(0); - *current_value -= value + let new_value = current_value + .checked_sub(value) + .ok_or(IronfishError::InvalidBalance)?; + + *current_value = new_value; + + Ok(()) } pub fn iter(&self) -> hash_map::Iter { @@ -57,8 +80,8 @@ mod test { fn test_value_balances_fee() { let mut vb = ValueBalances::new(); - vb.add(&NATIVE_ASSET, 5); - vb.subtract(&NATIVE_ASSET, 2); + vb.add(&NATIVE_ASSET, 5).unwrap(); + vb.subtract(&NATIVE_ASSET, 2).unwrap(); assert_eq!(*vb.fee(), 3); } @@ -67,19 +90,45 @@ mod test { fn test_value_balances_multiple_assets() { let mut vb = ValueBalances::new(); - let asset_two = [1u8; 32]; - let asset_three = [2u8; 32]; + let asset_one = [1u8; 32]; + let asset_two = [2u8; 32]; - vb.add(&NATIVE_ASSET, 5); - vb.subtract(&NATIVE_ASSET, 3); + vb.add(&NATIVE_ASSET, 5).unwrap(); + vb.subtract(&NATIVE_ASSET, 3).unwrap(); - vb.add(&asset_two, 6); - vb.subtract(&asset_two, 2); + vb.add(&asset_one, 6).unwrap(); + vb.subtract(&asset_one, 2).unwrap(); - vb.subtract(&asset_three, 10); + vb.subtract(&asset_two, 10).unwrap(); assert_eq!(*vb.fee(), 2); - assert_eq!(*vb.values.get(&asset_two).unwrap(), 4); - assert_eq!(*vb.values.get(&asset_three).unwrap(), -10); + assert_eq!(*vb.values.get(&asset_one).unwrap(), 4); + assert_eq!(*vb.values.get(&asset_two).unwrap(), -10); + } + + #[test] + fn test_value_balances_checks_overflows_add() { + let mut vb = ValueBalances::new(); + + let asset = [1u8; 32]; + + // First value add - does not overflow + vb.add(&asset, i64::MAX - 1).unwrap(); + + // Second value add - overflows + assert!(vb.add(&asset, 100).is_err()); + } + + #[test] + fn test_value_balances_checks_overflows_sub() { + let mut vb = ValueBalances::new(); + + let asset = [1u8; 32]; + + // First value sub - does not overflow + vb.subtract(&asset, i64::MAX - 1).unwrap(); + + // Second value sub - overflows + assert!(vb.subtract(&asset, 100).is_err()); } } From b39f5541e3450a11769a24364385c1c5598e80e3 Mon Sep 17 00:00:00 2001 From: Rohan Jadvani <5459049+rohanjadvani@users.noreply.github.com> Date: Fri, 6 Jan 2023 12:05:04 -0500 Subject: [PATCH 43/56] refactor(cli,ironfish,rust,rust-nodejs): asset identifier -> asset id (#2837) * refactor(cli,ironfish,rust,rust-nodejs): asset identifier -> asset id * refactor(cli): `yarn lint:fix` --- ironfish-cli/src/commands/accounts/balance.ts | 30 ++-- ironfish-cli/src/commands/accounts/notes.ts | 2 +- ironfish-cli/src/commands/accounts/send.ts | 12 +- ironfish-cli/src/commands/chain/asset.ts | 8 +- ironfish-cli/src/commands/service/faucet.ts | 2 +- ironfish-cli/src/commands/wallet/burn.ts | 8 +- ironfish-cli/src/commands/wallet/mint.ts | 2 +- ironfish-rust-nodejs/index.d.ts | 12 +- ironfish-rust-nodejs/index.js | 4 +- ironfish-rust-nodejs/src/structs/asset.rs | 12 +- ironfish-rust-nodejs/src/structs/note.rs | 20 +-- .../src/structs/transaction.rs | 11 +- ironfish-rust-nodejs/tests/demo.test.slow.ts | 6 +- ironfish-rust/src/assets/asset.rs | 24 +-- ironfish-rust/src/note.rs | 2 +- ironfish-rust/src/transaction/burns.rs | 37 ++-- ironfish-rust/src/transaction/mod.rs | 28 ++- ironfish-rust/src/transaction/tests.rs | 2 +- .../src/transaction/value_balances.rs | 12 +- ironfish-zkp/src/circuits/mint_asset.rs | 8 +- ironfish-zkp/src/constants.rs | 4 +- .../src/blockchain/blockchain.test.perf.ts | 4 +- ironfish/src/blockchain/blockchain.test.ts | 56 +++--- ironfish/src/blockchain/blockchain.ts | 42 ++--- .../src/blockchain/database/assets.test.ts | 2 +- ironfish/src/blockchain/database/assets.ts | 12 +- ironfish/src/genesis/genesis.test.slow.ts | 10 +- ironfish/src/genesis/makeGenesisBlock.ts | 6 +- ironfish/src/memPool/feeEstimator.test.ts | 2 +- ironfish/src/memPool/feeEstimator.ts | 2 +- ironfish/src/mining/poolShares.ts | 2 +- ironfish/src/primitives/burnDescription.ts | 2 +- ironfish/src/primitives/note.ts | 10 +- .../src/primitives/rawTransaction.test.ts | 20 +-- ironfish/src/primitives/rawTransaction.ts | 12 +- .../src/primitives/transaction.test.slow.ts | 4 +- ironfish/src/primitives/transaction.ts | 6 +- .../src/rpc/routes/chain/getAsset.test.ts | 6 +- ironfish/src/rpc/routes/chain/getAsset.ts | 22 +-- ironfish/src/rpc/routes/chain/getBlock.ts | 10 +- .../src/rpc/routes/wallet/burnAsset.test.ts | 14 +- ironfish/src/rpc/routes/wallet/burnAsset.ts | 12 +- ironfish/src/rpc/routes/wallet/getBalance.ts | 18 +- ironfish/src/rpc/routes/wallet/getNotes.ts | 8 +- .../src/rpc/routes/wallet/mintAsset.test.ts | 2 +- ironfish/src/rpc/routes/wallet/mintAsset.ts | 6 +- .../rpc/routes/wallet/sendTransaction.test.ts | 10 +- .../src/rpc/routes/wallet/sendTransaction.ts | 28 +-- ironfish/src/strategy.test.slow.ts | 8 +- ironfish/src/testUtilities/fixtures.ts | 14 +- .../src/testUtilities/helpers/transaction.ts | 6 +- ironfish/src/utils/asset.ts | 4 +- ironfish/src/utils/currency.ts | 20 +-- ironfish/src/wallet/account.test.ts | 12 +- ironfish/src/wallet/account.ts | 49 +++-- ironfish/src/wallet/errors.ts | 4 +- ironfish/src/wallet/wallet.test.slow.ts | 168 ++++++------------ ironfish/src/wallet/wallet.test.ts | 48 ++--- ironfish/src/wallet/wallet.ts | 42 ++--- .../wallet/walletdb/transactionValue.test.ts | 12 +- .../src/wallet/walletdb/transactionValue.ts | 12 +- ironfish/src/wallet/walletdb/walletdb.ts | 18 +- ironfish/src/workerPool/pool.ts | 2 +- .../src/workerPool/tasks/createMinersFee.ts | 2 +- .../tasks/createTransaction.test.slow.ts | 18 +- .../src/workerPool/tasks/createTransaction.ts | 37 ++-- 66 files changed, 456 insertions(+), 594 deletions(-) diff --git a/ironfish-cli/src/commands/accounts/balance.ts b/ironfish-cli/src/commands/accounts/balance.ts index a7f9ee135a..cacc092b1a 100644 --- a/ironfish-cli/src/commands/accounts/balance.ts +++ b/ironfish-cli/src/commands/accounts/balance.ts @@ -27,7 +27,7 @@ export class BalanceCommand extends IronfishCommand { required: false, description: 'Minimum number of blocks confirmations for a note', }), - assetIdentifier: Flags.string({ + assetId: Flags.string({ required: false, description: 'Asset identifier to check the balance for', }), @@ -50,42 +50,32 @@ export class BalanceCommand extends IronfishCommand { const response = await client.getAccountBalance({ account, - assetIdentifier: flags.assetIdentifier, + assetId: flags.assetId, minimumBlockConfirmations: flags.confirmations, }) - const assetIdentifier = response.content.assetIdentifier + const assetId = response.content.assetId if (flags.explain) { - this.explainBalance(response.content, assetIdentifier) + this.explainBalance(response.content, assetId) return } if (flags.all) { this.log(`Account: ${response.content.account}`) this.log( - `Balance: ${CurrencyUtils.renderIron( - response.content.confirmed, - true, - assetIdentifier, - )}`, + `Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetId)}`, ) this.log( - `Unconfirmed: ${CurrencyUtils.renderIron( - response.content.unconfirmed, - true, - assetIdentifier, - )}`, + `Unconfirmed: ${CurrencyUtils.renderIron(response.content.unconfirmed, true, assetId)}`, ) return } this.log(`Account: ${response.content.account}`) - this.log( - `Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetIdentifier)}`, - ) + this.log(`Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetId)}`) } - explainBalance(response: GetBalanceResponse, assetIdentifier: string): void { + explainBalance(response: GetBalanceResponse, assetId: string): void { const unconfirmed = CurrencyUtils.decode(response.unconfirmed) const confirmed = CurrencyUtils.decode(response.confirmed) @@ -95,7 +85,7 @@ export class BalanceCommand extends IronfishCommand { this.log('') this.log(`Your balance is made of notes on the chain that are safe to spend`) - this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true, assetIdentifier)}`) + this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true, assetId)}`) this.log('') this.log( @@ -103,6 +93,6 @@ export class BalanceCommand extends IronfishCommand { unconfirmedDelta, )} are on the chain within ${response.minimumBlockConfirmations.toString()} blocks of the head`, ) - this.log(`Unconfirmed: ${CurrencyUtils.renderIron(unconfirmed, true, assetIdentifier)}`) + this.log(`Unconfirmed: ${CurrencyUtils.renderIron(unconfirmed, true, assetId)}`) } } diff --git a/ironfish-cli/src/commands/accounts/notes.ts b/ironfish-cli/src/commands/accounts/notes.ts index cc9d1331da..94ada67c89 100644 --- a/ironfish-cli/src/commands/accounts/notes.ts +++ b/ironfish-cli/src/commands/accounts/notes.ts @@ -43,7 +43,7 @@ export class NotesCommand extends IronfishCommand { assetName: { header: 'Asset Name', }, - assetIdentifier: { + assetId: { header: 'Asset Id', }, memo: { diff --git a/ironfish-cli/src/commands/accounts/send.ts b/ironfish-cli/src/commands/accounts/send.ts index ec78420bff..3a1070766d 100644 --- a/ironfish-cli/src/commands/accounts/send.ts +++ b/ironfish-cli/src/commands/accounts/send.ts @@ -53,7 +53,7 @@ export class Send extends IronfishCommand { description: 'The priority level for transaction fee estimation.', options: ['low', 'medium', 'high'], }), - assetIdentifier: Flags.string({ + assetId: Flags.string({ char: 'i', description: 'The identifier for the asset to use when sending', }), @@ -82,10 +82,10 @@ export class Send extends IronfishCommand { amount = CurrencyUtils.decodeIron(flags.amount) } - const assetIdentifier = flags.assetIdentifier + const assetId = flags.assetId if (amount === null) { - const response = await client.getAccountBalance({ account: from, assetIdentifier }) + const response = await client.getAccountBalance({ account: from, assetId }) const input = await CliUx.ux.prompt( `Enter the amount (balance: ${CurrencyUtils.renderIron(response.content.confirmed)})`, @@ -186,7 +186,7 @@ You are about to send: ${CurrencyUtils.renderIron( amount, true, - assetIdentifier, + assetId, )} plus a transaction fee of ${CurrencyUtils.renderIron( fee, true, @@ -235,7 +235,7 @@ ${CurrencyUtils.renderIron( publicAddress: to, amount: CurrencyUtils.encode(amount), memo, - assetIdentifier, + assetId, }, ], fee: CurrencyUtils.encode(fee), @@ -247,7 +247,7 @@ ${CurrencyUtils.renderIron( const transaction = result.content const recipients = transaction.receives.map((receive) => receive.publicAddress).join(', ') this.log(` -Sending ${CurrencyUtils.renderIron(amount, true, assetIdentifier)} to ${recipients} from ${ +Sending ${CurrencyUtils.renderIron(amount, true, assetId)} to ${recipients} from ${ transaction.fromAccountName } Transaction Hash: ${transaction.hash} diff --git a/ironfish-cli/src/commands/chain/asset.ts b/ironfish-cli/src/commands/chain/asset.ts index c5b74b2361..cb947bfb29 100644 --- a/ironfish-cli/src/commands/chain/asset.ts +++ b/ironfish-cli/src/commands/chain/asset.ts @@ -23,18 +23,18 @@ export default class Asset extends IronfishCommand { async start(): Promise { const { args } = await this.parse(Asset) - Assert.isString(args.identifier) - const assetIdentifier = args.identifier + Assert.isString(args.id) + const assetId = args.id const client = await this.sdk.connectRpc() - const data = await client.getAsset({ identifier: assetIdentifier }) + const data = await client.getAsset({ id: assetId }) this.log(`Name: ${BufferUtils.toHuman(Buffer.from(data.content.name, 'hex'))}`) this.log(`Metadata: ${BufferUtils.toHuman(Buffer.from(data.content.metadata, 'hex'))}`) this.log(`Owner: ${data.content.owner}`) this.log(`Supply: ${data.content.supply}`) this.log(`Nonce: ${data.content.nonce}`) - this.log(`Identifier: ${data.content.identifier}`) + this.log(`Identifier: ${data.content.id}`) this.log(`Transaction Created: ${data.content.createdTransactionHash}`) } } diff --git a/ironfish-cli/src/commands/service/faucet.ts b/ironfish-cli/src/commands/service/faucet.ts index e91979ad74..171a8a074c 100644 --- a/ironfish-cli/src/commands/service/faucet.ts +++ b/ironfish-cli/src/commands/service/faucet.ts @@ -177,7 +177,7 @@ export default class Faucet extends IronfishCommand { publicAddress: ft.public_key, amount: BigInt(FAUCET_AMOUNT).toString(), memo: `Faucet for ${ft.id}`, - assetIdentifier: Asset.nativeIdentifier().toString('hex'), + assetId: Asset.nativeId().toString('hex'), } }) diff --git a/ironfish-cli/src/commands/wallet/burn.ts b/ironfish-cli/src/commands/wallet/burn.ts index 5b11c8efa1..8252721653 100644 --- a/ironfish-cli/src/commands/wallet/burn.ts +++ b/ironfish-cli/src/commands/wallet/burn.ts @@ -10,7 +10,7 @@ import { ProgressBar } from '../../types' export class Burn extends IronfishCommand { static description = 'Burn tokens and decrease supply for a given asset' - static examples = ['$ ironfish wallet:burn -i "assetIdentifier" -a 1000 -f myaccount -o 1'] + static examples = ['$ ironfish wallet:burn -i "assetId" -a 1000 -f myaccount -o 1'] static flags = { ...RemoteFlags, @@ -29,7 +29,7 @@ export class Burn extends IronfishCommand { description: 'Amount of coins to burn', required: true, }), - assetIdentifier: Flags.string({ + assetId: Flags.string({ char: 'i', description: 'Identifier for the asset', required: true, @@ -74,7 +74,7 @@ export class Burn extends IronfishCommand { try { const result = await client.burnAsset({ account: flags.account, - assetIdentifier: flags.assetIdentifier, + assetId: flags.assetId, fee: flags.fee, value: flags.amount, }) @@ -83,7 +83,7 @@ export class Burn extends IronfishCommand { const response = result.content this.log(` - Burned asset ${response.assetIdentifier} from ${flags.account} + Burned asset ${response.assetId} from ${flags.account} Value: ${flags.amount} Transaction Hash: ${response.hash} diff --git a/ironfish-cli/src/commands/wallet/mint.ts b/ironfish-cli/src/commands/wallet/mint.ts index 24ccc9c569..7568c1884f 100644 --- a/ironfish-cli/src/commands/wallet/mint.ts +++ b/ironfish-cli/src/commands/wallet/mint.ts @@ -100,7 +100,7 @@ export class Mint extends IronfishCommand { const response = result.content this.log(` Minted asset ${name} from ${account} - Asset Identifier: ${response.assetIdentifier} + Asset Identifier: ${response.assetId} Value: ${amount} Transaction Hash: ${response.hash} diff --git a/ironfish-rust-nodejs/index.d.ts b/ironfish-rust-nodejs/index.d.ts index 6ea4d1bed3..15877f5a49 100644 --- a/ironfish-rust-nodejs/index.d.ts +++ b/ironfish-rust-nodejs/index.d.ts @@ -12,7 +12,7 @@ export interface BoxedMessage { } export function boxMessage(plaintext: string, senderSecretKey: Uint8Array, recipientPublicKey: string): BoxedMessage export function unboxMessage(boxedMessage: string, nonce: string, senderPublicKey: string, recipientSecretKey: Uint8Array): string -export const ASSET_IDENTIFIER_LENGTH: number +export const ASSET_ID_LENGTH: number export const ASSET_METADATA_LENGTH: number export const ASSET_NAME_LENGTH: number export const ASSET_OWNER_LENGTH: number @@ -64,8 +64,8 @@ export class Asset { name(): Buffer nonce(): number owner(): Buffer - static nativeIdentifier(): Buffer - identifier(): Buffer + static nativeId(): Buffer + id(): Buffer serialize(): Buffer static deserialize(jsBytes: Buffer): NativeAsset } @@ -87,7 +87,7 @@ export class NoteEncrypted { } export type NativeNote = Note export class Note { - constructor(owner: string, value: bigint, memo: string, assetIdentifier: Buffer, sender: string) + constructor(owner: string, value: bigint, memo: string, assetId: Buffer, sender: string) static deserialize(jsBytes: Buffer): NativeNote serialize(): Buffer /** Value this note represents. */ @@ -100,7 +100,7 @@ export class Note { */ memo(): string /** Asset identifier associated with this note */ - assetIdentifier(): Buffer + assetId(): Buffer /** Sender of the note */ sender(): string /** Owner of the note */ @@ -140,7 +140,7 @@ export class Transaction { /** Mint a new asset with a given value as part of this transaction. */ mint(asset: Asset, value: bigint): void /** Burn some supply of a given asset and value as part of this transaction. */ - burn(assetIdentifierJsBytes: Buffer, value: bigint): void + burn(assetIdJsBytes: Buffer, value: bigint): void /** * Special case for posting a miners fee transaction. Miner fee transactions * are unique in that they generate currency. They do not have any spends diff --git a/ironfish-rust-nodejs/index.js b/ironfish-rust-nodejs/index.js index 55075bd020..2b8ee525e5 100644 --- a/ironfish-rust-nodejs/index.js +++ b/ironfish-rust-nodejs/index.js @@ -237,7 +237,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, ASSET_IDENTIFIER_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_OWNER_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, GENERATOR_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, TransactionPosted, PROOF_LENGTH, TRANSACTION_VERSION, Transaction, verifyTransactions, generateKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding +const { KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_OWNER_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, GENERATOR_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, TransactionPosted, PROOF_LENGTH, TRANSACTION_VERSION, Transaction, verifyTransactions, generateKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding module.exports.KEY_LENGTH = KEY_LENGTH module.exports.NONCE_LENGTH = NONCE_LENGTH @@ -246,7 +246,7 @@ module.exports.randomBytes = randomBytes module.exports.boxMessage = boxMessage module.exports.unboxMessage = unboxMessage module.exports.RollingFilter = RollingFilter -module.exports.ASSET_IDENTIFIER_LENGTH = ASSET_IDENTIFIER_LENGTH +module.exports.ASSET_ID_LENGTH = ASSET_ID_LENGTH module.exports.ASSET_METADATA_LENGTH = ASSET_METADATA_LENGTH module.exports.ASSET_NAME_LENGTH = ASSET_NAME_LENGTH module.exports.ASSET_OWNER_LENGTH = ASSET_OWNER_LENGTH diff --git a/ironfish-rust-nodejs/src/structs/asset.rs b/ironfish-rust-nodejs/src/structs/asset.rs index 74af6803b0..cb36bc4a08 100644 --- a/ironfish-rust-nodejs/src/structs/asset.rs +++ b/ironfish-rust-nodejs/src/structs/asset.rs @@ -4,8 +4,8 @@ use ironfish_rust::{ assets::asset::{ - Asset, ASSET_LENGTH as SERIALIZED_ASSET_LENGTH, IDENTIFIER_LENGTH, METADATA_LENGTH, - NAME_LENGTH, NATIVE_ASSET, + Asset, ASSET_LENGTH as SERIALIZED_ASSET_LENGTH, ID_LENGTH, METADATA_LENGTH, NAME_LENGTH, + NATIVE_ASSET, }, keys::PUBLIC_ADDRESS_SIZE, SaplingKey, @@ -19,7 +19,7 @@ use napi_derive::napi; use crate::to_napi_err; #[napi] -pub const ASSET_IDENTIFIER_LENGTH: u32 = IDENTIFIER_LENGTH as u32; +pub const ASSET_ID_LENGTH: u32 = ID_LENGTH as u32; #[napi] pub const ASSET_METADATA_LENGTH: u32 = METADATA_LENGTH as u32; @@ -71,13 +71,13 @@ impl NativeAsset { } #[napi] - pub fn native_identifier() -> Buffer { + pub fn native_id() -> Buffer { Buffer::from(&NATIVE_ASSET[..]) } #[napi] - pub fn identifier(&self) -> Buffer { - Buffer::from(&self.asset.identifier()[..]) + pub fn id(&self) -> Buffer { + Buffer::from(&self.asset.id()[..]) } #[napi] diff --git a/ironfish-rust-nodejs/src/structs/note.rs b/ironfish-rust-nodejs/src/structs/note.rs index 21eed61187..292d04aa57 100644 --- a/ironfish-rust-nodejs/src/structs/note.rs +++ b/ironfish-rust-nodejs/src/structs/note.rs @@ -3,9 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use ironfish_rust::{ - assets::asset::{ - asset_generator_from_identifier, IDENTIFIER_LENGTH as ASSET_IDENTIFIER_LENGTH, - }, + assets::asset::{asset_generator_from_id, ID_LENGTH as ASSET_ID_LENGTH}, note::{AMOUNT_VALUE_SIZE, GENERATOR_SIZE, MEMO_SIZE, SCALAR_SIZE}, }; use napi::{bindgen_prelude::*, JsBuffer}; @@ -59,7 +57,7 @@ impl NativeNote { owner: String, value: BigInt, memo: String, - asset_identifier: JsBuffer, + asset_id: JsBuffer, sender: String, ) -> Result { let value_u64 = value.get_u64().1; @@ -67,11 +65,11 @@ impl NativeNote { let sender_address = ironfish_rust::PublicAddress::from_hex(&sender).map_err(to_napi_err)?; - let buffer = asset_identifier.into_value()?; - let asset_identifier_vec = buffer.as_ref(); - let mut asset_identifier_bytes = [0; ASSET_IDENTIFIER_LENGTH]; - asset_identifier_bytes.clone_from_slice(&asset_identifier_vec[0..ASSET_IDENTIFIER_LENGTH]); - let asset_generator = asset_generator_from_identifier(&asset_identifier_bytes); + let buffer = asset_id.into_value()?; + let asset_id_vec = buffer.as_ref(); + let mut asset_id_bytes = [0; ASSET_ID_LENGTH]; + asset_id_bytes.clone_from_slice(&asset_id_vec[0..ASSET_ID_LENGTH]); + let asset_generator = asset_generator_from_id(&asset_id_bytes); Ok(NativeNote { note: Note::new( @@ -118,8 +116,8 @@ impl NativeNote { /// Asset identifier associated with this note #[napi] - pub fn asset_identifier(&self) -> Buffer { - Buffer::from(&self.note.asset_identifier()[..]) + pub fn asset_id(&self) -> Buffer { + Buffer::from(&self.note.asset_id()[..]) } /// Sender of the note diff --git a/ironfish-rust-nodejs/src/structs/transaction.rs b/ironfish-rust-nodejs/src/structs/transaction.rs index 6400f36d4b..ba53b23371 100644 --- a/ironfish-rust-nodejs/src/structs/transaction.rs +++ b/ironfish-rust-nodejs/src/structs/transaction.rs @@ -211,15 +211,12 @@ impl NativeTransaction { /// Burn some supply of a given asset and value as part of this transaction. #[napi] - pub fn burn(&mut self, asset_identifier_js_bytes: JsBuffer, value: BigInt) -> Result<()> { - let asset_identifier_bytes = asset_identifier_js_bytes.into_value()?; - let asset_identifier: AssetIdentifier = asset_identifier_bytes - .as_ref() - .try_into() - .map_err(to_napi_err)?; + pub fn burn(&mut self, asset_id_js_bytes: JsBuffer, value: BigInt) -> Result<()> { + let asset_id_bytes = asset_id_js_bytes.into_value()?; + let asset_id: AssetIdentifier = asset_id_bytes.as_ref().try_into().map_err(to_napi_err)?; let value_u64 = value.get_u64().1; self.transaction - .add_burn(asset_identifier, value_u64) + .add_burn(asset_id, value_u64) .map_err(to_napi_err)?; Ok(()) diff --git a/ironfish-rust-nodejs/tests/demo.test.slow.ts b/ironfish-rust-nodejs/tests/demo.test.slow.ts index cb3fac9903..63bf14644b 100644 --- a/ironfish-rust-nodejs/tests/demo.test.slow.ts +++ b/ironfish-rust-nodejs/tests/demo.test.slow.ts @@ -41,7 +41,7 @@ describe('Demonstrate the Sapling API', () => { const key = generateKey() const transaction = new Transaction(key.spending_key) - const note = new Note(key.public_address, BigInt(20), 'test', Asset.nativeIdentifier(), key.public_address) + const note = new Note(key.public_address, BigInt(20), 'test', Asset.nativeId(), key.public_address) transaction.receive(note) const serializedPostedTransaction = transaction.post_miners_fee() @@ -78,7 +78,7 @@ describe('Demonstrate the Sapling API', () => { const recipientKey = generateKey() const minersFeeTransaction = new Transaction(key.spending_key) - const minersFeeNote = new Note(key.public_address, BigInt(20), 'miner', Asset.nativeIdentifier(), key.public_address) + const minersFeeNote = new Note(key.public_address, BigInt(20), 'miner', Asset.nativeId(), key.public_address) minersFeeTransaction.receive(minersFeeNote) const postedMinersFeeTransaction = new TransactionPosted(minersFeeTransaction.post_miners_fee()) @@ -87,7 +87,7 @@ describe('Demonstrate the Sapling API', () => { transaction.setExpiration(10) const encryptedNote = new NoteEncrypted(postedMinersFeeTransaction.getNote(0)) const decryptedNote = Note.deserialize(encryptedNote.decryptNoteForOwner(key.incoming_view_key)!) - const newNote = new Note(recipientKey.public_address, BigInt(15), 'receive', Asset.nativeIdentifier(), minersFeeNote.owner()) + const newNote = new Note(recipientKey.public_address, BigInt(15), 'receive', Asset.nativeId(), minersFeeNote.owner()) let currentHash = encryptedNote.merkleHash() let authPath = Array.from({ length: 32 }, (_, depth) => { diff --git a/ironfish-rust/src/assets/asset.rs b/ironfish-rust/src/assets/asset.rs index f6a49b0ade..d541568df0 100644 --- a/ironfish-rust/src/assets/asset.rs +++ b/ironfish-rust/src/assets/asset.rs @@ -7,8 +7,8 @@ use byteorder::{ReadBytesExt, WriteBytesExt}; use group::GroupEncoding; use ironfish_zkp::{ constants::{ - ASSET_IDENTIFIER_LENGTH, ASSET_IDENTIFIER_PERSONALIZATION, - VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, VALUE_COMMITMENT_VALUE_GENERATOR, + ASSET_ID_LENGTH, ASSET_ID_PERSONALIZATION, VALUE_COMMITMENT_GENERATOR_PERSONALIZATION, + VALUE_COMMITMENT_VALUE_GENERATOR, }, group_hash, pedersen_hash, }; @@ -27,9 +27,9 @@ pub const NAME_LENGTH: usize = 32; const ASSET_INFO_HASHED_LENGTH: usize = 32; pub const METADATA_LENGTH: usize = 76; pub const ASSET_LENGTH: usize = NAME_LENGTH + PUBLIC_ADDRESS_SIZE + METADATA_LENGTH + 1; -pub const IDENTIFIER_LENGTH: usize = ASSET_IDENTIFIER_LENGTH; +pub const ID_LENGTH: usize = ASSET_ID_LENGTH; -pub type AssetIdentifier = [u8; ASSET_IDENTIFIER_LENGTH]; +pub type AssetIdentifier = [u8; ASSET_ID_LENGTH]; /// Describes all the fields necessary for creating and transacting with an /// asset on the Iron Fish network @@ -51,7 +51,7 @@ pub struct Asset { pub(crate) asset_info_hashed: [u8; ASSET_INFO_HASHED_LENGTH], /// The byte representation of the generator point derived from the hashed asset info - pub(crate) identifier: AssetIdentifier, + pub(crate) id: AssetIdentifier, } impl Asset { @@ -96,7 +96,7 @@ impl Asset { let preimage_bits = multipack::bytes_to_bits_le(&preimage); let asset_info_hashed_point = - pedersen_hash::pedersen_hash(ASSET_IDENTIFIER_PERSONALIZATION, preimage_bits); + pedersen_hash::pedersen_hash(ASSET_ID_PERSONALIZATION, preimage_bits); let asset_info_hashed = asset_info_hashed_point.to_bytes(); @@ -108,7 +108,7 @@ impl Asset { metadata, nonce, asset_info_hashed, - identifier: generator_point.to_bytes(), + id: generator_point.to_bytes(), }) } else { Err(IronfishError::InvalidAssetIdentifier) @@ -131,12 +131,12 @@ impl Asset { &self.nonce } - pub fn identifier(&self) -> &AssetIdentifier { - &self.identifier + pub fn id(&self) -> &AssetIdentifier { + &self.id } pub fn generator(&self) -> SubgroupPoint { - SubgroupPoint::from_bytes(&self.identifier).unwrap() + SubgroupPoint::from_bytes(&self.id).unwrap() } pub fn read(mut reader: R) -> Result { @@ -174,8 +174,8 @@ pub fn asset_generator_point( .ok_or(IronfishError::InvalidAssetIdentifier) } -pub fn asset_generator_from_identifier(asset_identifier: &AssetIdentifier) -> SubgroupPoint { - SubgroupPoint::from_bytes(asset_identifier).unwrap() +pub fn asset_generator_from_id(asset_id: &AssetIdentifier) -> SubgroupPoint { + SubgroupPoint::from_bytes(asset_id).unwrap() } #[cfg(test)] diff --git a/ironfish-rust/src/note.rs b/ironfish-rust/src/note.rs index 71c2f08d4a..9c00e6ca2e 100644 --- a/ironfish-rust/src/note.rs +++ b/ironfish-rust/src/note.rs @@ -234,7 +234,7 @@ impl<'a> Note { self.asset_generator } - pub fn asset_identifier(&self) -> AssetIdentifier { + pub fn asset_id(&self) -> AssetIdentifier { self.asset_generator.to_bytes() } diff --git a/ironfish-rust/src/transaction/burns.rs b/ironfish-rust/src/transaction/burns.rs index 25f1caf9a8..24635e851a 100644 --- a/ironfish-rust/src/transaction/burns.rs +++ b/ironfish-rust/src/transaction/burns.rs @@ -5,30 +5,27 @@ use std::io; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use ironfish_zkp::constants::ASSET_IDENTIFIER_LENGTH; +use ironfish_zkp::constants::ASSET_ID_LENGTH; use crate::{assets::asset::AssetIdentifier, errors::IronfishError}; /// Parameters used to build a burn description pub struct BurnBuilder { /// Identifier of the Asset to be burned - pub asset_identifier: AssetIdentifier, + pub asset_id: AssetIdentifier, /// Amount of asset to burn pub value: u64, } impl BurnBuilder { - pub fn new(asset_identifier: AssetIdentifier, value: u64) -> Self { - Self { - asset_identifier, - value, - } + pub fn new(asset_id: AssetIdentifier, value: u64) -> Self { + Self { asset_id, value } } pub fn build(&self) -> BurnDescription { BurnDescription { - asset_identifier: self.asset_identifier, + asset_id: self.asset_id, value: self.value, } } @@ -39,7 +36,7 @@ impl BurnBuilder { #[derive(Clone)] pub struct BurnDescription { /// Identifier for the Asset which is being burned - pub asset_identifier: AssetIdentifier, + pub asset_id: AssetIdentifier, /// Amount of asset to burn pub value: u64, @@ -55,24 +52,21 @@ impl BurnDescription { &self, mut writer: W, ) -> Result<(), IronfishError> { - writer.write_all(&self.asset_identifier)?; + writer.write_all(&self.asset_id)?; writer.write_u64::(self.value)?; Ok(()) } pub fn read(mut reader: R) -> Result { - let asset_identifier = { - let mut bytes = [0u8; ASSET_IDENTIFIER_LENGTH]; + let asset_id = { + let mut bytes = [0u8; ASSET_ID_LENGTH]; reader.read_exact(&mut bytes)?; bytes }; let value = reader.read_u64::()?; - Ok(BurnDescription { - asset_identifier, - value, - }) + Ok(BurnDescription { asset_id, value }) } /// Stow the bytes of this [`BurnDescription`] in the given writer. @@ -99,10 +93,10 @@ mod test { let asset = Asset::new(owner, name, metadata).unwrap(); let value = 5; - let builder = BurnBuilder::new(asset.identifier, value); + let builder = BurnBuilder::new(asset.id, value); assert_eq!(builder.value, value); - assert_eq!(builder.asset_identifier, asset.identifier); + assert_eq!(builder.asset_id, asset.id); } #[test] @@ -115,7 +109,7 @@ mod test { let asset = Asset::new(owner, name, metadata).unwrap(); let value = 5; - let builder = BurnBuilder::new(asset.identifier, value); + let builder = BurnBuilder::new(asset.id, value); let burn = builder.build(); let mut serialized_description = vec![]; @@ -125,10 +119,7 @@ mod test { let deserialized_description = BurnDescription::read(&serialized_description[..]) .expect("should be able to deserialize valid description"); - assert_eq!( - burn.asset_identifier, - deserialized_description.asset_identifier - ); + assert_eq!(burn.asset_id, deserialized_description.asset_id); assert_eq!(burn.value, deserialized_description.value); let mut reserialized_description = vec![]; diff --git a/ironfish-rust/src/transaction/mod.rs b/ironfish-rust/src/transaction/mod.rs index b44268dd04..080ca44a4b 100644 --- a/ironfish-rust/src/transaction/mod.rs +++ b/ironfish-rust/src/transaction/mod.rs @@ -9,8 +9,7 @@ use value_balances::ValueBalances; use crate::{ assets::asset::{ - asset_generator_from_identifier, Asset, AssetIdentifier, NATIVE_ASSET, - NATIVE_ASSET_GENERATOR, + asset_generator_from_id, Asset, AssetIdentifier, NATIVE_ASSET, NATIVE_ASSET_GENERATOR, }, errors::IronfishError, keys::{PublicAddress, SaplingKey}, @@ -139,7 +138,7 @@ impl ProposedTransaction { witness: &dyn WitnessTrait, ) -> Result<(), IronfishError> { self.value_balances - .add(¬e.asset_identifier(), note.value() as i64)?; + .add(¬e.asset_id(), note.value() as i64)?; self.spends.push(SpendBuilder::new(note, witness)); @@ -150,7 +149,7 @@ impl ProposedTransaction { /// transaction. pub fn add_output(&mut self, note: Note) -> Result<(), IronfishError> { self.value_balances - .subtract(¬e.asset_identifier(), note.value() as i64)?; + .subtract(¬e.asset_id(), note.value() as i64)?; self.outputs.push(OutputBuilder::new(note)); @@ -158,22 +157,17 @@ impl ProposedTransaction { } pub fn add_mint(&mut self, asset: Asset, value: u64) -> Result<(), IronfishError> { - self.value_balances.add(asset.identifier(), value as i64)?; + self.value_balances.add(asset.id(), value as i64)?; self.mints.push(MintBuilder::new(asset, value)); Ok(()) } - pub fn add_burn( - &mut self, - asset_identifier: AssetIdentifier, - value: u64, - ) -> Result<(), IronfishError> { - self.value_balances - .subtract(&asset_identifier, value as i64)?; + pub fn add_burn(&mut self, asset_id: AssetIdentifier, value: u64) -> Result<(), IronfishError> { + self.value_balances.subtract(&asset_id, value as i64)?; - self.burns.push(BurnBuilder::new(asset_identifier, value)); + self.burns.push(BurnBuilder::new(asset_id, value)); Ok(()) } @@ -195,8 +189,8 @@ impl ProposedTransaction { ) -> Result { let mut change_notes = vec![]; - for (asset_identifier, value) in self.value_balances.iter() { - let is_native_asset = asset_identifier == &NATIVE_ASSET; + for (asset_id, value) in self.value_balances.iter() { + let is_native_asset = asset_id == &NATIVE_ASSET; let change_amount = match is_native_asset { true => *value - intended_transaction_fee as i64, @@ -213,7 +207,7 @@ impl ProposedTransaction { change_address, change_amount as u64, // we checked it was positive "", - SubgroupPoint::from_bytes(asset_identifier).unwrap(), + SubgroupPoint::from_bytes(asset_id).unwrap(), self.spender_key.public_address(), ); @@ -743,7 +737,7 @@ fn calculate_value_balance( let mut value_balance_point = binding_verification_key - fee_point; for burn in burns { - let burn_generator = asset_generator_from_identifier(&burn.asset_identifier); + let burn_generator = asset_generator_from_id(&burn.asset_id); value_balance_point -= burn_generator * jubjub::Fr::from(burn.value); } diff --git a/ironfish-rust/src/transaction/tests.rs b/ironfish-rust/src/transaction/tests.rs index eaee113da0..12c42c1ff6 100644 --- a/ironfish-rust/src/transaction/tests.rs +++ b/ironfish-rust/src/transaction/tests.rs @@ -75,7 +75,7 @@ fn test_transaction() { assert_eq!(transaction.outputs.len(), 2); // Burn 2 tokens, leaving 1 token left to be put into a change note - transaction.add_burn(asset.identifier, burn_value).unwrap(); + transaction.add_burn(asset.id, burn_value).unwrap(); assert_eq!(transaction.burns.len(), 1); let public_transaction = transaction diff --git a/ironfish-rust/src/transaction/value_balances.rs b/ironfish-rust/src/transaction/value_balances.rs index a57e287f9e..ede3361e9f 100644 --- a/ironfish-rust/src/transaction/value_balances.rs +++ b/ironfish-rust/src/transaction/value_balances.rs @@ -21,12 +21,8 @@ impl ValueBalances { ValueBalances { values: hash_map } } - pub fn add( - &mut self, - asset_identifier: &AssetIdentifier, - value: i64, - ) -> Result<(), IronfishError> { - let current_value = self.values.entry(*asset_identifier).or_insert(0); + pub fn add(&mut self, asset_id: &AssetIdentifier, value: i64) -> Result<(), IronfishError> { + let current_value = self.values.entry(*asset_id).or_insert(0); let new_value = current_value .checked_add(value) .ok_or(IronfishError::InvalidBalance)?; @@ -38,10 +34,10 @@ impl ValueBalances { pub fn subtract( &mut self, - asset_identifier: &AssetIdentifier, + asset_id: &AssetIdentifier, value: i64, ) -> Result<(), IronfishError> { - let current_value = self.values.entry(*asset_identifier).or_insert(0); + let current_value = self.values.entry(*asset_id).or_insert(0); let new_value = current_value .checked_sub(value) .ok_or(IronfishError::InvalidBalance)?; diff --git a/ironfish-zkp/src/circuits/mint_asset.rs b/ironfish-zkp/src/circuits/mint_asset.rs index 5cdd1f2db5..8fe67553e6 100644 --- a/ironfish-zkp/src/circuits/mint_asset.rs +++ b/ironfish-zkp/src/circuits/mint_asset.rs @@ -11,7 +11,7 @@ use zcash_proofs::{ use crate::{ circuits::util::{asset_info_preimage, expose_value_commitment}, - constants::{proof::PUBLIC_KEY_GENERATOR, ASSET_IDENTIFIER_PERSONALIZATION}, + constants::{proof::PUBLIC_KEY_GENERATOR, ASSET_ID_PERSONALIZATION}, primitives::ValueCommitment, }; @@ -139,7 +139,7 @@ impl Circuit for MintAsset { // Computed identifier bits from the given asset info let asset_info_hashed_point = pedersen_hash::pedersen_hash( cs.namespace(|| "asset info hash"), - ASSET_IDENTIFIER_PERSONALIZATION, + ASSET_ID_PERSONALIZATION, &asset_info_preimage, )?; @@ -187,7 +187,7 @@ mod test { }; use crate::{ - constants::{ASSET_IDENTIFIER_PERSONALIZATION, PUBLIC_KEY_GENERATOR}, + constants::{ASSET_ID_PERSONALIZATION, PUBLIC_KEY_GENERATOR}, primitives::ValueCommitment, }; @@ -220,7 +220,7 @@ mod test { let asset_plaintext_bits = multipack::bytes_to_bits_le(&asset_plaintext); let asset_info_hashed_point = - pedersen_hash::pedersen_hash(ASSET_IDENTIFIER_PERSONALIZATION, asset_plaintext_bits); + pedersen_hash::pedersen_hash(ASSET_ID_PERSONALIZATION, asset_plaintext_bits); let asset_info_hashed_bytes = asset_info_hashed_point.to_bytes(); diff --git a/ironfish-zkp/src/constants.rs b/ironfish-zkp/src/constants.rs index a5f550257b..50460bc17a 100644 --- a/ironfish-zkp/src/constants.rs +++ b/ironfish-zkp/src/constants.rs @@ -10,10 +10,10 @@ use zcash_primitives::sapling::pedersen_hash; pub use zcash_proofs::circuit::sapling::TREE_DEPTH; /// Length in bytes of the asset identifier -pub const ASSET_IDENTIFIER_LENGTH: usize = 32; +pub const ASSET_ID_LENGTH: usize = 32; // Easier to alias this instead of forking pedersen hash just to extend the Personalization enum -pub const ASSET_IDENTIFIER_PERSONALIZATION: pedersen_hash::Personalization = +pub const ASSET_ID_PERSONALIZATION: pedersen_hash::Personalization = pedersen_hash::Personalization::MerkleTree(62); pub const PUBLIC_KEY_GENERATOR: SubgroupPoint = SubgroupPoint::from_raw_unchecked( diff --git a/ironfish/src/blockchain/blockchain.test.perf.ts b/ironfish/src/blockchain/blockchain.test.perf.ts index 3933ed050b..dcb97ea41a 100644 --- a/ironfish/src/blockchain/blockchain.test.perf.ts +++ b/ironfish/src/blockchain/blockchain.test.perf.ts @@ -57,8 +57,8 @@ describe('Blockchain', () => { blocksB.push(blockB) } - const balanceA = await nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()) - const balanceB = await nodeB.wallet.getBalance(accountB, Asset.nativeIdentifier()) + const balanceA = await nodeA.wallet.getBalance(accountA, Asset.nativeId()) + const balanceB = await nodeB.wallet.getBalance(accountB, Asset.nativeId()) // You'll need to update this if the block reward changes expect(balanceA.confirmed).toEqual(BigInt(1999999901)) diff --git a/ironfish/src/blockchain/blockchain.test.ts b/ironfish/src/blockchain/blockchain.test.ts index 5b8a624017..8eef69a505 100644 --- a/ironfish/src/blockchain/blockchain.test.ts +++ b/ironfish/src/blockchain/blockchain.test.ts @@ -860,7 +860,7 @@ describe('Blockchain', () => { [noteToBurn], [], [], - [{ assetIdentifier: asset.identifier(), value }], + [{ assetId: asset.id(), value }], sequence, ) } @@ -882,11 +882,11 @@ describe('Blockchain', () => { const block = await useMinerBlockFixture(node.chain, 2, undefined, undefined, [mint]) await expect(node.chain).toAddBlock(block) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toEqual({ createdTransactionHash: mint.hash(), - identifier: asset.identifier(), + id: asset.id(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), @@ -924,7 +924,7 @@ describe('Blockchain', () => { const blockB = await burnAsset(node, account, 3, asset, burnValue, noteToBurn) await expect(node.chain).toAddBlock(blockB) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toMatchObject({ createdTransactionHash: mintTransaction.hash(), supply: mintValue - burnValue, @@ -961,10 +961,10 @@ describe('Blockchain', () => { }) await expect(node.chain).toAddBlock(blockB) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toEqual({ createdTransactionHash: mintTransactionA.hash(), - identifier: asset.identifier(), + id: asset.id(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), @@ -994,7 +994,7 @@ describe('Blockchain', () => { await node.chain.removeBlock(block.header.hash) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toBeUndefined() }) }) @@ -1029,7 +1029,7 @@ describe('Blockchain', () => { await node.chain.removeBlock(blockB.header.hash) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toMatchObject({ supply: mintValueA, }) @@ -1061,7 +1061,7 @@ describe('Blockchain', () => { await node.chain.removeBlock(blockB.header.hash) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toMatchObject({ supply: mintValue, }) @@ -1075,7 +1075,7 @@ describe('Blockchain', () => { const account = await useAccountFixture(wallet) const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() + const assetId = asset.id() const mintValue = BigInt(10) const blockA = await useMintBlockFixture({ @@ -1093,7 +1093,7 @@ describe('Blockchain', () => { // hack, the posted transaction would raise an exception, which is a // separate flow to test for. We should never hit this case; this is a // sanity check. - await node.chain.assets.del(assetIdentifier) + await node.chain.assets.del(assetId) const burnValue = BigInt(3) const noteToBurn = blockA.transactions[1].getNote(0) @@ -1111,7 +1111,7 @@ describe('Blockchain', () => { const account = await useAccountFixture(wallet) const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() + const assetId = asset.id() const mintValue = BigInt(10) const blockA = await useMintBlockFixture({ @@ -1123,14 +1123,14 @@ describe('Blockchain', () => { }) await expect(node.chain).toAddBlock(blockA) - const record = await node.chain.assets.get(assetIdentifier) + const record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) // Perform a hack where we adjust the supply in the DB to be lower than // what was previously minted. This is done to check what happens if a // burn is processed but the DB does not have enough supply for a given // burn. Without this, the posted transaction would raise an invalid // balance exception, which is a separate flow to test for. - await node.chain.assets.put(assetIdentifier, { + await node.chain.assets.put(assetId, { ...record, supply: BigInt(1), }) @@ -1149,7 +1149,7 @@ describe('Blockchain', () => { const account = await useAccountFixture(wallet) const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() + const assetId = asset.id() // 1. Mint 10 const mintValueA = BigInt(10) @@ -1162,7 +1162,7 @@ describe('Blockchain', () => { }) await expect(node.chain).toAddBlock(blockA) // Check first mint value - let record = await node.chain.assets.get(assetIdentifier) + let record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1180,7 +1180,7 @@ describe('Blockchain', () => { }) await expect(node.chain).toAddBlock(blockB) // Check aggregate mint value - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1193,7 +1193,7 @@ describe('Blockchain', () => { const blockC = await burnAsset(node, account, 4, asset, burnValueC, noteToBurnC) await expect(node.chain).toAddBlock(blockC) // Check value after burn - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1203,7 +1203,7 @@ describe('Blockchain', () => { // 4. Roll back the burn from Block C (Step 3 above) await node.chain.removeBlock(blockC.header.hash) // Check value after burn roll back - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1216,7 +1216,7 @@ describe('Blockchain', () => { const blockD = await burnAsset(node, account, 4, asset, burnValueD, noteToBurnD) await expect(node.chain).toAddBlock(blockD) // Check aggregate mint value - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1234,7 +1234,7 @@ describe('Blockchain', () => { }) await expect(node.chain).toAddBlock(blockE) // Check aggregate mint value - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1244,7 +1244,7 @@ describe('Blockchain', () => { // 7. Roll back the mint from Block E (Step 6 above) await node.chain.removeBlock(blockE.header.hash) // Check value after burn roll back - record = await node.chain.assets.get(assetIdentifier) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1262,7 +1262,7 @@ describe('Blockchain', () => { const asset = new Asset(accountA.spendingKey, 'mint-asset', 'metadata') const mintValue = BigInt(10) - const assetIdentifier = asset.identifier() + const assetId = asset.id() // G -> A1 // -> B1 -> B2 @@ -1276,7 +1276,7 @@ describe('Blockchain', () => { await nodeA.chain.addBlock(blockA1) // Verify Node A has the asset - let record = await nodeA.chain.assets.get(assetIdentifier) + let record = await nodeA.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA1.transactions[1].hash(), @@ -1289,7 +1289,7 @@ describe('Blockchain', () => { await nodeB.chain.addBlock(blockB2) // Verify Node B does not have the asset - record = await nodeB.chain.assets.get(assetIdentifier) + record = await nodeB.chain.assets.get(assetId) expect(record).toBeUndefined() // Reorganize the chain on Node A @@ -1298,7 +1298,7 @@ describe('Blockchain', () => { // Verify Node A no longer has the asset from Block A1 expect(nodeA.chain.head.hash.equals(blockB2.header.hash)).toBe(true) - record = await nodeA.chain.assets.get(assetIdentifier) + record = await nodeA.chain.assets.get(assetId) expect(record).toBeUndefined() }) }) @@ -1326,7 +1326,7 @@ describe('Blockchain', () => { const rawBurn = new RawTransaction() rawBurn.spendingKey = account.spendingKey rawBurn.spends = [{ note: note.note, witness }] - rawBurn.burns = [{ assetIdentifier: Asset.nativeIdentifier(), value: BigInt(2) }] + rawBurn.burns = [{ assetId: Asset.nativeId(), value: BigInt(2) }] const rawSend = new RawTransaction() rawSend.spendingKey = account.spendingKey @@ -1338,7 +1338,7 @@ describe('Blockchain', () => { account.publicAddress, 3n, '', - Asset.nativeIdentifier(), + Asset.nativeId(), account.publicAddress, ).serialize(), ), diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 402bb26b3f..52a9ecf746 100644 --- a/ironfish/src/blockchain/blockchain.ts +++ b/ironfish/src/blockchain/blockchain.ts @@ -1330,8 +1330,8 @@ export class Blockchain { tx: IDatabaseTransaction, ): Promise { for (const { asset, value } of transaction.mints) { - const assetIdentifier = asset.identifier() - const existingAsset = await this.assets.get(assetIdentifier, tx) + const assetId = asset.id() + const existingAsset = await this.assets.get(assetId, tx) let createdTransactionHash = transaction.hash() let supply = BigInt(0) @@ -1341,10 +1341,10 @@ export class Blockchain { } await this.assets.put( - assetIdentifier, + assetId, { createdTransactionHash, - identifier: assetIdentifier, + id: assetId, metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), @@ -1360,8 +1360,8 @@ export class Blockchain { transaction: Transaction, tx: IDatabaseTransaction, ): Promise { - for (const { assetIdentifier, value } of transaction.burns) { - const existingAsset = await this.assets.get(assetIdentifier, tx) + for (const { assetId, value } of transaction.burns) { + const existingAsset = await this.assets.get(assetId, tx) Assert.isNotUndefined(existingAsset, 'Cannot burn undefined asset from the database') const existingSupply = existingAsset.supply @@ -1369,10 +1369,10 @@ export class Blockchain { Assert.isTrue(supply >= BigInt(0), 'Invalid burn value') await this.assets.put( - assetIdentifier, + assetId, { createdTransactionHash: existingAsset.createdTransactionHash, - identifier: existingAsset.identifier, + id: existingAsset.id, metadata: existingAsset.metadata, name: existingAsset.name, nonce: existingAsset.nonce, @@ -1388,18 +1388,18 @@ export class Blockchain { transaction: Transaction, tx: IDatabaseTransaction, ): Promise { - for (const { assetIdentifier, value } of transaction.burns.slice().reverse()) { - const existingAsset = await this.assets.get(assetIdentifier, tx) + for (const { assetId, value } of transaction.burns.slice().reverse()) { + const existingAsset = await this.assets.get(assetId, tx) Assert.isNotUndefined(existingAsset) const existingSupply = existingAsset.supply const supply = existingSupply + value await this.assets.put( - assetIdentifier, + assetId, { createdTransactionHash: existingAsset.createdTransactionHash, - identifier: existingAsset.identifier, + id: existingAsset.id, metadata: existingAsset.metadata, name: existingAsset.name, nonce: existingAsset.nonce, @@ -1416,8 +1416,8 @@ export class Blockchain { tx: IDatabaseTransaction, ): Promise { for (const { asset, value } of transaction.mints.slice().reverse()) { - const assetIdentifier = asset.identifier() - const existingAsset = await this.assets.get(assetIdentifier, tx) + const assetId = asset.id() + const existingAsset = await this.assets.get(assetId, tx) Assert.isNotUndefined(existingAsset) const existingSupply = existingAsset.supply @@ -1430,13 +1430,13 @@ export class Blockchain { transaction.hash().equals(existingAsset.createdTransactionHash) && supply === BigInt(0) ) { - await this.assets.del(assetIdentifier, tx) + await this.assets.del(assetId, tx) } else { await this.assets.put( - assetIdentifier, + assetId, { createdTransactionHash: existingAsset.createdTransactionHash, - identifier: asset.identifier(), + id: asset.id(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), @@ -1466,11 +1466,11 @@ export class Blockchain { this.onSynced.emit() } - async getAssetById(assetIdentifier: Buffer): Promise { - if (Asset.nativeIdentifier().equals(assetIdentifier)) { + async getAssetById(assetId: Buffer): Promise { + if (Asset.nativeId().equals(assetId)) { return { createdTransactionHash: GENESIS_BLOCK_PREVIOUS, - identifier: Asset.nativeIdentifier(), + id: Asset.nativeId(), metadata: Buffer.from('Native asset of Iron Fish blockchain', 'utf8'), name: Buffer.from('$IRON', 'utf8'), owner: Buffer.from('Iron Fish', 'utf8'), @@ -1479,7 +1479,7 @@ export class Blockchain { } } - const asset = await this.assets.get(assetIdentifier) + const asset = await this.assets.get(assetId) return asset || null } } diff --git a/ironfish/src/blockchain/database/assets.test.ts b/ironfish/src/blockchain/database/assets.test.ts index 94f7cee846..d3e03a8f66 100644 --- a/ironfish/src/blockchain/database/assets.test.ts +++ b/ironfish/src/blockchain/database/assets.test.ts @@ -15,7 +15,7 @@ describe('AssetsValueEncoding', () => { const value: AssetsValue = { createdTransactionHash: Buffer.alloc(32, 0), - identifier: asset.identifier(), + id: asset.id(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), diff --git a/ironfish/src/blockchain/database/assets.ts b/ironfish/src/blockchain/database/assets.ts index 6e85dad22b..ec62ee1ea2 100644 --- a/ironfish/src/blockchain/database/assets.ts +++ b/ironfish/src/blockchain/database/assets.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { IDatabaseEncoding } from '../../storage/database/types' import { - ASSET_IDENTIFIER_LENGTH, + ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_OWNER_LENGTH, @@ -14,7 +14,7 @@ import { BigIntUtils } from '../../utils' export interface AssetsValue { createdTransactionHash: Buffer - identifier: Buffer + id: Buffer metadata: Buffer name: Buffer nonce: number @@ -26,7 +26,7 @@ export class AssetsValueEncoding implements IDatabaseEncoding { serialize(value: AssetsValue): Buffer { const bw = bufio.write(this.getSize(value)) bw.writeHash(value.createdTransactionHash) - bw.writeHash(value.identifier) + bw.writeHash(value.id) bw.writeBytes(value.metadata) bw.writeBytes(value.name) bw.writeU8(value.nonce) @@ -38,19 +38,19 @@ export class AssetsValueEncoding implements IDatabaseEncoding { deserialize(buffer: Buffer): AssetsValue { const reader = bufio.read(buffer, true) const createdTransactionHash = reader.readHash() - const identifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) + const id = reader.readBytes(ASSET_ID_LENGTH) const metadata = reader.readBytes(ASSET_METADATA_LENGTH) const name = reader.readBytes(ASSET_NAME_LENGTH) const nonce = reader.readU8() const owner = reader.readBytes(ASSET_OWNER_LENGTH) const supply = BigIntUtils.fromBytesLE(reader.readVarBytes()) - return { createdTransactionHash, identifier, metadata, name, nonce, owner, supply } + return { createdTransactionHash, id, metadata, name, nonce, owner, supply } } getSize(value: AssetsValue): number { let size = 0 size += 32 // createdTransactionHash - size += ASSET_IDENTIFIER_LENGTH // identifier + size += ASSET_ID_LENGTH // id size += ASSET_METADATA_LENGTH // metadata size += ASSET_NAME_LENGTH // name size += 1 // nonce diff --git a/ironfish/src/genesis/genesis.test.slow.ts b/ironfish/src/genesis/genesis.test.slow.ts index 2ada27cc37..9a5ab3c338 100644 --- a/ironfish/src/genesis/genesis.test.slow.ts +++ b/ironfish/src/genesis/genesis.test.slow.ts @@ -85,9 +85,7 @@ describe('Create genesis block', () => { // Balance should still be zero, since generating the block should clear out // any notes made in the process - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -99,9 +97,7 @@ describe('Create genesis block', () => { await node.wallet.updateHead() // Check that the balance is what's expected - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: amountBigint, unconfirmed: amountBigint, }) @@ -138,7 +134,7 @@ describe('Create genesis block', () => { await newNode.wallet.scanTransactions() await expect( - newNode.wallet.getBalance(accountNewNode, Asset.nativeIdentifier()), + newNode.wallet.getBalance(accountNewNode, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: amountBigint, unconfirmed: amountBigint, diff --git a/ironfish/src/genesis/makeGenesisBlock.ts b/ironfish/src/genesis/makeGenesisBlock.ts index 958dd028b2..8b883cedfd 100644 --- a/ironfish/src/genesis/makeGenesisBlock.ts +++ b/ironfish/src/genesis/makeGenesisBlock.ts @@ -57,7 +57,7 @@ export async function makeGenesisBlock( genesisKey.public_address, allocationSum, '', - Asset.nativeIdentifier(), + Asset.nativeId(), genesisKey.public_address, ) @@ -73,7 +73,7 @@ export async function makeGenesisBlock( minersFeeKey.public_address, BigInt(0), '', - Asset.nativeIdentifier(), + Asset.nativeId(), minersFeeKey.public_address, ) @@ -138,7 +138,7 @@ export async function makeGenesisBlock( alloc.publicAddress, BigInt(alloc.amountInOre), alloc.memo, - Asset.nativeIdentifier(), + Asset.nativeId(), genesisNote.owner(), ) transaction.receive(note) diff --git a/ironfish/src/memPool/feeEstimator.test.ts b/ironfish/src/memPool/feeEstimator.test.ts index e7ffe87998..4e97f1cd0f 100644 --- a/ironfish/src/memPool/feeEstimator.test.ts +++ b/ironfish/src/memPool/feeEstimator.test.ts @@ -436,7 +436,7 @@ describe('FeeEstimator', () => { // account1 should have only one note -- change from its transaction to account2 const account1Notes = await AsyncUtils.materialize( - account1.getUnspentNotes(Asset.nativeIdentifier()), + account1.getUnspentNotes(Asset.nativeId()), ) expect(account1Notes.length).toEqual(1) diff --git a/ironfish/src/memPool/feeEstimator.ts b/ironfish/src/memPool/feeEstimator.ts index b43a945bea..68ab24809d 100644 --- a/ironfish/src/memPool/feeEstimator.ts +++ b/ironfish/src/memPool/feeEstimator.ts @@ -242,7 +242,7 @@ export class FeeEstimator { const { amount, notes } = await this.wallet.createSpendsForAsset( sender, - Asset.nativeIdentifier(), + Asset.nativeId(), amountNeeded, ) diff --git a/ironfish/src/mining/poolShares.ts b/ironfish/src/mining/poolShares.ts index f1b4d8bba3..bb079e12cc 100644 --- a/ironfish/src/mining/poolShares.ts +++ b/ironfish/src/mining/poolShares.ts @@ -153,7 +153,7 @@ export class MiningPoolShares { publicAddress, amount: amt.toString(), memo: `${this.poolName} payout ${shareCutoff.toUTCString()}`, - assetIdentifier: Asset.nativeIdentifier().toString('hex'), + assetId: Asset.nativeId().toString('hex'), } }, ) diff --git a/ironfish/src/primitives/burnDescription.ts b/ironfish/src/primitives/burnDescription.ts index 664bc62d4d..8419f109ac 100644 --- a/ironfish/src/primitives/burnDescription.ts +++ b/ironfish/src/primitives/burnDescription.ts @@ -2,6 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ export interface BurnDescription { - assetIdentifier: Buffer + assetId: Buffer value: bigint } diff --git a/ironfish/src/primitives/note.ts b/ironfish/src/primitives/note.ts index 76861a432e..122b779592 100644 --- a/ironfish/src/primitives/note.ts +++ b/ironfish/src/primitives/note.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { - ASSET_IDENTIFIER_LENGTH, + ASSET_ID_LENGTH, MEMO_LENGTH, Note as NativeNote, PUBLIC_ADDRESS_LENGTH, @@ -19,7 +19,7 @@ export class Note { private readonly _value: bigint private readonly _memo: Buffer - private readonly _assetIdentifier: Buffer + private readonly _assetId: Buffer private readonly _sender: string constructor(noteSerialized: Buffer) { @@ -30,7 +30,7 @@ export class Note { // skip owner public address reader.seek(PUBLIC_ADDRESS_LENGTH) - this._assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH, true) + this._assetId = reader.readBytes(ASSET_ID_LENGTH, true) this._value = reader.readBigU64() @@ -74,8 +74,8 @@ export class Note { return BufferUtils.toHuman(this._memo) } - assetIdentifier(): Buffer { - return this._assetIdentifier + assetId(): Buffer { + return this._assetId } nullifier(ownerPrivateKey: string, position: bigint): Buffer { diff --git a/ironfish/src/primitives/rawTransaction.test.ts b/ironfish/src/primitives/rawTransaction.test.ts index 7d5d7669be..eaf464a740 100644 --- a/ironfish/src/primitives/rawTransaction.test.ts +++ b/ironfish/src/primitives/rawTransaction.test.ts @@ -29,10 +29,10 @@ describe('RawTransaction', () => { ) await expect(nodeTest.chain).toAddBlock(block) await nodeTest.wallet.updateHead() - const { unconfirmed } = await account.getUnconfirmedBalance(Asset.nativeIdentifier()) + const { unconfirmed } = await account.getUnconfirmedBalance(Asset.nativeId()) const burn = { - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), value: 2n, } @@ -67,16 +67,16 @@ describe('RawTransaction', () => { const decryptedNote = note.decryptNoteForOwner(account.incomingViewKey) Assert.isNotUndefined(decryptedNote) - const identifier = decryptedNote.assetIdentifier() - const value = valuesByAsset.get(identifier) || 0n - valuesByAsset.set(identifier, value + decryptedNote.value()) + const id = decryptedNote.assetId() + const value = valuesByAsset.get(id) || 0n + valuesByAsset.set(id, value + decryptedNote.value()) } - const nativeValue = valuesByAsset.get(Asset.nativeIdentifier()) + const nativeValue = valuesByAsset.get(Asset.nativeId()) Assert.isNotUndefined(nativeValue) expect(nativeValue).toEqual(unconfirmed - raw.fee - mint.value - 1n) - const mintedValue = valuesByAsset.get(asset.identifier()) + const mintedValue = valuesByAsset.get(asset.id()) Assert.isNotUndefined(mintedValue) expect(mintedValue).toEqual(1n) }) @@ -91,7 +91,7 @@ describe('RawTransaction', () => { generateKey().public_address, 5n, 'memo', - asset.identifier(), + asset.id(), account.publicAddress, ).serialize(), ) @@ -121,7 +121,7 @@ describe('RawTransaction', () => { raw.burns = [ { - assetIdentifier: asset.identifier(), + assetId: asset.id(), value: 5n, }, ] @@ -145,7 +145,7 @@ describe('RawTransaction', () => { expect(RawTransactionSerde.serialize(deserialized).equals(serialized)).toBe(true) expect(deserialized.receives[0].note).toEqual(raw.receives[0].note) - expect(deserialized.burns[0].assetIdentifier).toEqual(asset.identifier()) + expect(deserialized.burns[0].assetId).toEqual(asset.id()) expect(deserialized.burns[0].value).toEqual(5n) expect(deserialized.mints[0].asset.serialize()).toEqual(asset.serialize()) expect(deserialized.mints[0].value).toEqual(5n) diff --git a/ironfish/src/primitives/rawTransaction.ts b/ironfish/src/primitives/rawTransaction.ts index cda251a1a4..7447377b36 100644 --- a/ironfish/src/primitives/rawTransaction.ts +++ b/ironfish/src/primitives/rawTransaction.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Transaction as NativeTransaction } from '@ironfish/rust-nodejs' -import { Asset, ASSET_IDENTIFIER_LENGTH, ASSET_LENGTH } from '@ironfish/rust-nodejs' +import { Asset, ASSET_ID_LENGTH, ASSET_LENGTH } from '@ironfish/rust-nodejs' import bufio from 'bufio' import { Witness } from '../merkletree' import { NoteHasher } from '../merkletree/hasher' @@ -53,7 +53,7 @@ export class RawTransaction { } for (const burn of this.burns) { - builder.burn(burn.assetIdentifier, burn.value) + builder.burn(burn.assetId, burn.value) } if (this.expiration !== null) { @@ -107,7 +107,7 @@ export class RawTransactionSerde { bw.writeU64(raw.burns.length) for (const burn of raw.burns) { - bw.writeBytes(burn.assetIdentifier) + bw.writeBytes(burn.assetId) bw.writeBigU64(burn.value) } @@ -160,9 +160,9 @@ export class RawTransactionSerde { const burnsLength = reader.readU64() for (let i = 0; i < burnsLength; i++) { - const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) + const assetId = reader.readBytes(ASSET_ID_LENGTH) const value = reader.readBigU64() - raw.burns.push({ assetIdentifier, value }) + raw.burns.push({ assetId, value }) } const hasExpiration = reader.readU8() @@ -205,7 +205,7 @@ export class RawTransactionSerde { size += 8 // raw.burns.length for (const _ of raw.burns) { - size += ASSET_IDENTIFIER_LENGTH // burn.assetIdentifier + size += ASSET_ID_LENGTH // burn.assetId size += 8 // burn.value } diff --git a/ironfish/src/primitives/transaction.test.slow.ts b/ironfish/src/primitives/transaction.test.slow.ts index b5e03cbef1..a0b1dee3c3 100644 --- a/ironfish/src/primitives/transaction.test.slow.ts +++ b/ironfish/src/primitives/transaction.test.slow.ts @@ -72,7 +72,7 @@ describe('Accounts', () => { publicAddress: accountB.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -106,7 +106,7 @@ describe('Accounts', () => { publicAddress: accountB.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], diff --git a/ironfish/src/primitives/transaction.ts b/ironfish/src/primitives/transaction.ts index 8d4424bb8e..01d6e6b074 100644 --- a/ironfish/src/primitives/transaction.ts +++ b/ironfish/src/primitives/transaction.ts @@ -4,7 +4,7 @@ import { Asset, - ASSET_IDENTIFIER_LENGTH, + ASSET_ID_LENGTH, ASSET_LENGTH, ENCRYPTED_NOTE_LENGTH, PROOF_LENGTH, @@ -102,10 +102,10 @@ export class Transaction { }) this.burns = Array.from({ length: _burnsLength }, () => { - const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) + const assetId = reader.readBytes(ASSET_ID_LENGTH) const value = reader.readBigU64() - return { assetIdentifier, value } + return { assetId, value } }) this._signature = reader.readBytes(64, true) diff --git a/ironfish/src/rpc/routes/chain/getAsset.test.ts b/ironfish/src/rpc/routes/chain/getAsset.test.ts index 7953ef2ef3..f18f354b69 100644 --- a/ironfish/src/rpc/routes/chain/getAsset.test.ts +++ b/ironfish/src/rpc/routes/chain/getAsset.test.ts @@ -12,14 +12,14 @@ describe('Route chain.getAsset', () => { const routeTest = createRouteTest() it('responds with an asset', async () => { - const asset = await routeTest.node.chain.getAssetById(Asset.nativeIdentifier()) + const asset = await routeTest.node.chain.getAssetById(Asset.nativeId()) Assert.isNotNull(asset) const response = await routeTest.client.getAsset({ - identifier: asset.identifier.toString('hex'), + id: asset.id.toString('hex'), }) - expect(response.content.identifier).toEqual(asset.identifier.toString('hex')) + expect(response.content.id).toEqual(asset.id.toString('hex')) expect(response.content.metadata).toBe(asset.metadata.toString('hex')) expect(response.content.owner).toBe(asset.owner.toString('hex')) expect(response.content.nonce).toBe(asset.nonce) diff --git a/ironfish/src/rpc/routes/chain/getAsset.ts b/ironfish/src/rpc/routes/chain/getAsset.ts index e8d5f96c97..e0b5305b5b 100644 --- a/ironfish/src/rpc/routes/chain/getAsset.ts +++ b/ironfish/src/rpc/routes/chain/getAsset.ts @@ -1,19 +1,19 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { ASSET_IDENTIFIER_LENGTH } from '@ironfish/rust-nodejs' +import { ASSET_ID_LENGTH } from '@ironfish/rust-nodejs' import * as yup from 'yup' import { CurrencyUtils } from '../../../utils' import { ValidationError } from '../../adapters' import { ApiNamespace, router } from '../router' export type GetAssetRequest = { - identifier: string + id: string } export type GetAssetResponse = { createdTransactionHash: string - identifier: string + id: string metadata: string name: string nonce: number @@ -24,14 +24,14 @@ export type GetAssetResponse = { export const GetAssetRequestSchema: yup.ObjectSchema = yup .object() .shape({ - identifier: yup.string(), + id: yup.string(), }) .defined() export const GetAssetResponse: yup.ObjectSchema = yup .object({ createdTransactionHash: yup.string().defined(), - identifier: yup.string().defined(), + id: yup.string().defined(), metadata: yup.string().defined(), name: yup.string().defined(), nonce: yup.number().defined(), @@ -44,23 +44,23 @@ router.register( `${ApiNamespace.chain}/getAsset`, GetAssetRequestSchema, async (request, node): Promise => { - const identifier = Buffer.from(request.data.identifier, 'hex') + const id = Buffer.from(request.data.id, 'hex') - if (identifier.byteLength !== ASSET_IDENTIFIER_LENGTH) { + if (id.byteLength !== ASSET_ID_LENGTH) { throw new ValidationError( - `Asset identifier is invalid length, expected ${ASSET_IDENTIFIER_LENGTH} but got ${identifier.byteLength}`, + `Asset identifier is invalid length, expected ${ASSET_ID_LENGTH} but got ${id.byteLength}`, ) } - const asset = await node.chain.getAssetById(identifier) + const asset = await node.chain.getAssetById(id) if (!asset) { - throw new ValidationError(`No asset found with identifier ${request.data.identifier}`) + throw new ValidationError(`No asset found with identifier ${request.data.id}`) } request.end({ createdTransactionHash: asset.createdTransactionHash.toString('hex'), - identifier: asset.identifier.toString('hex'), + id: asset.id.toString('hex'), metadata: asset.metadata.toString('hex'), name: asset.name.toString('hex'), nonce: asset.nonce, diff --git a/ironfish/src/rpc/routes/chain/getBlock.ts b/ironfish/src/rpc/routes/chain/getBlock.ts index 483d6c0a7d..e2dee0c987 100644 --- a/ironfish/src/rpc/routes/chain/getBlock.ts +++ b/ironfish/src/rpc/routes/chain/getBlock.ts @@ -10,7 +10,7 @@ import { ApiNamespace, router } from '../router' export type GetBlockRequest = { index?: number; hash?: string } interface Operation { - operation_identifier: { index: number; network_index: number } + operation_id: { index: number; network_index: number } type: string } interface Note { @@ -20,7 +20,7 @@ interface Spend { nullifier: string } interface Transaction { - transaction_identifier: { hash: string } + transaction_id: { hash: string } operations: Array metadata: { size: number @@ -65,7 +65,7 @@ const OperationSchema = yup .object() .shape({ type: yup.string().defined(), - operation_identifier: yup + operation_id: yup .object() .shape({ index: yup.number().defined(), @@ -78,7 +78,7 @@ const OperationSchema = yup const TransactionSchema = yup .object() .shape({ - transaction_identifier: yup.object({ hash: yup.string().defined() }).defined(), + transaction_id: yup.object({ hash: yup.string().defined() }).defined(), operations: yup.array().of(OperationSchema).defined(), metadata: yup .object({ @@ -171,7 +171,7 @@ router.register( const transactionBuffer = Buffer.from(JSON.stringify(transaction.serialize())) return { - transaction_identifier: { + transaction_id: { hash: BlockHashSerdeInstance.serialize(transaction.hash()), }, operations: [], diff --git a/ironfish/src/rpc/routes/wallet/burnAsset.test.ts b/ironfish/src/rpc/routes/wallet/burnAsset.test.ts index a5654b40ac..0f4a1cc0c8 100644 --- a/ironfish/src/rpc/routes/wallet/burnAsset.test.ts +++ b/ironfish/src/rpc/routes/wallet/burnAsset.test.ts @@ -22,7 +22,7 @@ describe('burnAsset', () => { await expect( routeTest.client.burnAsset({ account: 'fake-account', - assetIdentifier: '{ url: hello }', + assetId: '{ url: hello }', fee: '1', value: '1', }), @@ -35,7 +35,7 @@ describe('burnAsset', () => { await expect( routeTest.client.burnAsset({ account: 'account', - assetIdentifier: '{ url: hello }', + assetId: '{ url: hello }', fee: '0', value: '100', }), @@ -48,7 +48,7 @@ describe('burnAsset', () => { await expect( routeTest.client.burnAsset({ account: 'account', - assetIdentifier: '{ url: hello }', + assetId: '{ url: hello }', fee: '1', value: '-1', }), @@ -63,7 +63,7 @@ describe('burnAsset', () => { const account = await useAccountFixture(wallet) const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() + const assetId = asset.id() const value = BigInt(10) const mintBlock = await useMintBlockFixture({ node, account, asset, value, sequence: 3 }) await expect(node.chain).toAddBlock(mintBlock) @@ -74,19 +74,19 @@ describe('burnAsset', () => { node: node, wallet: node.wallet, from: account, - burns: [{ assetIdentifier: asset.identifier(), value: burnValue }], + burns: [{ assetId: asset.id(), value: burnValue }], }) jest.spyOn(wallet, 'burn').mockResolvedValueOnce(burnTransaction) const response = await routeTest.client.burnAsset({ account: account.name, - assetIdentifier: assetIdentifier.toString('hex'), + assetId: assetId.toString('hex'), fee: '1', value: CurrencyUtils.encode(value), }) expect(response.content).toEqual({ - assetIdentifier: asset.identifier().toString('hex'), + assetId: asset.id().toString('hex'), hash: burnTransaction.hash().toString('hex'), }) }) diff --git a/ironfish/src/rpc/routes/wallet/burnAsset.ts b/ironfish/src/rpc/routes/wallet/burnAsset.ts index 3e02837c6f..2fe42e4ac0 100644 --- a/ironfish/src/rpc/routes/wallet/burnAsset.ts +++ b/ironfish/src/rpc/routes/wallet/burnAsset.ts @@ -9,7 +9,7 @@ import { ApiNamespace, router } from '../router' export interface BurnAssetRequest { account: string - assetIdentifier: string + assetId: string fee: string value: string expiration?: number @@ -17,14 +17,14 @@ export interface BurnAssetRequest { } export interface BurnAssetResponse { - assetIdentifier: string + assetId: string hash: string } export const BurnAssetRequestSchema: yup.ObjectSchema = yup .object({ account: yup.string().required(), - assetIdentifier: yup.string().required(), + assetId: yup.string().required(), fee: yup.string().required(), value: yup.string().required(), expiration: yup.number().optional(), @@ -34,7 +34,7 @@ export const BurnAssetRequestSchema: yup.ObjectSchema = yup export const BurnAssetResponseSchema: yup.ObjectSchema = yup .object({ - assetIdentifier: yup.string().required(), + assetId: yup.string().required(), hash: yup.string().required(), }) .defined() @@ -61,7 +61,7 @@ router.register( const transaction = await node.wallet.burn( node.memPool, account, - Buffer.from(request.data.assetIdentifier, 'hex'), + Buffer.from(request.data.assetId, 'hex'), value, fee, request.data.expirationDelta ?? node.config.get('transactionExpirationDelta'), @@ -71,7 +71,7 @@ router.register( const burn = transaction.burns[0] request.end({ - assetIdentifier: burn.assetIdentifier.toString('hex'), + assetId: burn.assetId.toString('hex'), hash: transaction.hash().toString('hex'), }) }, diff --git a/ironfish/src/rpc/routes/wallet/getBalance.ts b/ironfish/src/rpc/routes/wallet/getBalance.ts index ccf2fc4b4d..e93a657e0d 100644 --- a/ironfish/src/rpc/routes/wallet/getBalance.ts +++ b/ironfish/src/rpc/routes/wallet/getBalance.ts @@ -8,13 +8,13 @@ import { getAccount } from './utils' export type GetBalanceRequest = { account?: string - assetIdentifier?: string + assetId?: string minimumBlockConfirmations?: number } export type GetBalanceResponse = { account: string - assetIdentifier: string + assetId: string confirmed: string unconfirmed: string unconfirmedCount: number @@ -24,14 +24,14 @@ export type GetBalanceResponse = { export const GetBalanceRequestSchema: yup.ObjectSchema = yup .object({ account: yup.string().strip(true), - assetIdentifier: yup.string().optional(), + assetId: yup.string().optional(), }) .defined() export const GetBalanceResponseSchema: yup.ObjectSchema = yup .object({ account: yup.string().defined(), - assetIdentifier: yup.string().defined(), + assetId: yup.string().defined(), unconfirmed: yup.string().defined(), unconfirmedCount: yup.number().defined(), confirmed: yup.string().defined(), @@ -50,18 +50,18 @@ router.register( const account = getAccount(node, request.data.account) - let assetIdentifier = Asset.nativeIdentifier() - if (request.data.assetIdentifier) { - assetIdentifier = Buffer.from(request.data.assetIdentifier, 'hex') + let assetId = Asset.nativeId() + if (request.data.assetId) { + assetId = Buffer.from(request.data.assetId, 'hex') } - const balance = await node.wallet.getBalance(account, assetIdentifier, { + const balance = await node.wallet.getBalance(account, assetId, { minimumBlockConfirmations, }) request.end({ account: account.name, - assetIdentifier: assetIdentifier.toString('hex'), + assetId: assetId.toString('hex'), confirmed: balance.confirmed.toString(), unconfirmed: balance.unconfirmed.toString(), unconfirmedCount: balance.unconfirmedCount, diff --git a/ironfish/src/rpc/routes/wallet/getNotes.ts b/ironfish/src/rpc/routes/wallet/getNotes.ts index 81f1022f14..4b43c1dcfd 100644 --- a/ironfish/src/rpc/routes/wallet/getNotes.ts +++ b/ironfish/src/rpc/routes/wallet/getNotes.ts @@ -11,7 +11,7 @@ export type GetAccountNotesStreamRequest = { account?: string } export type GetAccountNotesStreamResponse = { value: string - assetIdentifier: string + assetId: string assetName: string memo: string sender: string @@ -30,7 +30,7 @@ export const GetAccountNotesStreamResponseSchema: yup.ObjectSchema { }) expect(response.content).toEqual({ - assetIdentifier: asset.identifier().toString('hex'), + assetId: asset.id().toString('hex'), hash: mintTransaction.hash().toString('hex'), }) }) diff --git a/ironfish/src/rpc/routes/wallet/mintAsset.ts b/ironfish/src/rpc/routes/wallet/mintAsset.ts index 540554b524..439542f167 100644 --- a/ironfish/src/rpc/routes/wallet/mintAsset.ts +++ b/ironfish/src/rpc/routes/wallet/mintAsset.ts @@ -18,7 +18,7 @@ export interface MintAssetRequest { } export interface MintAssetResponse { - assetIdentifier: string + assetId: string hash: string } @@ -36,7 +36,7 @@ export const MintAssetRequestSchema: yup.ObjectSchema = yup export const MintAssetResponseSchema: yup.ObjectSchema = yup .object({ - assetIdentifier: yup.string().required(), + assetId: yup.string().required(), hash: yup.string().required(), }) .defined() @@ -74,7 +74,7 @@ router.register( const mint = transaction.mints[0] request.end({ - assetIdentifier: mint.asset.identifier().toString('hex'), + assetId: mint.asset.id().toString('hex'), hash: transaction.hash().toString('hex'), }) }, diff --git a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts index ef86eb314c..0ac244cee5 100644 --- a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts @@ -15,7 +15,7 @@ const TEST_PARAMS = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', - assetIdentifier: Asset.nativeIdentifier().toString('hex'), + assetId: Asset.nativeId().toString('hex'), }, ], fee: BigInt(1).toString(), @@ -28,13 +28,13 @@ const TEST_PARAMS_MULTI = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', - assetIdentifier: Asset.nativeIdentifier().toString('hex'), + assetId: Asset.nativeId().toString('hex'), }, { publicAddress: 'test3', amount: BigInt(10).toString(), memo: '', - assetIdentifier: Asset.nativeIdentifier().toString('hex'), + assetId: Asset.nativeId().toString('hex'), }, ], fee: BigInt(1).toString(), @@ -143,9 +143,7 @@ describe('Transactions sendTransaction', () => { jest .spyOn(routeTest.node.wallet, 'send') - .mockRejectedValue( - new NotEnoughFundsError(Asset.nativeIdentifier(), BigInt(0), BigInt(1)), - ) + .mockRejectedValue(new NotEnoughFundsError(Asset.nativeId(), BigInt(0), BigInt(1))) jest.spyOn(routeTest.node.wallet, 'getBalance').mockResolvedValueOnce({ unconfirmed: BigInt(11), confirmed: BigInt(11), diff --git a/ironfish/src/rpc/routes/wallet/sendTransaction.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.ts index 4c4a28ff76..48e00c245d 100644 --- a/ironfish/src/rpc/routes/wallet/sendTransaction.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.ts @@ -15,7 +15,7 @@ export type SendTransactionRequest = { publicAddress: string amount: string memo: string - assetIdentifier?: string + assetId?: string }[] fee: string expiration?: number | null @@ -27,7 +27,7 @@ export type SendTransactionResponse = { publicAddress: string amount: string memo: string - assetIdentifier?: string + assetId?: string }[] fromAccountName: string hash: string @@ -43,7 +43,7 @@ export const SendTransactionRequestSchema: yup.ObjectSchema( } const receives = transaction.receives.map((receive) => { - let assetIdentifier = Asset.nativeIdentifier() - if (receive.assetIdentifier) { - assetIdentifier = Buffer.from(receive.assetIdentifier, 'hex') + let assetId = Asset.nativeId() + if (receive.assetId) { + assetId = Buffer.from(receive.assetId, 'hex') } return { publicAddress: receive.publicAddress, amount: CurrencyUtils.decode(receive.amount), memo: receive.memo, - assetIdentifier, + assetId, } }) @@ -118,19 +118,19 @@ router.register( } const totalByAssetIdentifier = new BufferMap() - totalByAssetIdentifier.set(Asset.nativeIdentifier(), fee) - for (const { assetIdentifier, amount } of receives) { + totalByAssetIdentifier.set(Asset.nativeId(), fee) + for (const { assetId, amount } of receives) { if (amount < 0) { throw new ValidationError(`Invalid transaction amount ${amount}.`) } - const sum = totalByAssetIdentifier.get(assetIdentifier) ?? BigInt(0) - totalByAssetIdentifier.set(assetIdentifier, sum + amount) + const sum = totalByAssetIdentifier.get(assetId) ?? BigInt(0) + totalByAssetIdentifier.set(assetId, sum + amount) } // Check that the node account is updated - for (const [assetIdentifier, sum] of totalByAssetIdentifier) { - const balance = await node.wallet.getBalance(account, assetIdentifier) + for (const [assetId, sum] of totalByAssetIdentifier) { + const balance = await node.wallet.getBalance(account, assetId) if (balance.confirmed < sum) { throw new ValidationError( diff --git a/ironfish/src/strategy.test.slow.ts b/ironfish/src/strategy.test.slow.ts index 4c0dd87a59..a853165f33 100644 --- a/ironfish/src/strategy.test.slow.ts +++ b/ironfish/src/strategy.test.slow.ts @@ -95,7 +95,7 @@ describe('Demonstrate the Sapling API', () => { it('Can create a miner reward', () => { const owner = generateKeyFromPrivateKey(spenderKey.spending_key).public_address - minerNote = new NativeNote(owner, BigInt(42), '', Asset.nativeIdentifier(), owner) + minerNote = new NativeNote(owner, BigInt(42), '', Asset.nativeId(), owner) const transaction = new NativeTransaction(spenderKey.spending_key) transaction.receive(minerNote) @@ -140,7 +140,7 @@ describe('Demonstrate the Sapling API', () => { receiverKey.public_address, BigInt(40), '', - Asset.nativeIdentifier(), + Asset.nativeId(), minerNote.owner(), ) transaction.receive(outputNote) @@ -288,14 +288,14 @@ describe('Demonstrate the Sapling API', () => { spenderKey.public_address, BigInt(10), '', - Asset.nativeIdentifier(), + Asset.nativeId(), receiverAddress, ) const receiverNoteToSelf = new NativeNote( receiverAddress, BigInt(29), '', - Asset.nativeIdentifier(), + Asset.nativeId(), receiverAddress, ) diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures.ts index 6d2afb2afb..b01fee8bc2 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures.ts @@ -261,7 +261,7 @@ export async function useBurnBlockFixture(options: { node: options.node, wallet: options.node.wallet, from: options.account, - burns: [{ assetIdentifier: options.asset.identifier(), value: options.value }], + burns: [{ assetId: options.asset.id(), value: options.value }], }) return useMinerBlockFixture(options.node.chain, options.sequence, undefined, undefined, [ @@ -277,12 +277,12 @@ export async function usePostTxFixture(options: { fee?: bigint amount?: bigint expiration?: number - assetIdentifier?: Buffer + assetId?: Buffer receives?: { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[] mints?: MintDescription[] burns?: BurnDescription[] @@ -311,7 +311,7 @@ export async function useTxFixture( publicAddress: to.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -341,7 +341,7 @@ export async function useBlockWithRawTxFixture( pool: WorkerPool, sender: Account, notesToSpend: NoteEncrypted[], - receives: { publicAddress: string; amount: bigint; memo: string; assetIdentifier: Buffer }[], + receives: { publicAddress: string; amount: bigint; memo: string; assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], sequence: number, @@ -481,7 +481,7 @@ export async function useBlockWithTx( publicAddress: to.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -538,7 +538,7 @@ export async function useBlockWithTxs( publicAddress: to.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], diff --git a/ironfish/src/testUtilities/helpers/transaction.ts b/ironfish/src/testUtilities/helpers/transaction.ts index 032575696d..1e79124eca 100644 --- a/ironfish/src/testUtilities/helpers/transaction.ts +++ b/ironfish/src/testUtilities/helpers/transaction.ts @@ -32,12 +32,12 @@ export async function createRawTransaction(options: { fee?: bigint amount?: bigint expiration?: number - assetIdentifier?: Buffer + assetId?: Buffer receives?: { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[] mints?: MintDescription[] burns?: BurnDescription[] @@ -49,7 +49,7 @@ export async function createRawTransaction(options: { publicAddress: options.to.publicAddress, amount: options.amount ?? 1n, memo: '', - assetIdentifier: options.assetIdentifier ?? Asset.nativeIdentifier(), + assetId: options.assetId ?? Asset.nativeId(), }) } diff --git a/ironfish/src/utils/asset.ts b/ironfish/src/utils/asset.ts index 92e6ff5ea6..c0133c27dd 100644 --- a/ironfish/src/utils/asset.ts +++ b/ironfish/src/utils/asset.ts @@ -3,6 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Asset } from '@ironfish/rust-nodejs' -export function isNativeIdentifier(assetIdentifier: string): boolean { - return Buffer.from(assetIdentifier, 'hex').equals(Asset.nativeIdentifier()) +export function isNativeIdentifier(assetId: string): boolean { + return Buffer.from(assetId, 'hex').equals(Asset.nativeId()) } diff --git a/ironfish/src/utils/currency.ts b/ironfish/src/utils/currency.ts index 36d5ea12f5..89fb6ba1ea 100644 --- a/ironfish/src/utils/currency.ts +++ b/ironfish/src/utils/currency.ts @@ -40,11 +40,7 @@ export class CurrencyUtils { /* * Renders ore as iron for human-readable purposes */ - static renderIron( - amount: bigint | string, - includeTicker = false, - assetIdentifier?: string, - ): string { + static renderIron(amount: bigint | string, includeTicker = false, assetId?: string): string { if (typeof amount === 'string') { amount = this.decode(amount) } @@ -53,8 +49,8 @@ export class CurrencyUtils { if (includeTicker) { let ticker = '$IRON' - if (assetIdentifier && !isNativeIdentifier(assetIdentifier)) { - ticker = assetIdentifier + if (assetId && !isNativeIdentifier(assetId)) { + ticker = assetId } return `${ticker} ${iron}` } @@ -65,11 +61,7 @@ export class CurrencyUtils { /* * Renders ore for human-readable purposes */ - static renderOre( - amount: bigint | string, - includeTicker = false, - assetIdentifier?: string, - ): string { + static renderOre(amount: bigint | string, includeTicker = false, assetId?: string): string { if (typeof amount === 'string') { amount = this.decode(amount) } @@ -78,8 +70,8 @@ export class CurrencyUtils { if (includeTicker) { let ticker = '$ORE' - if (assetIdentifier && !isNativeIdentifier(assetIdentifier)) { - ticker = assetIdentifier + if (assetId && !isNativeIdentifier(assetId)) { + ticker = assetId } return `${ticker} ${ore}` } diff --git a/ironfish/src/wallet/account.test.ts b/ironfish/src/wallet/account.test.ts index d253f8f6e5..46197bc2f9 100644 --- a/ironfish/src/wallet/account.test.ts +++ b/ironfish/src/wallet/account.test.ts @@ -116,7 +116,7 @@ describe('Accounts', () => { AsyncUtils.materialize(node.wallet.walletDb.loadNoteHashesNotOnChain(account)), ).resolves.toHaveLength(1) - await expect(account.getBalance(1, Asset.nativeIdentifier(), 1)).resolves.toMatchObject({ + await expect(account.getBalance(1, Asset.nativeId(), 1)).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -129,7 +129,7 @@ describe('Accounts', () => { AsyncUtils.materialize(node.wallet.walletDb.loadNoteHashesNotOnChain(account)), ).resolves.toHaveLength(0) - await expect(account.getBalance(1, Asset.nativeIdentifier(), 1)).resolves.toMatchObject({ + await expect(account.getBalance(1, Asset.nativeId(), 1)).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -214,13 +214,13 @@ describe('Accounts', () => { sequence: null, } - await account.saveUnconfirmedBalance(Asset.nativeIdentifier(), nativeBalance) - await account.saveUnconfirmedBalance(asset.identifier(), mintedAssetBalance) + await account.saveUnconfirmedBalance(Asset.nativeId(), nativeBalance) + await account.saveUnconfirmedBalance(asset.id(), mintedAssetBalance) const balances = await account.getUnconfirmedBalances() const expectedBalances = new BufferMap([ - [Asset.nativeIdentifier(), nativeBalance], - [asset.identifier(), mintedAssetBalance], + [Asset.nativeId(), nativeBalance], + [asset.id(), mintedAssetBalance], ]) expect(balances.size).toBe(expectedBalances.size) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index bf21db56d3..f6ba7c4b92 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -91,10 +91,10 @@ export class Account { } async *getUnspentNotes( - assetIdentifier: Buffer, + assetId: Buffer, ): AsyncGenerator { for await (const decryptedNote of this.getNotes()) { - if (!decryptedNote.note.assetIdentifier().equals(assetIdentifier)) { + if (!decryptedNote.note.assetId().equals(assetId)) { continue } @@ -154,7 +154,7 @@ export class Account { sequence, } - assetBalanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) + assetBalanceDeltas.increment(note.note.assetId(), note.note.value()) await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -169,7 +169,7 @@ export class Account { Assert.isNotUndefined(note) - assetBalanceDeltas.increment(note.note.assetIdentifier(), -note.note.value()) + assetBalanceDeltas.increment(note.note.assetId(), -note.note.value()) const spentNote = { ...note, spent: true } await this.walletDb.saveDecryptedNote(this, spentNoteHash, spentNote, tx) @@ -222,7 +222,7 @@ export class Account { sequence: null, } - assetBalanceDeltas.increment(note.note.assetIdentifier(), note.note.value()) + assetBalanceDeltas.increment(note.note.assetId(), note.note.value()) await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -237,7 +237,7 @@ export class Account { Assert.isNotUndefined(note) - assetBalanceDeltas.increment(note.note.assetIdentifier(), -note.note.value()) + assetBalanceDeltas.increment(note.note.assetId(), -note.note.value()) const spentNote = { ...note, spent: true } await this.walletDb.saveDecryptedNote(this, spentNoteHash, spentNote, tx) @@ -280,7 +280,7 @@ export class Account { } balanceDeltas.increment( - decryptedNoteValue.note.assetIdentifier(), + decryptedNoteValue.note.assetId(), -decryptedNoteValue.note.value(), ) @@ -315,7 +315,7 @@ export class Account { Assert.isNotUndefined(spentNote) - balanceDeltas.increment(spentNote.note.assetIdentifier(), spentNote.note.value()) + balanceDeltas.increment(spentNote.note.assetId(), spentNote.note.value()) } await this.walletDb.savePendingTransactionHash( @@ -454,7 +454,7 @@ export class Account { */ async getBalance( headSequence: number, - assetIdentifier: Buffer, + assetId: Buffer, minimumBlockConfirmations: number, tx?: IDatabaseTransaction, ): Promise<{ @@ -464,7 +464,7 @@ export class Account { }> { let unconfirmedCount = 0 - const { unconfirmed } = await this.getUnconfirmedBalance(assetIdentifier, tx) + const { unconfirmed } = await this.getUnconfirmedBalance(assetId, tx) let confirmed = unconfirmed if (minimumBlockConfirmations > 0) { @@ -481,7 +481,7 @@ export class Account { unconfirmedSequenceEnd, tx, )) { - if (!note.note.assetIdentifier().equals(assetIdentifier)) { + if (!note.note.assetId().equals(assetId)) { continue } @@ -501,20 +501,17 @@ export class Account { async getUnconfirmedBalances(tx?: IDatabaseTransaction): Promise> { const unconfirmedBalances = new BufferMap() - for await (const { assetIdentifier, balance } of this.walletDb.getUnconfirmedBalances( - this, - tx, - )) { - unconfirmedBalances.set(assetIdentifier, balance) + for await (const { assetId, balance } of this.walletDb.getUnconfirmedBalances(this, tx)) { + unconfirmedBalances.set(assetId, balance) } return unconfirmedBalances } async getUnconfirmedBalance( - assetIdentifier: Buffer, + assetId: Buffer, tx?: IDatabaseTransaction, ): Promise { - return this.walletDb.getUnconfirmedBalance(this, assetIdentifier, tx) + return this.walletDb.getUnconfirmedBalance(this, assetId, tx) } async updateUnconfirmedBalances( @@ -523,12 +520,12 @@ export class Account { sequence: number | null, tx?: IDatabaseTransaction, ): Promise { - for (const [assetIdentifier, balanceDelta] of balanceDeltas) { - const currentUnconfirmedBalance = await this.getUnconfirmedBalance(assetIdentifier, tx) + for (const [assetId, balanceDelta] of balanceDeltas) { + const currentUnconfirmedBalance = await this.getUnconfirmedBalance(assetId, tx) await this.walletDb.saveUnconfirmedBalance( this, - assetIdentifier, + assetId, { unconfirmed: currentUnconfirmedBalance.unconfirmed + balanceDelta, blockHash, @@ -540,11 +537,11 @@ export class Account { } async saveUnconfirmedBalance( - assetIdentifier: Buffer, + assetId: Buffer, balance: BalanceValue, tx?: IDatabaseTransaction, ): Promise { - await this.walletDb.saveUnconfirmedBalance(this, assetIdentifier, balance, tx) + await this.walletDb.saveUnconfirmedBalance(this, assetId, balance, tx) } async getHeadHash(tx?: IDatabaseTransaction): Promise { @@ -582,8 +579,8 @@ export function calculateAccountPrefix(id: string): Buffer { } class AssetBalanceDeltas extends BufferMap { - increment(assetIdentifier: Buffer, delta: bigint): void { - const currentDelta = this.get(assetIdentifier) ?? 0n - this.set(assetIdentifier, currentDelta + delta) + increment(assetId: Buffer, delta: bigint): void { + const currentDelta = this.get(assetId) ?? 0n + this.set(assetId, currentDelta + delta) } } diff --git a/ironfish/src/wallet/errors.ts b/ironfish/src/wallet/errors.ts index 72f7b5c55d..81fd97af26 100644 --- a/ironfish/src/wallet/errors.ts +++ b/ironfish/src/wallet/errors.ts @@ -5,9 +5,9 @@ export class NotEnoughFundsError extends Error { name = this.constructor.name - constructor(assetIdentifier: Buffer, amount: bigint, amountNeeded: bigint) { + constructor(assetId: Buffer, amount: bigint, amountNeeded: bigint) { super() - this.message = `Insufficient funds: Needed ${amountNeeded.toString()} but have ${amount.toString()} for asset '${assetIdentifier.toString( + this.message = `Insufficient funds: Needed ${amountNeeded.toString()} but have ${amount.toString()} for asset '${assetId.toString( 'hex', )}'` } diff --git a/ironfish/src/wallet/wallet.test.slow.ts b/ironfish/src/wallet/wallet.test.slow.ts index a9e34cbc86..009399f9eb 100644 --- a/ironfish/src/wallet/wallet.test.slow.ts +++ b/ironfish/src/wallet/wallet.test.slow.ts @@ -42,9 +42,7 @@ describe('Accounts', () => { await node.wallet.updateHead() // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -52,9 +50,7 @@ describe('Accounts', () => { await node.wallet.updateHead() // Balance after adding the genesis block should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -68,9 +64,7 @@ describe('Accounts', () => { await node.wallet.updateHead() // Account should now have a balance of 2000000000 after adding the miner's fee - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -85,18 +79,14 @@ describe('Accounts', () => { const account = await node.wallet.createAccount('test', true) // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) // Balance after adding the genesis block should be 0 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -109,9 +99,7 @@ describe('Accounts', () => { // Account should now have a balance of 2000000000 after adding the miner's fee await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -125,7 +113,7 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -145,9 +133,7 @@ describe('Accounts', () => { // Balance after adding the transaction that spends 2 should be 1999999998 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999998), unconfirmed: BigInt(1999999998), }) @@ -162,18 +148,14 @@ describe('Accounts', () => { const account = await node.wallet.createAccount('test', true) // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) // Balance after adding the genesis block should be 0 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -186,9 +168,7 @@ describe('Accounts', () => { // Account should now have a balance of 2000000000 after adding the miner's fee await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -202,7 +182,7 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -225,9 +205,7 @@ describe('Accounts', () => { // Balance after adding the transaction that spends 2 should be 1999999998 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999998), unconfirmed: BigInt(1999999998), }) @@ -242,18 +220,14 @@ describe('Accounts', () => { const account = await node.wallet.createAccount('test', true) // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) // Balance after adding the genesis block should be 0 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -266,9 +240,7 @@ describe('Accounts', () => { // Account should now have a balance of 2000000000 after adding the miner's fee await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -281,19 +253,19 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: 'recipient 1', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, { publicAddress: generateKey().public_address, amount: BigInt(2), memo: 'recipient 2', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, { publicAddress: generateKey().public_address, amount: BigInt(2), memo: 'recipient 3', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -316,9 +288,7 @@ describe('Accounts', () => { // Balance after adding the transaction that spends 6 should be 1999999994 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999994), unconfirmed: BigInt(1999999994), }) @@ -338,7 +308,7 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -360,18 +330,14 @@ describe('Accounts', () => { node.wallet['isStarted'] = true // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) // Balance after adding the genesis block should be 0 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -384,9 +350,7 @@ describe('Accounts', () => { // Account should now have a balance of 2000000000 after adding the miner's fee await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -400,7 +364,7 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -408,18 +372,14 @@ describe('Accounts', () => { ) // Transaction should be pending - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) // Expiring transactions should not yet remove the transaction await node.wallet.expireTransactions() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -437,9 +397,7 @@ describe('Accounts', () => { // Expiring transactions should now remove the transaction await node.wallet.updateHead() await node.wallet.expireTransactions() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -460,18 +418,14 @@ describe('Accounts', () => { await node.wallet.createAccount('test2') // Initial balance should be 0 - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) // Balance after adding the genesis block should be 0 await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -483,9 +437,7 @@ describe('Accounts', () => { // Account should now have a balance of 2000000000 after adding the miner's fee await node.wallet.updateHead() - await expect( - node.wallet.getBalance(account, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -499,7 +451,7 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), @@ -547,9 +499,7 @@ describe('Accounts', () => { // Initial balance should be 2000000000 await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -563,7 +513,7 @@ describe('Accounts', () => { publicAddress: accountB.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -594,7 +544,7 @@ describe('Accounts', () => { publicAddress: accountC.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -637,21 +587,17 @@ describe('Accounts', () => { // Update account head and check all balances await nodeA.wallet.updateHead() await nodeB.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) - await expect( - nodeB.wallet.getBalance(accountB, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeB.wallet.getBalance(accountB, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(4000000000), unconfirmed: BigInt(4000000000), }) @@ -663,14 +609,12 @@ describe('Accounts', () => { // Copy block B2 to nodeA await nodeA.chain.addBlock(blockB2) await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(4000000000), unconfirmed: BigInt(4000000000), @@ -713,7 +657,7 @@ describe('Accounts', () => { publicAddress: accountB.publicAddress, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -750,20 +694,18 @@ describe('Accounts', () => { await nodeA.wallet.updateHead() await nodeB.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999998), unconfirmed: BigInt(1999999998), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(2), unconfirmed: BigInt(2), }) await expect( - nodeB.wallet.getBalance(accountANodeB, Asset.nativeIdentifier()), + nodeB.wallet.getBalance(accountANodeB, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), @@ -776,14 +718,12 @@ describe('Accounts', () => { // B should not have confirmed coins yet because the transaction isn't on a block // A should still have confirmed coins because the transaction isn't on a block - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), @@ -829,7 +769,7 @@ describe('Accounts', () => { publicAddress: accountB.publicAddress, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [], @@ -876,20 +816,18 @@ describe('Accounts', () => { await nodeA.wallet.updateHead() await nodeB.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999998), unconfirmed: BigInt(1999999998), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(2), unconfirmed: BigInt(2), }) await expect( - nodeB.wallet.getBalance(accountANodeB, Asset.nativeIdentifier()), + nodeB.wallet.getBalance(accountANodeB, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), @@ -902,14 +840,12 @@ describe('Accounts', () => { // B should not have confirmed coins yet because the transaction isn't on a block // A should still have confirmed coins because the transaction isn't on a block - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) await expect( - nodeA.wallet.getBalance(accountBNodeA, Asset.nativeIdentifier()), + nodeA.wallet.getBalance(accountBNodeA, Asset.nativeId()), ).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index 5ebbb3b1f3..a2dbd9a94e 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -54,9 +54,7 @@ describe('Accounts', () => { // Check nodeA balance await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(2000000000), unconfirmed: BigInt(2000000000), }) @@ -86,9 +84,7 @@ describe('Accounts', () => { }) await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -147,7 +143,7 @@ describe('Accounts', () => { accountA['walletDb'].loadNotesNotOnChain(accountA), ) // set minimumBlockConfirmations so that balance considers confirmations - const balanceA = await nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier(), { + const balanceA = await nodeA.wallet.getBalance(accountA, Asset.nativeId(), { minimumBlockConfirmations: 2, }) @@ -185,9 +181,7 @@ describe('Accounts', () => { await expect(nodeA.chain).toAddBlock(blockA2) await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(1999999998), unconfirmed: BigInt(1999999998), }) @@ -202,9 +196,7 @@ describe('Accounts', () => { expect(nodeA.chain.head.hash.equals(blockB3.header.hash)).toBe(true) await nodeA.wallet.updateHead() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ + await expect(nodeA.wallet.getBalance(accountA, Asset.nativeId())).resolves.toMatchObject({ confirmed: BigInt(0), unconfirmed: BigInt(0), }) @@ -430,11 +422,11 @@ describe('Accounts', () => { expect(nodeA.chain.head.hash.equals(blockA5.header.hash)).toBe(true) expect(nodeB.chain.head.hash.equals(blockA5.header.hash)).toBe(true) - expect(await nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier())).toMatchObject({ + expect(await nodeA.wallet.getBalance(accountA, Asset.nativeId())).toMatchObject({ confirmed: BigInt(6000000000), unconfirmed: BigInt(10000000000), }) - expect(await nodeB.wallet.getBalance(accountB, Asset.nativeIdentifier())).toMatchObject({ + expect(await nodeB.wallet.getBalance(accountB, Asset.nativeId())).toMatchObject({ confirmed: BigInt(0), }) }) @@ -956,12 +948,10 @@ describe('Accounts', () => { node: node, wallet: node.wallet, from: account, - burns: [{ assetIdentifier: asset.identifier(), value: burnValue }], + burns: [{ assetId: asset.id(), value: burnValue }], }) - expect(transaction.burns).toEqual([ - { assetIdentifier: asset.identifier(), value: burnValue }, - ]) + expect(transaction.burns).toEqual([{ assetId: asset.id(), value: burnValue }]) }) it('subtracts balance for the asset from the wallet', async () => { @@ -989,7 +979,7 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(burnBlock) await node.wallet.updateHead() - expect(await node.wallet.getBalance(account, asset.identifier())).toEqual({ + expect(await node.wallet.getBalance(account, asset.id())).toEqual({ unconfirmed: BigInt(8), unconfirmedCount: 0, confirmed: BigInt(8), @@ -1008,7 +998,7 @@ describe('Accounts', () => { await node.wallet.updateHead() const asset = new Asset(account.spendingKey, 'mint-asset', 'metadata') - const assetIdentifier = asset.identifier() + const assetId = asset.id() const mintValue = BigInt(10) // Mint some coins const blockB = await useBlockFixture(node.chain, async () => { @@ -1030,7 +1020,7 @@ describe('Accounts', () => { }) await expect(node.chain).toAddBlock(blockB) await node.wallet.updateHead() - await expect(node.wallet.getBalance(account, asset.identifier())).resolves.toMatchObject({ + await expect(node.wallet.getBalance(account, asset.id())).resolves.toMatchObject({ confirmed: mintValue, }) @@ -1042,7 +1032,7 @@ describe('Accounts', () => { // Check what notes would be spent const { amount, notes } = await node.wallet.createSpendsForAsset( account, - assetIdentifier, + assetId, BigInt(2), ) expect(amount).toEqual(mintValue) @@ -1151,7 +1141,7 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(blockA1) await node.wallet.updateHead() - const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) + const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceBefore.unconfirmed).toEqual(2000000000n) const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) @@ -1159,7 +1149,7 @@ describe('Accounts', () => { await node.wallet.connectBlock(blockA2.header, [accountA, accountB]) - const balanceAfter = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) + const balanceAfter = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceAfter.unconfirmed).toEqual(1999999998n) }) }) @@ -1239,7 +1229,7 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(blockA1) await node.wallet.updateHead() - const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) + const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceBefore.unconfirmed).toEqual(2000000000n) const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) @@ -1247,7 +1237,7 @@ describe('Accounts', () => { await node.wallet.updateHead() - const balanceAfterConnect = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) + const balanceAfterConnect = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceAfterConnect.unconfirmed).toEqual(1999999998n) await node.chain.db.transaction(async (tx) => { @@ -1256,9 +1246,7 @@ describe('Accounts', () => { await node.wallet.updateHead() - const balanceAfterDisconnect = await accountA.getUnconfirmedBalance( - Asset.nativeIdentifier(), - ) + const balanceAfterDisconnect = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceAfterDisconnect.unconfirmed).toEqual(2000000000n) }) }) diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 2b63533433..8d02420998 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -585,7 +585,7 @@ export class Wallet { async getBalance( account: Account, - assetIdentifier: Buffer, + assetId: Buffer, options?: { minimumBlockConfirmations?: number }, ): Promise<{ unconfirmedCount: number @@ -610,13 +610,13 @@ export class Wallet { } } - return account.getBalance(headSequence, assetIdentifier, minimumBlockConfirmations, tx) + return account.getBalance(headSequence, assetId, minimumBlockConfirmations, tx) }) } private async *getUnspentNotes( account: Account, - assetIdentifier: Buffer, + assetId: Buffer, options?: { minimumBlockConfirmations?: number }, @@ -629,7 +629,7 @@ export class Wallet { return } - for await (const decryptedNote of account.getUnspentNotes(assetIdentifier)) { + for await (const decryptedNote of account.getUnspentNotes(assetId)) { if (minimumBlockConfirmations > 0) { if (!decryptedNote.sequence) { continue @@ -653,7 +653,7 @@ export class Wallet { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], transactionFee: bigint, transactionExpirationDelta: number, @@ -742,7 +742,7 @@ export class Wallet { async burn( memPool: MemPool, account: Account, - assetIdentifier: Buffer, + assetId: Buffer, value: bigint, fee: bigint, transactionExpirationDelta: number, @@ -762,7 +762,7 @@ export class Wallet { account, [], [], - [{ assetIdentifier, value }], + [{ assetId, value }], fee, expiration, ) @@ -788,7 +788,7 @@ export class Wallet { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], @@ -816,7 +816,7 @@ export class Wallet { receive.publicAddress, receive.amount, receive.memo, - receive.assetIdentifier, + receive.assetId, sender.publicAddress, ) @@ -873,16 +873,16 @@ export class Wallet { }, ): BufferMap { const amountsNeeded = new BufferMap() - amountsNeeded.set(Asset.nativeIdentifier(), options.fee) + amountsNeeded.set(Asset.nativeId(), options.fee) for (const receive of raw.receives) { - const currentAmount = amountsNeeded.get(receive.note.assetIdentifier()) ?? BigInt(0) - amountsNeeded.set(receive.note.assetIdentifier(), currentAmount + receive.note.value()) + const currentAmount = amountsNeeded.get(receive.note.assetId()) ?? BigInt(0) + amountsNeeded.set(receive.note.assetId(), currentAmount + receive.note.value()) } for (const burn of raw.burns) { - const currentAmount = amountsNeeded.get(burn.assetIdentifier) ?? BigInt(0) - amountsNeeded.set(burn.assetIdentifier, currentAmount + burn.value) + const currentAmount = amountsNeeded.get(burn.assetId) ?? BigInt(0) + amountsNeeded.set(burn.assetId, currentAmount + burn.value) } return amountsNeeded @@ -894,15 +894,11 @@ export class Wallet { ): Promise> { const notesToSpend: Array<{ note: Note; witness: NoteWitness }> = [] - for (const [assetIdentifier, amountNeeded] of amountsNeeded.entries()) { - const { amount, notes } = await this.createSpendsForAsset( - sender, - assetIdentifier, - amountNeeded, - ) + for (const [assetId, amountNeeded] of amountsNeeded.entries()) { + const { amount, notes } = await this.createSpendsForAsset(sender, assetId, amountNeeded) if (amount < amountNeeded) { - throw new NotEnoughFundsError(assetIdentifier, amount, amountNeeded) + throw new NotEnoughFundsError(assetId, amount, amountNeeded) } notesToSpend.push(...notes) @@ -913,13 +909,13 @@ export class Wallet { async createSpendsForAsset( sender: Account, - assetIdentifier: Buffer, + assetId: Buffer, amountNeeded: bigint, ): Promise<{ amount: bigint; notes: Array<{ note: Note; witness: NoteWitness }> }> { let amount = BigInt(0) const notes: Array<{ note: Note; witness: NoteWitness }> = [] - for await (const unspentNote of this.getUnspentNotes(sender, assetIdentifier)) { + for await (const unspentNote of this.getUnspentNotes(sender, assetId)) { if (unspentNote.note.value() <= BigInt(0)) { continue } diff --git a/ironfish/src/wallet/walletdb/transactionValue.test.ts b/ironfish/src/wallet/walletdb/transactionValue.test.ts index 2da010800d..f235031999 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.test.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.test.ts @@ -22,7 +22,7 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) const assetBalanceDeltas = new BufferMap() - assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) const value: TransactionValue = { transaction, @@ -45,7 +45,7 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) const assetBalanceDeltas = new BufferMap() - assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) const value: TransactionValue = { transaction, @@ -68,7 +68,7 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) const assetBalanceDeltas = new BufferMap() - assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) const value: TransactionValue = { transaction, @@ -117,8 +117,8 @@ describe('TransactionValueEncoding', () => { const accountA = await useAccountFixture(wallet, 'accountA') const testAsset = new Asset(accountA.spendingKey, 'test-asset', 'test-asset-metadata') - assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) - assetBalanceDeltas.set(testAsset.identifier(), 1n) + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) + assetBalanceDeltas.set(testAsset.id(), 1n) const value: TransactionValue = { transaction, @@ -142,7 +142,7 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) const assetBalanceDeltas = new BufferMap() - assetBalanceDeltas.set(Asset.nativeIdentifier(), -transaction.fee()) + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) const value: TransactionValue = { transaction, diff --git a/ironfish/src/wallet/walletdb/transactionValue.ts b/ironfish/src/wallet/walletdb/transactionValue.ts index 25b21e07c9..b0304a90eb 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.ts @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { IDatabaseEncoding } from '../../storage/database/types' -import { ASSET_IDENTIFIER_LENGTH } from '@ironfish/rust-nodejs' +import { ASSET_ID_LENGTH } from '@ironfish/rust-nodejs' import { BufferMap } from 'buffer-map' import bufio from 'bufio' import { Transaction } from '../../primitives' @@ -47,8 +47,8 @@ export class TransactionValueEncoding implements IDatabaseEncoding { - const unconfirmedBalance = await this.balances.get([account.prefix, assetIdentifier], tx) + const unconfirmedBalance = await this.balances.get([account.prefix, assetId], tx) return ( unconfirmedBalance ?? { @@ -650,22 +650,22 @@ export class WalletDB { async *getUnconfirmedBalances( account: Account, tx?: IDatabaseTransaction, - ): AsyncGenerator<{ assetIdentifier: Buffer; balance: BalanceValue }> { - for await (const [[_, assetIdentifier], balance] of this.balances.getAllIter( + ): AsyncGenerator<{ assetId: Buffer; balance: BalanceValue }> { + for await (const [[_, assetId], balance] of this.balances.getAllIter( tx, account.prefixRange, )) { - yield { assetIdentifier, balance } + yield { assetId, balance } } } async saveUnconfirmedBalance( account: Account, - assetIdentifier: Buffer, + assetId: Buffer, balance: BalanceValue, tx?: IDatabaseTransaction, ): Promise { - await this.balances.put([account.prefix, assetIdentifier], balance, tx) + await this.balances.put([account.prefix, assetId], balance, tx) } async clearBalance(account: Account, tx?: IDatabaseTransaction): Promise { diff --git a/ironfish/src/workerPool/pool.ts b/ironfish/src/workerPool/pool.ts index 44b9ee5e74..c428285d00 100644 --- a/ironfish/src/workerPool/pool.ts +++ b/ironfish/src/workerPool/pool.ts @@ -158,7 +158,7 @@ export class WorkerPool { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], diff --git a/ironfish/src/workerPool/tasks/createMinersFee.ts b/ironfish/src/workerPool/tasks/createMinersFee.ts index 7d5d4e0e6b..3aad179e23 100644 --- a/ironfish/src/workerPool/tasks/createMinersFee.ts +++ b/ironfish/src/workerPool/tasks/createMinersFee.ts @@ -82,7 +82,7 @@ export class CreateMinersFeeTask extends WorkerTask { minerPublicAddress, amount, memo, - Asset.nativeIdentifier(), + Asset.nativeId(), minerPublicAddress, ) diff --git a/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts b/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts index def0cdb786..4062783bc4 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts @@ -86,7 +86,7 @@ describe('CreateTransactionRequest', () => { publicAddress: '', amount: BigInt(5), memo: '👁️🏃🐟', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [ @@ -97,7 +97,7 @@ describe('CreateTransactionRequest', () => { ], [ { - assetIdentifier: burnAsset.identifier(), + assetId: burnAsset.id(), value: BigInt(2), }, ], @@ -164,7 +164,7 @@ describe('CreateTransactionTask', () => { publicAddress: account.publicAddress, amount: BigInt(1), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], [ @@ -175,7 +175,7 @@ describe('CreateTransactionTask', () => { ], [ { - assetIdentifier: asset.identifier(), + assetId: asset.id(), value: burnValue, }, ], @@ -197,16 +197,16 @@ describe('CreateTransactionTask', () => { ).decryptNoteForOwner(account.incomingViewKey) Assert.isNotUndefined(decryptedNote) - const identifier = decryptedNote.assetIdentifier() - const value = outputValuesByAssetIdentifier.get(identifier) || BigInt(0) - outputValuesByAssetIdentifier.set(identifier, value + decryptedNote.value()) + const id = decryptedNote.assetId() + const value = outputValuesByAssetIdentifier.get(id) || BigInt(0) + outputValuesByAssetIdentifier.set(id, value + decryptedNote.value()) } - const nativeAssetValue = outputValuesByAssetIdentifier.get(Asset.nativeIdentifier()) + const nativeAssetValue = outputValuesByAssetIdentifier.get(Asset.nativeId()) Assert.isNotUndefined(nativeAssetValue) expect(nativeAssetValue).toEqual(2000000000n - fee) - const mintedAssetValue = outputValuesByAssetIdentifier.get(asset.identifier()) + const mintedAssetValue = outputValuesByAssetIdentifier.get(asset.id()) Assert.isNotUndefined(mintedAssetValue) expect(mintedAssetValue).toEqual(mintValue - burnValue) }) diff --git a/ironfish/src/workerPool/tasks/createTransaction.ts b/ironfish/src/workerPool/tasks/createTransaction.ts index 3ad21d86d0..357e460b4f 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.ts @@ -2,13 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { - Asset, - ASSET_IDENTIFIER_LENGTH, - ASSET_LENGTH, - Note, - Transaction, -} from '@ironfish/rust-nodejs' +import { Asset, ASSET_ID_LENGTH, ASSET_LENGTH, Note, Transaction } from '@ironfish/rust-nodejs' import bufio from 'bufio' import { Witness } from '../../merkletree' import { NoteHasher } from '../../merkletree/hasher' @@ -39,7 +33,7 @@ export class CreateTransactionRequest extends WorkerMessage { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[] readonly mints: MintDescription[] readonly burns: BurnDescription[] @@ -58,7 +52,7 @@ export class CreateTransactionRequest extends WorkerMessage { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], @@ -105,7 +99,7 @@ export class CreateTransactionRequest extends WorkerMessage { bw.writeVarString(receive.publicAddress) bw.writeVarBytes(BigIntUtils.toBytesBE(receive.amount)) bw.writeVarString(receive.memo, 'utf8') - bw.writeBytes(receive.assetIdentifier) + bw.writeBytes(receive.assetId) } bw.writeU64(this.mints.length) @@ -116,7 +110,7 @@ export class CreateTransactionRequest extends WorkerMessage { bw.writeU64(this.burns.length) for (const burn of this.burns) { - bw.writeBytes(burn.assetIdentifier) + bw.writeBytes(burn.assetId) bw.writeVarBytes(BigIntUtils.toBytesBE(burn.value)) } @@ -153,8 +147,8 @@ export class CreateTransactionRequest extends WorkerMessage { const publicAddress = reader.readVarString() const amount = BigIntUtils.fromBytesBE(reader.readVarBytes()) const memo = reader.readVarString('utf8') - const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) - receives.push({ publicAddress, amount, memo, assetIdentifier }) + const assetId = reader.readBytes(ASSET_ID_LENGTH) + receives.push({ publicAddress, amount, memo, assetId }) } const mintsLength = reader.readU64() @@ -168,9 +162,9 @@ export class CreateTransactionRequest extends WorkerMessage { const burnsLength = reader.readU64() const burns = [] for (let i = 0; i < burnsLength; i++) { - const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) + const assetId = reader.readBytes(ASSET_ID_LENGTH) const value = BigIntUtils.fromBytesBE(reader.readVarBytes()) - burns.push({ assetIdentifier, value }) + burns.push({ assetId, value }) } return new CreateTransactionRequest( @@ -208,7 +202,7 @@ export class CreateTransactionRequest extends WorkerMessage { bufio.sizeVarString(receive.publicAddress) + bufio.sizeVarBytes(BigIntUtils.toBytesBE(receive.amount)) + bufio.sizeVarString(receive.memo, 'utf8') + - ASSET_IDENTIFIER_LENGTH + ASSET_ID_LENGTH } let mintsSize = 0 @@ -218,8 +212,7 @@ export class CreateTransactionRequest extends WorkerMessage { let burnsSize = 0 for (const burn of this.burns) { - burnsSize += - ASSET_IDENTIFIER_LENGTH + bufio.sizeVarBytes(BigIntUtils.toBytesBE(burn.value)) + burnsSize += ASSET_ID_LENGTH + bufio.sizeVarBytes(BigIntUtils.toBytesBE(burn.value)) } return ( @@ -295,8 +288,8 @@ export class CreateTransactionTask extends WorkerTask { ) } - for (const { publicAddress, amount, memo, assetIdentifier } of receives) { - const note = new Note(publicAddress, amount, memo, assetIdentifier, transaction.sender()) + for (const { publicAddress, amount, memo, assetId } of receives) { + const note = new Note(publicAddress, amount, memo, assetId, transaction.sender()) transaction.receive(note) } @@ -304,8 +297,8 @@ export class CreateTransactionTask extends WorkerTask { transaction.mint(asset, value) } - for (const { assetIdentifier, value } of burns) { - transaction.burn(assetIdentifier, value) + for (const { assetId, value } of burns) { + transaction.burn(assetId, value) } const serializedTransactionPosted = transaction.post(undefined, transactionFee) From c6e5ec65a2f9bf20f4caff885302572a95f97129 Mon Sep 17 00:00:00 2001 From: Derek Guenther Date: Fri, 6 Jan 2023 13:17:42 -0500 Subject: [PATCH 44/56] Update napi-rs (#2842) --- Cargo.lock | 34 +++++++++++++++++++++---------- Cargo.toml | 2 -- ironfish-rust-nodejs/Cargo.toml | 4 ++-- ironfish-rust-nodejs/index.js | 9 ++++++++ ironfish-rust-nodejs/package.json | 2 +- yarn.lock | 8 ++++---- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adb42b3b05..46acc03f33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -276,9 +276,12 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "cpufeatures" @@ -761,8 +764,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.9.0" -source = "git+https://github.com/napi-rs/napi-rs?rev=26f6c926d30de744146fe54db6a6b399e142e63c#26f6c926d30de744146fe54db6a6b399e142e63c" +version = "2.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "838b5b414a008e75b97edb3c3e6f189034af789a0608686299b149d3b0e66c39" dependencies = [ "bitflags", "ctor", @@ -779,9 +783,9 @@ checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" [[package]] name = "napi-derive" -version = "2.9.0" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be75210f300e9fbf386ccac1c8eaaed23410e2f7f7aa9295b78c436a172ef51" +checksum = "af4e44e34e70aa61be9036ae652e27c20db5bca80e006be0f482419f6601352a" dependencies = [ "convert_case", "napi-derive-backend", @@ -792,8 +796,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.37" -source = "git+https://github.com/napi-rs/napi-rs?rev=26f6c926d30de744146fe54db6a6b399e142e63c#26f6c926d30de744146fe54db6a6b399e142e63c" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17925fff04b6fa636f8e4b4608cc1a4f1360b64ac8ecbfdb7da1be1dc74f6843" dependencies = [ "convert_case", "once_cell", @@ -806,7 +811,8 @@ dependencies = [ [[package]] name = "napi-sys" version = "2.2.2" -source = "git+https://github.com/napi-rs/napi-rs?rev=26f6c926d30de744146fe54db6a6b399e142e63c#26f6c926d30de744146fe54db6a6b399e142e63c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529671ebfae679f2ce9630b62dd53c72c56b3eb8b2c852e7e2fa91704ff93d67" dependencies = [ "libloading", ] @@ -859,9 +865,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -1381,6 +1387,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d276ec8553..89a04ca034 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,3 @@ edition = "2021" [patch.crates-io] bellman = { git = "https://github.com/iron-fish/bellman", rev = "1cc52ca33e6db14233f1cbc0c9c5b7c822b229ec" } -napi = { git = "https://github.com/napi-rs/napi-rs", rev = "26f6c926d30de744146fe54db6a6b399e142e63c" } -napi-derive-backend = { git = "https://github.com/napi-rs/napi-rs", rev = "26f6c926d30de744146fe54db6a6b399e142e63c" } diff --git a/ironfish-rust-nodejs/Cargo.toml b/ironfish-rust-nodejs/Cargo.toml index d8b4d7950a..321d99779a 100644 --- a/ironfish-rust-nodejs/Cargo.toml +++ b/ironfish-rust-nodejs/Cargo.toml @@ -17,10 +17,10 @@ crate-type = ["cdylib"] [dependencies] base64 = "0.13.0" ironfish_rust = { path = "../ironfish-rust" } -napi-derive = "2.9.0" +napi-derive = "2.9.3" [dependencies.napi] -version = "2.9.0" +version = "2.10.4" features = ["napi6"] [build-dependencies] diff --git a/ironfish-rust-nodejs/index.js b/ironfish-rust-nodejs/index.js index 2b8ee525e5..c87871cab3 100644 --- a/ironfish-rust-nodejs/index.js +++ b/ironfish-rust-nodejs/index.js @@ -102,6 +102,15 @@ switch (platform) { } break case 'darwin': + localFileExisted = existsSync(join(__dirname, 'ironfish-rust-nodejs.darwin-universal.node')) + try { + if (localFileExisted) { + nativeBinding = require('./ironfish-rust-nodejs.darwin-universal.node') + } else { + nativeBinding = require('@ironfish/rust-nodejs-darwin-universal') + } + break + } catch {} switch (arch) { case 'x64': localFileExisted = existsSync(join(__dirname, 'ironfish-rust-nodejs.darwin-x64.node')) diff --git a/ironfish-rust-nodejs/package.json b/ironfish-rust-nodejs/package.json index ce8682df21..f7910e3675 100644 --- a/ironfish-rust-nodejs/package.json +++ b/ironfish-rust-nodejs/package.json @@ -33,7 +33,7 @@ "node": ">= 18" }, "devDependencies": { - "@napi-rs/cli": "2.13.3", + "@napi-rs/cli": "2.14.1", "@types/jest": "29.2.4", "jest": "29.3.1", "jest-jasmine2": "29.3.1", diff --git a/yarn.lock b/yarn.lock index 63b8ad8731..66f17e718d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3116,10 +3116,10 @@ "@napi-rs/blake-hash-win32-ia32-msvc" "1.3.1" "@napi-rs/blake-hash-win32-x64-msvc" "1.3.1" -"@napi-rs/cli@2.13.3": - version "2.13.3" - resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.13.3.tgz#ac4de8c551f190a646d0e1bd86ffbfaac08adef3" - integrity sha512-nAlbKuakQ+YHZE+M3Afih9UA1jr+gx63Gt4xHA+j2xD1NY6TjQ+QCgF9Yaj/YZIkCc2t3CZh52znFrfbU8b2bA== +"@napi-rs/cli@2.14.1": + version "2.14.1" + resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.14.1.tgz#08cb9573eb1d9a7d5b4a0d7c14ae010cb8e0a9f9" + integrity sha512-+mnge6gvdbOrwtYrBO7iMlTjXcaRk17wDqzxSG4SPBKPhI3HroWY+tRsx+OdluAuRyJZOkWTdsvGnMsGO1ff/A== "@nodelib/fs.scandir@2.1.5": version "2.1.5" From fee2e097a6ebdfbd35871edbe270d6015b0e86da Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Fri, 6 Jan 2023 13:19:07 -0500 Subject: [PATCH 45/56] Rename assetIdentifier -> assetId (#2843) --- .../workerPool/tasks/createTransaction.test.slow.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts b/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts index 4062783bc4..5d83ad26ad 100644 --- a/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts +++ b/ironfish/src/workerPool/tasks/createTransaction.test.slow.ts @@ -190,7 +190,7 @@ describe('CreateTransactionTask', () => { expect(transactionPosted.verify()).toBe(true) expect(transactionPosted.notesLength()).toBe(3) - const outputValuesByAssetIdentifier = new BufferMap() + const outputValuesByAssetId = new BufferMap() for (let i = 0; i < transactionPosted.notesLength(); i++) { const decryptedNote = new NoteEncrypted( transactionPosted.getNote(i), @@ -198,15 +198,15 @@ describe('CreateTransactionTask', () => { Assert.isNotUndefined(decryptedNote) const id = decryptedNote.assetId() - const value = outputValuesByAssetIdentifier.get(id) || BigInt(0) - outputValuesByAssetIdentifier.set(id, value + decryptedNote.value()) + const value = outputValuesByAssetId.get(id) || BigInt(0) + outputValuesByAssetId.set(id, value + decryptedNote.value()) } - const nativeAssetValue = outputValuesByAssetIdentifier.get(Asset.nativeId()) + const nativeAssetValue = outputValuesByAssetId.get(Asset.nativeId()) Assert.isNotUndefined(nativeAssetValue) expect(nativeAssetValue).toEqual(2000000000n - fee) - const mintedAssetValue = outputValuesByAssetIdentifier.get(asset.id()) + const mintedAssetValue = outputValuesByAssetId.get(asset.id()) Assert.isNotUndefined(mintedAssetValue) expect(mintedAssetValue).toEqual(mintValue - burnValue) }) From ea718ebc0145f8aef1ecc2214782f8eeadbcbd9c Mon Sep 17 00:00:00 2001 From: jowparks Date: Fri, 6 Jan 2023 10:56:07 -0800 Subject: [PATCH 46/56] feat: update get transaction stream (1/2) (#2835) * feat: wire up assets to masp syncer cli command * feat: fix typo chore: renaming to multi asset feat: add tests feat: cleanup logic more readable * feat: update get transaction stream to handle multi asset * feat: review updates * feat: renaming and asset value change * feat: rename back to assetId since PR was merged for renaming --- .../getTransactionStream.test.ts.fixture | 134 ++++++++++++++++++ .../routes/chain/getTransactionStream.test.ts | 95 +++++++++++++ .../rpc/routes/chain/getTransactionStream.ts | 81 +++++++++-- 3 files changed, 301 insertions(+), 9 deletions(-) create mode 100644 ironfish/src/rpc/routes/chain/__fixtures__/getTransactionStream.test.ts.fixture create mode 100644 ironfish/src/rpc/routes/chain/getTransactionStream.test.ts diff --git a/ironfish/src/rpc/routes/chain/__fixtures__/getTransactionStream.test.ts.fixture b/ironfish/src/rpc/routes/chain/__fixtures__/getTransactionStream.test.ts.fixture new file mode 100644 index 0000000000..2dd60b9485 --- /dev/null +++ b/ironfish/src/rpc/routes/chain/__fixtures__/getTransactionStream.test.ts.fixture @@ -0,0 +1,134 @@ +{ + "Route chain.getTransactionStream responds with burns when block has burns": [ + { + "id": "584fb7ca-bc1d-417a-b34f-472c8d561bd5", + "name": "test", + "spendingKey": "1606040f1c2eca533d460b84d41938048267e5e1d166de26b1e9ae962f617669", + "incomingViewKey": "119c0cceb2a6e4c95f8c0f9f971167e54979af1d9c3762e8a5cce5ad7a333d03", + "outgoingViewKey": "0b112ce39fc0df5bffe16d5a221b78f2cccd0015b77206c4072648e478decc5a", + "publicAddress": "c087c4757916ff8b522a5373e53c02a31932e830caf8ee1e41718cb3010f975c" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtVtsr0qd3eP1KIOA0NTWG5eg+OHgrmr6A1/4erenIu6LINFJqAAfGWiB/8x+UYUpYU/Rxu21+coyB/Y09mcO5doSZRhQPT/p9TyZrs3vTS6gX5wWMWaLMg0gsFIvSZGfAhPNSfQJztai4mcOWDEktuI/fqi5gZdt6BTU8tKIMfsPgt51zMB/SNK7+QhQJea/IHqD6Jj+Bp61+JxvcffSUBQqCyIjCmY/u5GmP6AH49KwoaY/jfNNgUKH/XT0A/3l3LLy6LhlvwYWh7ghLodPOo+pIL/a6kbibPI/y0dyS2Qhsj+n8RlNDbSx3jaElDbA5oNAzZuHvCI2tRQ3qoWKI1BbKSvIvuxPiy3mH1bnm9+d/doyWAIfKWj4nof0iBhoL2bJnmffXEKkpp/p3gc90Q75AQbK0CncEgSCdyYbgMsGvH4dwCRM/s9KAdxD3b/SPkcMgCOoIaHWeflcgxxRVHSnL63UKuP7loDHt11rxnrrXSqqEBRtL7rfH+DeaKtuS+I5rfEBM+LZK0Rs0V1BZNTh00CIhPqMyrP8SPhN5NnF4r1hLmGxAMgyAqiZFidDPDiZm8W0+krkQLsjwf2IgMNJ/a+rAStMVYlkXEuWKYkLE+JWv2TdjOwZI1V2VOk6KLrPzjCT9IO0CCddpobXPi4Onhxm0RMf5AWKdsct2Zl5QNMlvgkntUjiK23BSFWOuFxQkzaYUbIW+oRN8Vb8bHSLLf74Cbc5rScQ98dtM+maKjKIgSEfmHFGxjZlb8yOMN7IwBwd17Q75nnJaZwW8MXX3JL+gKrAppaZbx4n8pmMibuiT0lD5kh+1/MWmWay1i55K5l+iFjBDa/w7ckMkuqCbPOXdhVQCTps8GPaL5ChMLUJMlsVkVzecKL0EgdhhXE2hM5M+xAN6mE5IPEOqwwiUmMk/DwSmOnigTCCekdhszy94V/gVqP1NrILkYvGPfFhc7RJed0IPWSCJjcCxmM3T4T9j3RswIfEdXkW/4tSKlNz5TwCoxky6DDK+O4eQXGMswEPl1xtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACDMz8gp8yHUZ6YV7Ft5/sFFTVOZ3M5iAVfvoWKxruYrOP61WoMeuxG910lAnQxB/2zN1Ew5k0r67WcgvEp2ehHfPoV8jMET6AdqglLN/88fQAVoLICmg/q1EL8HxhjeAoHPDOAUq3H0S/jPUpRotApIFJQvxRtO5RH7/3ol9cyG3B7e403sDg0uzDVEAax4t5F8sI7W2RA+4JIVJQBZGQE" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:w0uGmyo6QkJErJyM0lKw3WkfApPtHQR9qVsqeoqCEW0=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:IeDxbVJ3O1kk5674StrV+an1qLCo6smHwCak75sYN/o=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672870780783, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAo/bT443Xw2x2+4q+vqSimde5Q+HvhqKPDE23hn/ID3KLT1Kvge7fnvRK+XID9As/UdyOPT5Fl9Kp/Mu1SSjwKbZEAm8eWFWVWyIcwAADEfWkM60jRb+PlNxcQfl96aXnXcrqj+hHBOKptV5oKz4wvxAb0FGpKDvYo5cvTCM69x8Xg13PnH40KrV4EI1Hl9ntKbKO+Hh847rEpm4WgViRnF1s8rYwvycI4V8W6clyoi6BOxwdKepjGixfRbAfXfWEsktkj7bOCaihf1WnAVlBwAJHak3hdDR1tSnSwXi1CSfYCZvjZrOKueBfzYLiqUffd9rLXOUFSA7XW45d2HtmLFVsNEJV27qbHTQ7oW1s6XRh+DDVamez01mIidrUJ7FQobakZ94P3uhyHHF76HQarzfZnC4e+l/olilbt/JpPpdDHpmVAbPJClRjRHtqj4ERs4Jb5MiFNw9Eil8fQyk6r1H5Alf28gFTHzQ19bhnHcLxJ2EdH6SY6OOj1bVCgvWQAiI5lpk1kkgmykUiJsRMgGuP1eaYshk6i2KnkGOvWKKxvWxwyRDbTa9UpttISHh2DIrfL3htupkDeY/HIhiK2Cg+si1Rno8H0We0qzGLIRTkO0sb0yRRsUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwTVlOyKTAnnGtXkOuxIlG7Bt8MnRw34DHTrxr1qv29WKr6xF+hQRAUUrPfZMsHxt9TF4YoKGrmy8EO4OF/za2Cw==" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtVtsr0qd3eP1KIOA0NTWG5eg+OHgrmr6A1/4erenIu6LINFJqAAfGWiB/8x+UYUpYU/Rxu21+coyB/Y09mcO5doSZRhQPT/p9TyZrs3vTS6gX5wWMWaLMg0gsFIvSZGfAhPNSfQJztai4mcOWDEktuI/fqi5gZdt6BTU8tKIMfsPgt51zMB/SNK7+QhQJea/IHqD6Jj+Bp61+JxvcffSUBQqCyIjCmY/u5GmP6AH49KwoaY/jfNNgUKH/XT0A/3l3LLy6LhlvwYWh7ghLodPOo+pIL/a6kbibPI/y0dyS2Qhsj+n8RlNDbSx3jaElDbA5oNAzZuHvCI2tRQ3qoWKI1BbKSvIvuxPiy3mH1bnm9+d/doyWAIfKWj4nof0iBhoL2bJnmffXEKkpp/p3gc90Q75AQbK0CncEgSCdyYbgMsGvH4dwCRM/s9KAdxD3b/SPkcMgCOoIaHWeflcgxxRVHSnL63UKuP7loDHt11rxnrrXSqqEBRtL7rfH+DeaKtuS+I5rfEBM+LZK0Rs0V1BZNTh00CIhPqMyrP8SPhN5NnF4r1hLmGxAMgyAqiZFidDPDiZm8W0+krkQLsjwf2IgMNJ/a+rAStMVYlkXEuWKYkLE+JWv2TdjOwZI1V2VOk6KLrPzjCT9IO0CCddpobXPi4Onhxm0RMf5AWKdsct2Zl5QNMlvgkntUjiK23BSFWOuFxQkzaYUbIW+oRN8Vb8bHSLLf74Cbc5rScQ98dtM+maKjKIgSEfmHFGxjZlb8yOMN7IwBwd17Q75nnJaZwW8MXX3JL+gKrAppaZbx4n8pmMibuiT0lD5kh+1/MWmWay1i55K5l+iFjBDa/w7ckMkuqCbPOXdhVQCTps8GPaL5ChMLUJMlsVkVzecKL0EgdhhXE2hM5M+xAN6mE5IPEOqwwiUmMk/DwSmOnigTCCekdhszy94V/gVqP1NrILkYvGPfFhc7RJed0IPWSCJjcCxmM3T4T9j3RswIfEdXkW/4tSKlNz5TwCoxky6DDK+O4eQXGMswEPl1xtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAACDMz8gp8yHUZ6YV7Ft5/sFFTVOZ3M5iAVfvoWKxruYrOP61WoMeuxG910lAnQxB/2zN1Ew5k0r67WcgvEp2ehHfPoV8jMET6AdqglLN/88fQAVoLICmg/q1EL8HxhjeAoHPDOAUq3H0S/jPUpRotApIFJQvxRtO5RH7/3ol9cyG3B7e403sDg0uzDVEAax4t5F8sI7W2RA+4JIVJQBZGQE" + } + ] + } + ], + "Route chain.getTransactionStream should fail if block can't be found with hash": [ + { + "id": "ff936de6-007f-4e7b-bb63-4f96b89b6868", + "name": "test", + "spendingKey": "2c17273d9e3f1b426095443628678f28ea5779bc0eed83d682e3b8a0a737afca", + "incomingViewKey": "7747318df99cd600359c38cfae4966e404d659f6b101ec36e653a7ac8d64a400", + "outgoingViewKey": "597a8ee60710b325d77e7f1ad96cf0d36967bd84c4c7fd021e4df1e8d73db5b1", + "publicAddress": "641431124bf337ca00080616c954a042dbe571cdc81641f2b726e641eec8e538" + } + ], + "Route chain.getTransactionStream returns expected mints and burns": [ + { + "id": "ab388cd5-2038-4ee4-9589-ec085499173a", + "name": "test", + "spendingKey": "3dedfcb315507180e4c9ce26e67d7793059c202b487ef50b0e658890b420425e", + "incomingViewKey": "3178e3dfcf6f18e78abc44188efcb76716ced0af42ea2183b8ee6c3f53edb407", + "outgoingViewKey": "ee5f829e278949c668e6470daa357becc0574bdb88035592b50a67f43c7c8892", + "publicAddress": "329b9bfd734f4901ff59e510f071ed58794ab340b11898ff7fcd73d583c6ae08" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzjEZ0SHpSJBlmMpjpCLGiGRGoyMOHRw01uS8VdiZDSi0gr2IFbfVPUyFM23md9nxLzsTsvj54/Ee5ngBGGWUMzPsx4ivzYAz+2iwFuutLQa2GbjYjatDlJOWUOSO/DEvbt8D2wq1E1Ro5cukKGIb3yKL3MJpRqIYVzjKwBXleGsHkyfjVyUeKGwSZkWpxg1Ox1zmRrANkxDYxNkmmu3OSEbJV7MYtpbbUFnXB59K76erizBtCdqHjkCTqLQ+Gu90DM94tC52vqzHl56l5iqp5KROA/CUsyrK06dmle4kdFmQIsARSW3Qg++Z8LV2EjjuPPboJ6W7Kssz9fsQYOKvL4I1Hxht9+ItvDuF2fPNaxcOwlLNTPWNfw3/KUKSiak+wkdkpFKXjvQaf/9DtwXjm5q7SDxfgOVPgpn5bFENqZbIdyTYf8RUDy11cQnXHs6qTGyJiIel/4Po4ap+tjGKMprPwb5x8iV2ng2I6UWCf0b8dTn/MhRGYYqVuoJYYrfBRAWKecITEJlr/yHDPc2C4fdG9t14oHjPFJZMYLurJM9qbGnur1Kvs7ZHCT5Rxp5+GOPIsRtPw5s7fygtyrPokGXYGnfMKqenrqxIqEHPUQxPwSagnutt6kjWZsbaHOQ9z3GP+myRkcrmn4N9UiwjTUbTgHTn/TtHGKFr6hBXxxtJcsXx9tqgaBbFvyruHpD6zW93CZeM1+XU3aCn1SRU7K8sKEFrWQYVuDBvDTZyu+B2qSnsg6OsWfk1I/pcUUc4Ru4DxBHYAtOtEyzAK89gcgdM5jfE7RQCtPjwyvHXu6SL0EN/7yUiIf5i+63CHM/aAMt4qm7dTUkJisgUkHzcnPC7Po+L7OFsCl7Ns73L2zAeTRrVfOsn2U8gy1xQjNMrKxOOqvqRUlXJAGqHBRVBS5aE/TIkGHCWiz23VGOLQCAp/KEte9wdL7aOgxL2CMNv9fwfa3Fm49amcnUXkm1jNeYMppu5sec0Mpub/XNPSQH/WeUQ8HHtWHlKs0CxGJj/f81z1YPGrghjdXN0b21hc3NldAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCgAAAAAAAADi9kkHHExmbcaFHnnm9C0POgVStsbmxXmgkbYWt1aYpQ1+ma9REoSA7BBnrhk4Okkk6CBmeIHvzypRHhX/yu/vHh+B4l0Bv+M+N+o1mShNBsd7ay+0SAFTJ0cecBxeQgPAAfUNXo+nlddA5SeIjX0VEq+MppwMrnI4+kSs9OuIbZM/a/CIBTKwyQdP964OtegavmK4z1hymL8vcaqstLIJ" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:t/0vvSzSB7HQbbAwlA4JAdZvIBiQQP6VczNwXn46ykY=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:el+gjcbZsqa1ccxLAjmcgks4ZVyxBsEr3iPw/erO9CA=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672872686861, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAQwrE42P0W1k7o5MRkQ3T0lQOB6by2yCScQhnPftGGuCyhJqvuwqzEgnCL4Z2RXi2SnsPCT3C4gS2k+sjoUXOrccmTyZV3GR3jeKeHTmAc3KGSc2+1f5hNEUC0E/axXh6yXDp8qMNrC9T7Rqhd4Si7nTim8kEDK+keFaLNafRnqkDTLIykSTB5R52OawEywW9V0Rlbau2qGWgccf7vAibGe9A5fkBANqrR6Vu4w8GcHyWstoZpf9lxMfmfa4S5X3PgqjvRsRk1BPb+OaSzba4uPuCPr1EEpcXJQfSUsRzBtG90i8Bs8QAUFEEzii6LDNHNC6dz40FLjeYL08bnUFFbXV20GAlO2hnw/1FhWQDRUh5cLdDVhepM1z3WuLkJoc9KAN5anc+sP1xItu0ZEZv5V5a0iFoWie+UOshCnNXDYEHHBMP9QiiawCvdac/wQEnlk/It5SMifJYpXM4OVYbjy8y9YyKidMN9gxqA39jTu3KMa1pNNARvknoZP0Z17bDi4K7F9AiFTi0kD9qDf2j0XhzNdBR6zw9QPPPPQlHgY+BAaCIDhz9DWZM0alikZHXz1rNrMjBozgyamlkNp2AzlHw4kYXkVd8jcyAPbe8cp/VP7lWr0nWJ0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwD5a87Kl/443ilPBm2gS94v73zKfJl2YaJ383da+/PZZnAjZ6IwkAejeoCTflBUTbjLrJV/fi6DywbNXq/O80Cw==" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzjEZ0SHpSJBlmMpjpCLGiGRGoyMOHRw01uS8VdiZDSi0gr2IFbfVPUyFM23md9nxLzsTsvj54/Ee5ngBGGWUMzPsx4ivzYAz+2iwFuutLQa2GbjYjatDlJOWUOSO/DEvbt8D2wq1E1Ro5cukKGIb3yKL3MJpRqIYVzjKwBXleGsHkyfjVyUeKGwSZkWpxg1Ox1zmRrANkxDYxNkmmu3OSEbJV7MYtpbbUFnXB59K76erizBtCdqHjkCTqLQ+Gu90DM94tC52vqzHl56l5iqp5KROA/CUsyrK06dmle4kdFmQIsARSW3Qg++Z8LV2EjjuPPboJ6W7Kssz9fsQYOKvL4I1Hxht9+ItvDuF2fPNaxcOwlLNTPWNfw3/KUKSiak+wkdkpFKXjvQaf/9DtwXjm5q7SDxfgOVPgpn5bFENqZbIdyTYf8RUDy11cQnXHs6qTGyJiIel/4Po4ap+tjGKMprPwb5x8iV2ng2I6UWCf0b8dTn/MhRGYYqVuoJYYrfBRAWKecITEJlr/yHDPc2C4fdG9t14oHjPFJZMYLurJM9qbGnur1Kvs7ZHCT5Rxp5+GOPIsRtPw5s7fygtyrPokGXYGnfMKqenrqxIqEHPUQxPwSagnutt6kjWZsbaHOQ9z3GP+myRkcrmn4N9UiwjTUbTgHTn/TtHGKFr6hBXxxtJcsXx9tqgaBbFvyruHpD6zW93CZeM1+XU3aCn1SRU7K8sKEFrWQYVuDBvDTZyu+B2qSnsg6OsWfk1I/pcUUc4Ru4DxBHYAtOtEyzAK89gcgdM5jfE7RQCtPjwyvHXu6SL0EN/7yUiIf5i+63CHM/aAMt4qm7dTUkJisgUkHzcnPC7Po+L7OFsCl7Ns73L2zAeTRrVfOsn2U8gy1xQjNMrKxOOqvqRUlXJAGqHBRVBS5aE/TIkGHCWiz23VGOLQCAp/KEte9wdL7aOgxL2CMNv9fwfa3Fm49amcnUXkm1jNeYMppu5sec0Mpub/XNPSQH/WeUQ8HHtWHlKs0CxGJj/f81z1YPGrghjdXN0b21hc3NldAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCgAAAAAAAADi9kkHHExmbcaFHnnm9C0POgVStsbmxXmgkbYWt1aYpQ1+ma9REoSA7BBnrhk4Okkk6CBmeIHvzypRHhX/yu/vHh+B4l0Bv+M+N+o1mShNBsd7ay+0SAFTJ0cecBxeQgPAAfUNXo+nlddA5SeIjX0VEq+MppwMrnI4+kSs9OuIbZM/a/CIBTKwyQdP964OtegavmK4z1hymL8vcaqstLIJ" + } + ] + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAfj0nrI5LY5Icu0Q0c8Qd3Xmatr+AAxgNGVzXNz5/45yFnQwG+G4//c4jYsJM3mNnkkLSLF52Yi0OfkyXAiux9/OoBUilrVXJwxcjTQ5BFLWEMh9MCsDLlk86vvOXoShbLwqfVvcKnJ4uZWqy1ppcBNseicCHLwxsKuDB+Q4MfroLPwBO27prhYjnffQr6sPziE5ShbrwcsNvTqi/j1g7WXZiuNVke23mih1h+7Xwnwy4yWXAQoTwbMS5fOe7HjCSK5XeREYysVy3F9YUvPLzESgCZAJDWd0/9weQ3W1C++oasM4+KIdjsaIvsULLCCovxlg03MZWIX3Fx18FwyMT47f9L70s0gex0G2wMJQOCQHWbyAYkED+lXMzcF5+OspGBQAAAJuJoZD9lmAyaQHK/gEZ6m9WaWnzbQ4WiZLw2o9A8x8XzVsutKC+JAYtX9nEQGhZmivhj5iv5ffYsOFTGdKPnsvjVqJPMc88MUpVE9HNHoEV9QE4cjzGBv6gc9U6wTg4CtoCVNbjteFLRrLH/AGxZb/KAiNGdB+QobS//SdSC72dCgAAAAAAAABUJCZL6tiFTWsrOcj60OG3IKH/hWyYRdgdWCd7/mCnqmQuNABcQEj5J05II6rEMWfF3EJpp/nhgzoMlYK5MTcH" + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "20B195856877E653087A62BBD5A086E3194C31E38F6498EFCA75CBB19A7E18FA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:3bqp9lxZ0nAocYutrNbsc8/C789t9tHRJz7cILvDvjc=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:sdvPRGN3xfAeSHGg/+oNa/xlOOVk4DknognbITjJTQA=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672872688434, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 6, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAFQ6dPsBCctLIX40u9MaaUgueA7SO2+WOGXqdHxCQHhK5Oq3WD0s1ZyOlg1KutlmLVdKHURM1T8TFN+OIFZD4HzimMvc4BDTMRVGYm5hoyyStBACs0JUzoYgjcEeEycgOCmWZEJLWDA34a5bxuEcCW53AtrKy2gaGxD6QhXUtjb8W/+yVQoLj8FUKAcx6qLt/V6KcueBcbuH/pIFSRzG94V79KkKQmd+DHsxStCj/wIW0X0haCVgA069iprtS8QKjRWTW3YzzHY/dq14DDFN4v00nC3KjQ7MXEoroure+nfiCZZFzaz+VvvQldDuKUa4QC6c7Y2/ZQ7E/s8N6J6uKEmrLEHwsT/1LA3kYE+VLKpaLdZAjCcrWInrsG6g/enESYHugdhePwPwMX+RxK1b/my3Gd/UHtnHu6FezJHb7vgAN3SpJ+wPy1aLGWQPZ0aOhABeFF5R+++89h712qyaGO9b626jSV0Q0sW2B939ZWYlLOc2O7rKaWptfrMg8wf7eudC2SeORt/cbaaUSwr7KNaucNojZkwXPA1oAm7A257IvPjvsIC/OExBEN9d6RlInjSxVUPK9GJf4JailMZF+atCefHH2k7DPS6sZ3yJybdj+bDb6fWNW3Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw/7FE7B6ia7B7vgukoWG9KONpfWpsPzPwvN064NR7E8wAHMw/S/FEaZMn0rZ32JarK8UUZaQi3j0B/P/lJ+c1Bg==" + }, + { + "type": "Buffer", + "data": "base64:AQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAfj0nrI5LY5Icu0Q0c8Qd3Xmatr+AAxgNGVzXNz5/45yFnQwG+G4//c4jYsJM3mNnkkLSLF52Yi0OfkyXAiux9/OoBUilrVXJwxcjTQ5BFLWEMh9MCsDLlk86vvOXoShbLwqfVvcKnJ4uZWqy1ppcBNseicCHLwxsKuDB+Q4MfroLPwBO27prhYjnffQr6sPziE5ShbrwcsNvTqi/j1g7WXZiuNVke23mih1h+7Xwnwy4yWXAQoTwbMS5fOe7HjCSK5XeREYysVy3F9YUvPLzESgCZAJDWd0/9weQ3W1C++oasM4+KIdjsaIvsULLCCovxlg03MZWIX3Fx18FwyMT47f9L70s0gex0G2wMJQOCQHWbyAYkED+lXMzcF5+OspGBQAAAJuJoZD9lmAyaQHK/gEZ6m9WaWnzbQ4WiZLw2o9A8x8XzVsutKC+JAYtX9nEQGhZmivhj5iv5ffYsOFTGdKPnsvjVqJPMc88MUpVE9HNHoEV9QE4cjzGBv6gc9U6wTg4CtoCVNbjteFLRrLH/AGxZb/KAiNGdB+QobS//SdSC72dCgAAAAAAAABUJCZL6tiFTWsrOcj60OG3IKH/hWyYRdgdWCd7/mCnqmQuNABcQEj5J05II6rEMWfF3EJpp/nhgzoMlYK5MTcH" + } + ] + } + ] +} \ No newline at end of file diff --git a/ironfish/src/rpc/routes/chain/getTransactionStream.test.ts b/ironfish/src/rpc/routes/chain/getTransactionStream.test.ts new file mode 100644 index 0000000000..68e9c45601 --- /dev/null +++ b/ironfish/src/rpc/routes/chain/getTransactionStream.test.ts @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import '../../../testUtilities/matchers' +import { Asset } from '@ironfish/rust-nodejs' +import { BlockHashSerdeInstance } from '../../../serde' +import { + useAccountFixture, + useBurnBlockFixture, + useMintBlockFixture, +} from '../../../testUtilities/fixtures' +import { createRouteTest } from '../../../testUtilities/routeTest' +import { GetTransactionStreamResponse } from './getTransactionStream' + +describe('Route chain.getTransactionStream', () => { + const routeTest = createRouteTest() + + it('should fail if no incoming view key is specified', async () => { + await expect( + routeTest.client.request('chain/getTransactionStream', {}).waitForEnd(), + ).rejects.toThrow('Request failed (400) validation: incomingViewKey is a required field') + }) + + it(`should fail if block can't be found with hash`, async () => { + const hash = BlockHashSerdeInstance.serialize(Buffer.alloc(32, 'blockhashnotfound')) + const wallet = routeTest.node.wallet + const account = await useAccountFixture(wallet) + + await expect( + routeTest.client + .request('chain/getTransactionStream', { + incomingViewKey: account.incomingViewKey, + head: hash, + }) + .waitForEnd(), + ).rejects.toThrow( + `Request failed (400) validation: Block with hash ${hash} was not found in the chain`, + ) + }) + + it('returns expected mints and burns', async () => { + const wallet = routeTest.node.wallet + const account = await useAccountFixture(wallet) + const asset = new Asset(account.spendingKey, 'customasset', 'metadata') + const response = routeTest.client.request( + 'chain/getTransactionStream', + { incomingViewKey: account.incomingViewKey }, + ) + await response.contentStream().next() + // Mint so we have an existing asset + const mintValue = BigInt(10) + + const mintBlock = await useMintBlockFixture({ + node: routeTest.node, + account, + asset, + value: mintValue, + }) + await expect(routeTest.node.chain).toAddBlock(mintBlock) + // validate mint block + expect(await (await response.contentStream().next()).value).toEqual( + expect.objectContaining({ + transactions: expect.arrayContaining([ + expect.objectContaining({ + mints: expect.arrayContaining([expect.objectContaining({ value: '10' })]), + }), + ]), + }), + ) + + // update wallet so it sees newly added asset + await wallet.updateHead() + + // now burn + const burnBlock = await useBurnBlockFixture({ + node: routeTest.node, + account, + asset, + value: mintValue, + }) + await expect(routeTest.node.chain).toAddBlock(burnBlock) + // validate burn block + expect(await (await response.contentStream().next()).value).toEqual( + expect.objectContaining({ + transactions: expect.arrayContaining([ + expect.objectContaining({ + burns: expect.arrayContaining([expect.objectContaining({ value: '10' })]), + }), + ]), + }), + ) + response.end() + }) +}) diff --git a/ironfish/src/rpc/routes/chain/getTransactionStream.ts b/ironfish/src/rpc/routes/chain/getTransactionStream.ts index aa67df1c58..61829ff542 100644 --- a/ironfish/src/rpc/routes/chain/getTransactionStream.ts +++ b/ironfish/src/rpc/routes/chain/getTransactionStream.ts @@ -13,30 +13,66 @@ import { ValidationError } from '../../adapters/errors' import { ApiNamespace, router } from '../router' interface Note { - amount: string + assetId: string + assetName: string + value: string memo: string } +interface Mint { + assetId: string + assetName: string + value: string +} +interface Burn { + assetId: string + assetName: string + value: string +} interface Transaction { hash: string isMinersFee: boolean notes: Note[] + mints: Mint[] + burns: Burn[] } const NoteSchema = yup .object() .shape({ - amount: yup.string().required(), + assetId: yup.string().required(), + assetName: yup.string().required(), + value: yup.string().required(), memo: yup.string().required(), }) .required() +const MintSchema = yup + .object() + .shape({ + assetId: yup.string().required(), + assetName: yup.string().required(), + value: yup.string().required(), + }) + .required() + +const BurnSchema = yup + .object() + .shape({ + assetId: yup.string().required(), + assetName: yup.string().required(), + value: yup.string().required(), + }) + .required() + const TransactionSchema = yup .object() .shape({ hash: yup.string().required(), isMinersFee: yup.boolean().required(), notes: yup.array().of(NoteSchema).required(), + mints: yup.array().of(MintSchema).required(), + burns: yup.array().of(BurnSchema).required(), }) .required() @@ -106,28 +142,55 @@ router.register { + const processBlock = async ( + block: Block, + type: 'connected' | 'disconnected' | 'fork', + ): Promise => { const transactions: Transaction[] = [] for (const tx of block.transactions) { const notes = new Array() + const mints = new Array() + const burns = new Array() for (const note of tx.notes) { const decryptedNote = note.decryptNoteForOwner(request.data.incomingViewKey) if (decryptedNote) { + const assetValue = await node.chain.getAssetById(decryptedNote.assetId()) notes.push({ - amount: CurrencyUtils.encode(decryptedNote.value()), + value: CurrencyUtils.encode(decryptedNote.value()), memo: decryptedNote.memo(), + assetId: decryptedNote.assetId().toString('hex'), + assetName: assetValue?.name.toString('hex') || '', }) } } - if (notes.length) { + for (const burn of tx.burns) { + const assetValue = await node.chain.getAssetById(burn.assetId) + burns.push({ + value: CurrencyUtils.encode(burn.value), + assetId: burn.assetId.toString('hex'), + assetName: assetValue?.name.toString('hex') || '', + }) + } + + for (const mint of tx.mints) { + mints.push({ + value: CurrencyUtils.encode(mint.value), + assetId: mint.asset.id().toString('hex'), + assetName: mint.asset.name().toString('hex'), + }) + } + + if (notes.length || burns.length || mints.length) { transactions.push({ hash: tx.hash().toString('hex'), isMinersFee: tx.isMinersFee(), notes: notes, + burns: burns, + mints: mints, }) } } @@ -150,17 +213,17 @@ router.register { const block = await node.chain.getBlock(header) Assert.isNotNull(block) - processBlock(block, 'connected') + await processBlock(block, 'connected') } const onRemove = async (header: BlockHeader) => { const block = await node.chain.getBlock(header) Assert.isNotNull(block) - processBlock(block, 'disconnected') + await processBlock(block, 'disconnected') } - const onFork = (block: Block) => { - processBlock(block, 'fork') + const onFork = async (block: Block) => { + await processBlock(block, 'fork') } const abortController = new AbortController() From 06bc8817cd3de322e83b9b095f20afb9dacd7770 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Fri, 6 Jan 2023 14:27:23 -0500 Subject: [PATCH 47/56] WIP (#2844) --- .../src/testUtilities/fixtures/account.ts | 27 ++ .../{fixtures.ts => fixtures/blocks.ts} | 313 +++--------------- .../src/testUtilities/fixtures/fixture.ts | 113 +++++++ ironfish/src/testUtilities/fixtures/index.ts | 6 + .../testUtilities/fixtures/transactions.ts | 108 ++++++ 5 files changed, 300 insertions(+), 267 deletions(-) create mode 100644 ironfish/src/testUtilities/fixtures/account.ts rename ironfish/src/testUtilities/{fixtures.ts => fixtures/blocks.ts} (56%) create mode 100644 ironfish/src/testUtilities/fixtures/fixture.ts create mode 100644 ironfish/src/testUtilities/fixtures/index.ts create mode 100644 ironfish/src/testUtilities/fixtures/transactions.ts diff --git a/ironfish/src/testUtilities/fixtures/account.ts b/ironfish/src/testUtilities/fixtures/account.ts new file mode 100644 index 0000000000..bc990eef62 --- /dev/null +++ b/ironfish/src/testUtilities/fixtures/account.ts @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Account, AccountValue, Wallet } from '../../wallet' +import { FixtureGenerate, useFixture } from './fixture' + +export function useAccountFixture( + wallet: Wallet, + generate: FixtureGenerate | string = 'test', +): Promise { + if (typeof generate === 'string') { + const name = generate + generate = () => wallet.createAccount(name) + } + + return useFixture(generate, { + serialize: (account: Account): AccountValue => { + return account.serialize() + }, + + deserialize: async (accountData: AccountValue): Promise => { + const account = await wallet.importAccount(accountData) + await wallet.updateHeadHash(account, wallet.chainProcessor.hash) + return account + }, + }) +} diff --git a/ironfish/src/testUtilities/fixtures.ts b/ironfish/src/testUtilities/fixtures/blocks.ts similarity index 56% rename from ironfish/src/testUtilities/fixtures.ts rename to ironfish/src/testUtilities/fixtures/blocks.ts index b01fee8bc2..bd5c444715 100644 --- a/ironfish/src/testUtilities/fixtures.ts +++ b/ironfish/src/testUtilities/fixtures/blocks.ts @@ -2,149 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Asset, generateKey } from '@ironfish/rust-nodejs' -import fs from 'fs' -import path from 'path' -import { Assert } from '../assert' -import { Blockchain } from '../blockchain' -import { IronfishNode } from '../node' -import { Block, BlockSerde, SerializedBlock } from '../primitives/block' -import { BurnDescription } from '../primitives/burnDescription' -import { MintDescription } from '../primitives/mintDescription' -import { NoteEncrypted } from '../primitives/noteEncrypted' -import { SerializedTransaction, Transaction } from '../primitives/transaction' -import { IJSON } from '../serde' -import { Account, AccountValue, Wallet } from '../wallet' -import { WorkerPool } from '../workerPool/pool' -import { createRawTransaction } from './helpers/transaction' -import { getCurrentTestPath } from './utils' - -const FIXTURE_FOLDER = '__fixtures__' - -type FixtureGenerate = () => Promise | T -type FixtureRestore = (fixture: T) => Promise | void -type FitxureDeserialize = (data: TSerialized) => Promise | T -type FixtureSerialize = (fixture: T) => Promise | TSerialized - -const fixtureIds = new Map() -const fixtureCache = new Map>() - -export function shouldUpdateFixtures(): boolean { - // Use the same parameters as jest snapshots for usability - return process.argv.indexOf('--updateSnapshot') !== -1 || process.argv.indexOf('-u') !== -1 -} - -export function disableFixtures(): void { - const currentTestName = expect.getState().currentTestName || '' - const testName = currentTestName.replace(/ /g, '_') - const fixtureInfo = fixtureIds.get(testName) || { id: 0, disabled: false } - fixtureIds.set(testName, fixtureInfo) - fixtureInfo.disabled = true -} - -export async function useFixture( - generate: FixtureGenerate, - options: { - restore?: FixtureRestore - process?: FixtureRestore - deserialize?: FitxureDeserialize - serialize?: FixtureSerialize - } = {}, -): Promise { - const testPath = getCurrentTestPath() - const testName = expect.getState().currentTestName || '' - const testDir = path.dirname(testPath) - const testFile = path.basename(testPath) - - const fixtureInfo = fixtureIds.get(testName) || { id: -1, disabled: false } - const fixtureId = (fixtureInfo.id += 1) - fixtureIds.set(testName, fixtureInfo) - - const fixtureDir = path.join(testDir, FIXTURE_FOLDER) - const fixtureName = `${testFile}.fixture` - const fixturePath = path.join(fixtureDir, fixtureName) - - const updateFixtures = shouldUpdateFixtures() - - let fixtures = fixtureCache.get(testPath) - - // Load serialized fixtures in if they are not loaded - if (!fixtures) { - fixtures = new Map() - - if (fs.existsSync(fixturePath)) { - const buffer = await fs.promises.readFile(fixturePath) - const data = IJSON.parse(buffer.toString('utf8')) as Record - - for (const test in data) { - fixtures.set(test, data[test]) - } - } - - fixtureCache.set(testPath, fixtures) - } - - let fixture: TFixture | null = null - - const serializedAll = fixtures.get(testName) || [] - fixtures.set(testName, serializedAll) - - if (!updateFixtures && !fixtureInfo.disabled && serializedAll[fixtureId]) { - // deserialize existing fixture - if (options.deserialize) { - const serialized = serializedAll[fixtureId] as TSerialized - fixture = await options.deserialize(serialized) - } else { - fixture = serializedAll[fixtureId] as TFixture - } - - if (options.restore) { - await options.restore(fixture) - } - } else { - // generate the fixture - fixture = await generate() - const serialized = options.serialize ? await options?.serialize(fixture) : fixture - serializedAll[fixtureId] = serialized - - if (!fs.existsSync(fixtureDir)) { - await fs.promises.mkdir(fixtureDir) - } - - const result = Object.fromEntries(fixtures.entries()) - const data = IJSON.stringify(result, ' ') - await fs.promises.writeFile(fixturePath, data) - } - - if (options.process) { - await options.process(fixture) - } - - return fixture -} - -export async function useAccountFixture( - wallet: Wallet, - generate: FixtureGenerate | string = 'test', -): Promise { - if (typeof generate === 'string') { - const name = generate - generate = () => wallet.createAccount(name) - } - - return useFixture(generate, { - serialize: (account: Account): AccountValue => { - return account.serialize() - }, - - deserialize: async (accountData: AccountValue): Promise => { - const account = await wallet.importAccount(accountData) - - await wallet.updateHeadHash(account, wallet.chainProcessor.hash) - - return account - }, - }) -} +import { Assert } from '../../assert' +import { Blockchain } from '../../blockchain' +import { IronfishNode } from '../../node' +import { Block, BlockSerde, SerializedBlock } from '../../primitives/block' +import { BurnDescription } from '../../primitives/burnDescription' +import { MintDescription } from '../../primitives/mintDescription' +import { NoteEncrypted } from '../../primitives/noteEncrypted' +import { Transaction } from '../../primitives/transaction' +import { Account, Wallet } from '../../wallet' +import { WorkerPool } from '../../workerPool/pool' +import { useAccountFixture } from './account' +import { FixtureGenerate, useFixture } from './fixture' +import { + restoreTransactionFixtureToAccounts, + usePostTxFixture, + useTxFixture, +} from './transactions' /* * We need the workaround because transactions related to us @@ -164,13 +38,6 @@ export async function restoreBlockFixtureToAccounts( } } -export async function restoreTransactionFixtureToAccounts( - transaction: Transaction, - wallet: Wallet, -): Promise { - await wallet.addPendingTransaction(transaction) -} - /** * Executes a generator function which creates a block and * caches that in the fixtures folder next to the current test @@ -269,73 +136,6 @@ export async function useBurnBlockFixture(options: { ]) } -export async function usePostTxFixture(options: { - node: IronfishNode - wallet: Wallet - from: Account - to?: Account - fee?: bigint - amount?: bigint - expiration?: number - assetId?: Buffer - receives?: { - publicAddress: string - amount: bigint - memo: string - assetId: Buffer - }[] - mints?: MintDescription[] - burns?: BurnDescription[] -}): Promise { - return useTxFixture(options.wallet, options.from, options.from, async () => { - const raw = await createRawTransaction(options) - return options.node.workerPool.postTransaction(raw) - }) -} - -export async function useTxFixture( - wallet: Wallet, - from: Account, - to: Account, - generate?: FixtureGenerate, - fee?: bigint, - expiration?: number, -): Promise { - generate = - generate || - (async () => { - const raw = await wallet.createTransaction( - from, - [ - { - publicAddress: to.publicAddress, - amount: BigInt(1), - memo: '', - assetId: Asset.nativeId(), - }, - ], - [], - [], - fee ?? BigInt(0), - expiration ?? 0, - ) - - return await wallet.postTransaction(raw) - }) - - return useFixture(generate, { - process: async (tx: Transaction): Promise => { - await restoreTransactionFixtureToAccounts(tx, wallet) - }, - serialize: (tx: Transaction): SerializedTransaction => { - return tx.serialize() - }, - deserialize: (tx: SerializedTransaction): Transaction => { - return new Transaction(tx) - }, - }) -} - export async function useBlockWithRawTxFixture( chain: Blockchain, pool: WorkerPool, @@ -384,56 +184,6 @@ export async function useBlockWithRawTxFixture( return useBlockFixture(chain, generate) } -export async function useMinersTxFixture( - wallet: Wallet, - to?: Account, - sequence?: number, - amount = 0, -): Promise { - if (!to) { - to = await useAccountFixture(wallet) - } - - return useTxFixture(wallet, to, to, () => { - Assert.isNotUndefined(to) - - return wallet.chain.strategy.createMinersFee( - BigInt(amount), - sequence || wallet.chain.head.sequence + 1, - to.spendingKey, - ) - }) -} - -export async function useTxSpendsFixture( - node: IronfishNode, - options?: { - account?: Account - expiration?: number - }, -): Promise<{ account: Account; transaction: Transaction }> { - const account = options?.account ?? (await useAccountFixture(node.wallet)) - - const block = await useMinerBlockFixture(node.chain, 2, account, node.wallet) - - await expect(node.chain).toAddBlock(block) - await node.wallet.updateHead() - - const transaction = await useTxFixture( - node.wallet, - account, - account, - undefined, - undefined, - options?.expiration, - ) - - return { - account: account, - transaction: transaction, - } -} - /** * Produces a block with a transaction that has 1 spend, and 3 notes * By default first produces a block with a mining fee to fund the @@ -565,3 +315,32 @@ export async function useBlockWithTxs( return { block, account: from, transactions: block.transactions.slice(1) } } + +export async function useTxSpendsFixture( + node: IronfishNode, + options?: { + account?: Account + expiration?: number + }, +): Promise<{ account: Account; transaction: Transaction }> { + const account = options?.account ?? (await useAccountFixture(node.wallet)) + + const block = await useMinerBlockFixture(node.chain, 2, account, node.wallet) + + await expect(node.chain).toAddBlock(block) + await node.wallet.updateHead() + + const transaction = await useTxFixture( + node.wallet, + account, + account, + undefined, + undefined, + options?.expiration, + ) + + return { + account: account, + transaction: transaction, + } +} diff --git a/ironfish/src/testUtilities/fixtures/fixture.ts b/ironfish/src/testUtilities/fixtures/fixture.ts new file mode 100644 index 0000000000..21d7ab1c97 --- /dev/null +++ b/ironfish/src/testUtilities/fixtures/fixture.ts @@ -0,0 +1,113 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import fs from 'fs' +import path from 'path' +import { IJSON } from '../../serde' +import { getCurrentTestPath } from '../utils' + +const FIXTURE_FOLDER = '__fixtures__' + +export type FixtureGenerate = () => Promise | T +export type FixtureRestore = (fixture: T) => Promise | void +export type FitxureDeserialize = (data: TSerialized) => Promise | T +export type FixtureSerialize = ( + fixture: T, +) => Promise | TSerialized + +const fixtureIds = new Map() +const fixtureCache = new Map>() + +export function shouldUpdateFixtures(): boolean { + // Use the same parameters as jest snapshots for usability + return process.argv.indexOf('--updateSnapshot') !== -1 || process.argv.indexOf('-u') !== -1 +} + +export function disableFixtures(): void { + const currentTestName = expect.getState().currentTestName || '' + const testName = currentTestName.replace(/ /g, '_') + const fixtureInfo = fixtureIds.get(testName) || { id: 0, disabled: false } + fixtureIds.set(testName, fixtureInfo) + fixtureInfo.disabled = true +} + +export async function useFixture( + generate: FixtureGenerate, + options: { + restore?: FixtureRestore + process?: FixtureRestore + deserialize?: FitxureDeserialize + serialize?: FixtureSerialize + } = {}, +): Promise { + const testPath = getCurrentTestPath() + const testName = expect.getState().currentTestName || '' + const testDir = path.dirname(testPath) + const testFile = path.basename(testPath) + + const fixtureInfo = fixtureIds.get(testName) || { id: -1, disabled: false } + const fixtureId = (fixtureInfo.id += 1) + fixtureIds.set(testName, fixtureInfo) + + const fixtureDir = path.join(testDir, FIXTURE_FOLDER) + const fixtureName = `${testFile}.fixture` + const fixturePath = path.join(fixtureDir, fixtureName) + + const updateFixtures = shouldUpdateFixtures() + + let fixtures = fixtureCache.get(testPath) + + // Load serialized fixtures in if they are not loaded + if (!fixtures) { + fixtures = new Map() + + if (fs.existsSync(fixturePath)) { + const buffer = await fs.promises.readFile(fixturePath) + const data = IJSON.parse(buffer.toString('utf8')) as Record + + for (const test in data) { + fixtures.set(test, data[test]) + } + } + + fixtureCache.set(testPath, fixtures) + } + + let fixture: TFixture | null = null + + const serializedAll = fixtures.get(testName) || [] + fixtures.set(testName, serializedAll) + + if (!updateFixtures && !fixtureInfo.disabled && serializedAll[fixtureId]) { + // deserialize existing fixture + if (options.deserialize) { + const serialized = serializedAll[fixtureId] as TSerialized + fixture = await options.deserialize(serialized) + } else { + fixture = serializedAll[fixtureId] as TFixture + } + + if (options.restore) { + await options.restore(fixture) + } + } else { + // generate the fixture + fixture = await generate() + const serialized = options.serialize ? await options?.serialize(fixture) : fixture + serializedAll[fixtureId] = serialized + + if (!fs.existsSync(fixtureDir)) { + await fs.promises.mkdir(fixtureDir) + } + + const result = Object.fromEntries(fixtures.entries()) + const data = IJSON.stringify(result, ' ') + await fs.promises.writeFile(fixturePath, data) + } + + if (options.process) { + await options.process(fixture) + } + + return fixture +} diff --git a/ironfish/src/testUtilities/fixtures/index.ts b/ironfish/src/testUtilities/fixtures/index.ts new file mode 100644 index 0000000000..5d83fe9474 --- /dev/null +++ b/ironfish/src/testUtilities/fixtures/index.ts @@ -0,0 +1,6 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +export * from './account' +export * from './blocks' +export * from './transactions' diff --git a/ironfish/src/testUtilities/fixtures/transactions.ts b/ironfish/src/testUtilities/fixtures/transactions.ts new file mode 100644 index 0000000000..2e8245ace0 --- /dev/null +++ b/ironfish/src/testUtilities/fixtures/transactions.ts @@ -0,0 +1,108 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' +import { Assert } from '../../assert' +import { IronfishNode } from '../../node' +import { BurnDescription } from '../../primitives/burnDescription' +import { MintDescription } from '../../primitives/mintDescription' +import { SerializedTransaction, Transaction } from '../../primitives/transaction' +import { Account, Wallet } from '../../wallet' +import { createRawTransaction } from '../helpers/transaction' +import { useAccountFixture } from './account' +import { FixtureGenerate, useFixture } from './fixture' + +export async function restoreTransactionFixtureToAccounts( + transaction: Transaction, + wallet: Wallet, +): Promise { + await wallet.addPendingTransaction(transaction) +} + +export async function usePostTxFixture(options: { + node: IronfishNode + wallet: Wallet + from: Account + to?: Account + fee?: bigint + amount?: bigint + expiration?: number + assetId?: Buffer + receives?: { + publicAddress: string + amount: bigint + memo: string + assetId: Buffer + }[] + mints?: MintDescription[] + burns?: BurnDescription[] +}): Promise { + return useTxFixture(options.wallet, options.from, options.from, async () => { + const raw = await createRawTransaction(options) + return options.node.workerPool.postTransaction(raw) + }) +} + +export async function useTxFixture( + wallet: Wallet, + from: Account, + to: Account, + generate?: FixtureGenerate, + fee?: bigint, + expiration?: number, +): Promise { + generate = + generate || + (async () => { + const raw = await wallet.createTransaction( + from, + [ + { + publicAddress: to.publicAddress, + amount: BigInt(1), + memo: '', + assetId: Asset.nativeId(), + }, + ], + [], + [], + fee ?? BigInt(0), + expiration ?? 0, + ) + + return await wallet.postTransaction(raw) + }) + + return useFixture(generate, { + process: async (tx: Transaction): Promise => { + await restoreTransactionFixtureToAccounts(tx, wallet) + }, + serialize: (tx: Transaction): SerializedTransaction => { + return tx.serialize() + }, + deserialize: (tx: SerializedTransaction): Transaction => { + return new Transaction(tx) + }, + }) +} + +export async function useMinersTxFixture( + wallet: Wallet, + to?: Account, + sequence?: number, + amount = 0, +): Promise { + if (!to) { + to = await useAccountFixture(wallet) + } + + return useTxFixture(wallet, to, to, () => { + Assert.isNotUndefined(to) + + return wallet.chain.strategy.createMinersFee( + BigInt(amount), + sequence || wallet.chain.head.sequence + 1, + to.spendingKey, + ) + }) +} From c481b8239ee68dfed203da89f441e15336c9af71 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Fri, 6 Jan 2023 14:33:13 -0500 Subject: [PATCH 48/56] Rename accounts commands to wallet (#2845) --- ironfish-cli/src/commands/{accounts => wallet}/address.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/balance.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/create.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/export.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/import.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/index.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/notes.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/remove.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/repair.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/rescan.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/send.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/status.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/transaction.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/transactions.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/use.ts | 0 ironfish-cli/src/commands/{accounts => wallet}/which.ts | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename ironfish-cli/src/commands/{accounts => wallet}/address.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/balance.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/create.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/export.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/import.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/index.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/notes.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/remove.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/repair.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/rescan.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/send.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/status.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/transaction.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/transactions.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/use.ts (100%) rename ironfish-cli/src/commands/{accounts => wallet}/which.ts (100%) diff --git a/ironfish-cli/src/commands/accounts/address.ts b/ironfish-cli/src/commands/wallet/address.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/address.ts rename to ironfish-cli/src/commands/wallet/address.ts diff --git a/ironfish-cli/src/commands/accounts/balance.ts b/ironfish-cli/src/commands/wallet/balance.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/balance.ts rename to ironfish-cli/src/commands/wallet/balance.ts diff --git a/ironfish-cli/src/commands/accounts/create.ts b/ironfish-cli/src/commands/wallet/create.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/create.ts rename to ironfish-cli/src/commands/wallet/create.ts diff --git a/ironfish-cli/src/commands/accounts/export.ts b/ironfish-cli/src/commands/wallet/export.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/export.ts rename to ironfish-cli/src/commands/wallet/export.ts diff --git a/ironfish-cli/src/commands/accounts/import.ts b/ironfish-cli/src/commands/wallet/import.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/import.ts rename to ironfish-cli/src/commands/wallet/import.ts diff --git a/ironfish-cli/src/commands/accounts/index.ts b/ironfish-cli/src/commands/wallet/index.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/index.ts rename to ironfish-cli/src/commands/wallet/index.ts diff --git a/ironfish-cli/src/commands/accounts/notes.ts b/ironfish-cli/src/commands/wallet/notes.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/notes.ts rename to ironfish-cli/src/commands/wallet/notes.ts diff --git a/ironfish-cli/src/commands/accounts/remove.ts b/ironfish-cli/src/commands/wallet/remove.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/remove.ts rename to ironfish-cli/src/commands/wallet/remove.ts diff --git a/ironfish-cli/src/commands/accounts/repair.ts b/ironfish-cli/src/commands/wallet/repair.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/repair.ts rename to ironfish-cli/src/commands/wallet/repair.ts diff --git a/ironfish-cli/src/commands/accounts/rescan.ts b/ironfish-cli/src/commands/wallet/rescan.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/rescan.ts rename to ironfish-cli/src/commands/wallet/rescan.ts diff --git a/ironfish-cli/src/commands/accounts/send.ts b/ironfish-cli/src/commands/wallet/send.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/send.ts rename to ironfish-cli/src/commands/wallet/send.ts diff --git a/ironfish-cli/src/commands/accounts/status.ts b/ironfish-cli/src/commands/wallet/status.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/status.ts rename to ironfish-cli/src/commands/wallet/status.ts diff --git a/ironfish-cli/src/commands/accounts/transaction.ts b/ironfish-cli/src/commands/wallet/transaction.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/transaction.ts rename to ironfish-cli/src/commands/wallet/transaction.ts diff --git a/ironfish-cli/src/commands/accounts/transactions.ts b/ironfish-cli/src/commands/wallet/transactions.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/transactions.ts rename to ironfish-cli/src/commands/wallet/transactions.ts diff --git a/ironfish-cli/src/commands/accounts/use.ts b/ironfish-cli/src/commands/wallet/use.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/use.ts rename to ironfish-cli/src/commands/wallet/use.ts diff --git a/ironfish-cli/src/commands/accounts/which.ts b/ironfish-cli/src/commands/wallet/which.ts similarity index 100% rename from ironfish-cli/src/commands/accounts/which.ts rename to ironfish-cli/src/commands/wallet/which.ts From 2f532343720e5b7817b6da0bf0c8d62e66f2b159 Mon Sep 17 00:00:00 2001 From: jowparks Date: Fri, 6 Jan 2023 12:35:11 -0800 Subject: [PATCH 49/56] feat: wire up multi asset syncer to API (2/2) (#2795) * feat: wire up assets to masp syncer cli command * feat: fix typo chore: renaming to multi asset feat: add tests feat: cleanup logic more readable --- ...sp-transactions.ts => sync-multi-asset.ts} | 61 ++++++++++++++----- ironfish/src/webApi.ts | 17 +++--- 2 files changed, 55 insertions(+), 23 deletions(-) rename ironfish-cli/src/commands/service/{sync-masp-transactions.ts => sync-multi-asset.ts} (77%) diff --git a/ironfish-cli/src/commands/service/sync-masp-transactions.ts b/ironfish-cli/src/commands/service/sync-multi-asset.ts similarity index 77% rename from ironfish-cli/src/commands/service/sync-masp-transactions.ts rename to ironfish-cli/src/commands/service/sync-multi-asset.ts index efbb2aaaf0..42dad00f02 100644 --- a/ironfish-cli/src/commands/service/sync-masp-transactions.ts +++ b/ironfish-cli/src/commands/service/sync-multi-asset.ts @@ -1,12 +1,13 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { Asset } from '@ironfish/rust-nodejs' import { - ApiMaspUpload, + ApiMultiAssetUpload, GENESIS_BLOCK_SEQUENCE, GetTransactionStreamResponse, - MaspTransactionTypes, Meter, + MultiAssetTypes, PromiseUtils, TimeUtils, WebApi, @@ -20,10 +21,11 @@ const RAW_MAX_UPLOAD = Number(process.env.MAX_UPLOAD) const MAX_UPLOAD = isNaN(RAW_MAX_UPLOAD) ? 1000 : RAW_MAX_UPLOAD const NEAR_SYNC_THRESHOLD = 5 -export default class SyncMaspTransactions extends IronfishCommand { +export default class SyncMultiAsset extends IronfishCommand { + static aliases = ['service:syncMultiAsset'] static hidden = true - static description = 'Upload MASP transactions to an HTTP API using IronfishApi' + static description = 'Upload Multi Asset events to an HTTP API using IronfishApi' static flags = { ...RemoteFlags, @@ -53,7 +55,7 @@ export default class SyncMaspTransactions extends IronfishCommand { } async start(): Promise { - const { flags } = await this.parse(SyncMaspTransactions) + const { flags } = await this.parse(SyncMultiAsset) const apiHost = (flags.endpoint || process.env.IRONFISH_API_HOST || '').trim() const apiToken = (flags.token || process.env.IRONFISH_API_TOKEN || '').trim() @@ -111,7 +113,7 @@ export default class SyncMaspTransactions extends IronfishCommand { const buffer = new Array() async function commit(): Promise { - const serialized = buffer.map(serializeMasp) + const serialized = buffer.map(serializeMultiAssets) buffer.length = 0 await api.uploadMaspTransactions(serialized) } @@ -156,7 +158,7 @@ export default class SyncMaspTransactions extends IronfishCommand { while (true) { const headHash = (await api.headMaspTransactions()) || '' - const choices: MaspTransactionTypes[] = ['MASP_MINT', 'MASP_BURN', 'MASP_TRANSFER'] + const choices: MultiAssetTypes[] = ['MASP_MINT', 'MASP_BURN', 'MASP_TRANSFER'] const choice = choices[Math.floor(Math.random() * choices.length)] const connectedblockHash = uuid() await api.uploadMaspTransactions([ @@ -171,8 +173,7 @@ export default class SyncMaspTransactions extends IronfishCommand { transactions: [ { hash: uuid(), - type: choice, - assetName: 'jowparks', + multiAssets: [{ type: choice, assetName: 'jowparks' }], }, ], }, @@ -198,14 +199,42 @@ export default class SyncMaspTransactions extends IronfishCommand { } } -function serializeMasp(data: GetTransactionStreamResponse): ApiMaspUpload { +function serializeMultiAssets(data: GetTransactionStreamResponse): ApiMultiAssetUpload { + const txs = [] + // should not send transactions if block is disconnected + if (data.type !== 'connected') { + for (const tx of data.transactions) { + const multiAssets = [] + for (const mint of tx.mints) { + multiAssets.push({ + type: 'MULTI_ASSET_MINT' as MultiAssetTypes, + assetName: mint.assetName, + }) + } + for (const burn of tx.burns) { + multiAssets.push({ + type: 'MULTI_ASSET_BURN' as MultiAssetTypes, + assetName: burn.assetName, + }) + } + for (const note of tx.notes) { + // standard notes should not be included + if (note.assetId !== Asset.nativeId().toString('hex')) { + multiAssets.push({ + type: 'MULTI_ASSET_TRANSFER' as MultiAssetTypes, + assetName: note.assetName, + }) + } + } + + txs.push({ + ...tx, + multiAssets: multiAssets, + }) + } + } return { ...data, - transactions: data.transactions.map((tx) => ({ - ...tx, - hash: tx.hash, - type: 'MASP_TRANSFER', - assetName: 'STUBBED', - })), + transactions: txs, } } diff --git a/ironfish/src/webApi.ts b/ironfish/src/webApi.ts index 77fa413b95..e89923a685 100644 --- a/ironfish/src/webApi.ts +++ b/ironfish/src/webApi.ts @@ -15,9 +15,10 @@ type FaucetTransaction = { completed_at: string | null } -export type MaspTransactionTypes = 'MASP_TRANSFER' | 'MASP_BURN' | 'MASP_MINT' +export const MaspTransactionTypes = ['MASP_TRANSFER', 'MASP_BURN', 'MASP_MINT'] +export type MultiAssetTypes = typeof MaspTransactionTypes[number] -export type ApiMaspUpload = { +export type ApiMultiAssetUpload = { type: 'connected' | 'disconnected' | 'fork' block: { hash: string @@ -27,8 +28,10 @@ export type ApiMaspUpload = { } transactions: { hash: string - type: MaspTransactionTypes - assetName: string + multiAssets: { + type: MultiAssetTypes + assetName: string + }[] }[] } @@ -78,7 +81,7 @@ export class WebApi { } async headMaspTransactions(): Promise { const response = await axios - .get<{ block_hash: string }>(`${this.host}/masp/head`) + .get<{ block_hash: string }>(`${this.host}/multi_asset/head`) .catch((e) => { // The API returns 404 for no head if (IsAxiosError(e) && e.response?.status === 404) { @@ -106,11 +109,11 @@ export class WebApi { return response?.data.hash || null } - async uploadMaspTransactions(maspTransactions: ApiMaspUpload[]): Promise { + async uploadMaspTransactions(multiAssets: ApiMultiAssetUpload[]): Promise { this.requireToken() const options = this.options({ 'Content-Type': 'application/json' }) - await axios.post(`${this.host}/masp`, { operations: maspTransactions }, options) + await axios.post(`${this.host}/multi_asset`, { operations: multiAssets }, options) } async blocks(blocks: FollowChainStreamResponse[]): Promise { From ee68be8a27e937ed02ba7e25f7a56921879ed080 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Fri, 6 Jan 2023 13:40:01 -0800 Subject: [PATCH 50/56] fixes submittedSequence to be non-nullable (#2841) in the past we only populated submittedSequence for transactions that the node created and submitted. now we also populate submittedSequence for any transaction that is gossiped to the node. submittedSequence should no longer be null for any transaction in the wallet. - defaults submittedSequence to the block sequence for transactions found on blocks but not previously synced to the wallet through the mempool --- ironfish/src/wallet/account.ts | 4 ++-- ironfish/src/wallet/wallet.ts | 4 ---- .../wallet/walletdb/transactionValue.test.ts | 6 ++--- .../src/wallet/walletdb/transactionValue.ts | 24 +++++++------------ 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index f6ba7c4b92..ad9dbf16af 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -126,7 +126,7 @@ export class Account { const blockHash = blockHeader.hash const sequence = blockHeader.sequence const assetBalanceDeltas = new AssetBalanceDeltas() - let submittedSequence: number | null = null + let submittedSequence = sequence let timestamp = new Date() await this.walletDb.db.withTransaction(tx, async (tx) => { @@ -196,7 +196,7 @@ export class Account { async addPendingTransaction( transaction: Transaction, decryptedNotes: Array, - submittedSequence: number | null, + submittedSequence: number, tx?: IDatabaseTransaction, ): Promise { const assetBalanceDeltas = new AssetBalanceDeltas() diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 8d02420998..b92b23c7fc 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -1037,10 +1037,6 @@ export class Wallet { continue } - if (!submittedSequence) { - continue - } - // TODO: This algorithm suffers a deanonymization attack where you can // watch to see what transactions node continuously send out, then you can // know those transactions are theres. This should be randomized and made diff --git a/ironfish/src/wallet/walletdb/transactionValue.test.ts b/ironfish/src/wallet/walletdb/transactionValue.test.ts index f235031999..8007079b75 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.test.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.test.ts @@ -29,7 +29,7 @@ describe('TransactionValueEncoding', () => { timestamp: new Date(), blockHash: null, sequence: null, - submittedSequence: null, + submittedSequence: 123, assetBalanceDeltas, } const buffer = encoder.serialize(value) @@ -75,7 +75,7 @@ describe('TransactionValueEncoding', () => { timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, - submittedSequence: null, + submittedSequence: 123, assetBalanceDeltas, } const buffer = encoder.serialize(value) @@ -95,7 +95,7 @@ describe('TransactionValueEncoding', () => { timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, - submittedSequence: null, + submittedSequence: 123, assetBalanceDeltas: new BufferMap(), } const buffer = encoder.serialize(value) diff --git a/ironfish/src/wallet/walletdb/transactionValue.ts b/ironfish/src/wallet/walletdb/transactionValue.ts index b0304a90eb..9b58713f88 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.ts @@ -16,7 +16,7 @@ export interface TransactionValue { // This is populated when we create a transaction to track when we should // rebroadcast. This can be null if we created it on another node, or the // transaction was created for us by another person. - submittedSequence: number | null + submittedSequence: number assetBalanceDeltas: BufferMap } @@ -30,20 +30,18 @@ export class TransactionValueEncoding implements IDatabaseEncoding() const assetCount = reader.readU32() @@ -106,13 +100,11 @@ export class TransactionValueEncoding implements IDatabaseEncoding Date: Fri, 6 Jan 2023 14:39:51 -0800 Subject: [PATCH 51/56] delegates headHashes datastore to account (#2832) most datastores in the wallet are keyed by account and managed by the account. headHashes is an exception in that the wallet writes to the datastore and uses an in-memory cache of values. - removes in-memory headHashes cache - removes wallet methods for writing to headHashes - removes update of head hashes on wallet close (head hashes should only be updated when a block is connected or disconnected) - defines updateHeadHash on the account instead of the wallet --- .../src/primitives/transaction.test.slow.ts | 2 +- .../src/testUtilities/fixtures/account.ts | 2 +- ironfish/src/wallet/account.ts | 5 + ironfish/src/wallet/wallet.test.ts | 85 +++-------------- ironfish/src/wallet/wallet.ts | 94 +++++++------------ 5 files changed, 53 insertions(+), 135 deletions(-) diff --git a/ironfish/src/primitives/transaction.test.slow.ts b/ironfish/src/primitives/transaction.test.slow.ts index a0b1dee3c3..a771f2c898 100644 --- a/ironfish/src/primitives/transaction.test.slow.ts +++ b/ironfish/src/primitives/transaction.test.slow.ts @@ -63,7 +63,7 @@ describe('Accounts', () => { Assert.isNotNull(headhash) // Modify the headhash headhash[0] = 0 - await nodeA.wallet.updateHeadHash(accountA, headhash) + await accountA.updateHeadHash(headhash) const response = nodeA.wallet.createTransaction( accountA, diff --git a/ironfish/src/testUtilities/fixtures/account.ts b/ironfish/src/testUtilities/fixtures/account.ts index bc990eef62..59fb5210a9 100644 --- a/ironfish/src/testUtilities/fixtures/account.ts +++ b/ironfish/src/testUtilities/fixtures/account.ts @@ -20,7 +20,7 @@ export function useAccountFixture( deserialize: async (accountData: AccountValue): Promise => { const account = await wallet.importAccount(accountData) - await wallet.updateHeadHash(account, wallet.chainProcessor.hash) + await account.updateHeadHash(wallet.chainProcessor.hash) return account }, }) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index ad9dbf16af..3e368ae778 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -82,6 +82,7 @@ export class Account { await this.walletDb.clearNonChainNoteHashes(this, tx) await this.walletDb.clearPendingTransactionHashes(this, tx) await this.walletDb.clearBalance(this, tx) + await this.updateHeadHash(null, tx) } async *getNotes(): AsyncGenerator { @@ -548,6 +549,10 @@ export class Account { return this.walletDb.getHeadHash(this, tx) } + async updateHeadHash(headHash: Buffer | null, tx?: IDatabaseTransaction): Promise { + await this.walletDb.saveHeadHash(this, headHash, tx) + } + async getTransactionNotes( transaction: Transaction, ): Promise> { diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index a2dbd9a94e..4c6c9a4390 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -259,35 +259,6 @@ describe('Accounts', () => { expect(await accountA.getNoteHash(forkSpendNullifier)).toBeNull() }) - describe('updateHeadHash', () => { - it('should update head hashes for all existing accounts', async () => { - const { node } = nodeTest - - const newHeadHash = Buffer.alloc(32, 1) - - const accountA = await useAccountFixture(node.wallet, 'accountA') - const accountB = await useAccountFixture(node.wallet, 'accountB') - - const saveHeadHashSpy = jest.spyOn(node.wallet.walletDb, 'saveHeadHash') - - await node.wallet.updateHeadHashes(newHeadHash) - - expect(saveHeadHashSpy).toHaveBeenCalledTimes(2) - expect(saveHeadHashSpy).toHaveBeenNthCalledWith( - 1, - accountA, - newHeadHash, - expect.anything(), - ) - expect(saveHeadHashSpy).toHaveBeenNthCalledWith( - 2, - accountB, - newHeadHash, - expect.anything(), - ) - }) - }) - describe('scanTransactions', () => { it('should update head status', async () => { // G -> 1 -> 2 @@ -308,19 +279,19 @@ describe('Accounts', () => { const block2 = await useMinerBlockFixture(node.chain, 2, accountA) await expect(node.chain).toAddBlock(block2) - expect(node.wallet['headHashes'].get(accountA.id)).toEqual(block1.header.hash) - expect(node.wallet['headHashes'].get(accountB.id)).toEqual(null) + await expect(accountA.getHeadHash()).resolves.toEqual(block1.header.hash) + await expect(accountB.getHeadHash()).resolves.toEqual(null) await node.wallet.updateHead() // Confirm pre-rescan state - expect(node.wallet['headHashes'].get(accountA.id)).toEqual(block2.header.hash) - expect(node.wallet['headHashes'].get(accountB.id)).toEqual(null) + await expect(accountA.getHeadHash()).resolves.toEqual(block2.header.hash) + await expect(accountB.getHeadHash()).resolves.toEqual(null) await node.wallet.scanTransactions() - expect(node.wallet['headHashes'].get(accountA.id)).toEqual(block2.header.hash) - expect(node.wallet['headHashes'].get(accountB.id)).toEqual(block2.header.hash) + await expect(accountA.getHeadHash()).resolves.toEqual(block2.header.hash) + await expect(accountB.getHeadHash()).resolves.toEqual(block2.header.hash) }) it('should rescan and update chain processor', async () => { @@ -368,7 +339,7 @@ describe('Accounts', () => { const connectSpy = jest.spyOn(wallet, 'connectBlock') - expect(wallet.shouldRescan).toBe(false) + await expect(wallet.shouldRescan()).resolves.toBe(false) await wallet.scanTransactions() @@ -446,9 +417,9 @@ describe('Accounts', () => { const blockB = await useMinerBlockFixture(node.chain, 3, accountA) await node.chain.addBlock(blockB) - node.wallet['headHashes'].set(accountA.id, blockA.header.hash) - node.wallet['headHashes'].set(accountB.id, blockB.header.hash) - node.wallet['headHashes'].set(accountC.id, null) + await accountA.updateHeadHash(blockA.header.hash) + await accountB.updateHeadHash(blockB.header.hash) + await accountC.updateHeadHash(null) expect(await node.wallet.getEarliestHeadHash()).toEqual(null) }) @@ -468,44 +439,14 @@ describe('Accounts', () => { const blockB = await useMinerBlockFixture(node.chain, 3, accountA) await node.chain.addBlock(blockB) - node.wallet['headHashes'].set(accountA.id, blockA.header.hash) - node.wallet['headHashes'].set(accountB.id, blockB.header.hash) - node.wallet['headHashes'].set(accountC.id, null) + await accountA.updateHeadHash(blockA.header.hash) + await accountB.updateHeadHash(blockB.header.hash) + await accountC.updateHeadHash(null) expect(await node.wallet.getLatestHeadHash()).toEqual(blockB.header.hash) }) }) - describe('loadHeadHashes', () => { - it('should properly saturate headStatus', async () => { - const { node } = nodeTest - - const accountA = await useAccountFixture(node.wallet, 'accountA') - const blockA = await useMinerBlockFixture(node.chain, 2, accountA) - await node.chain.addBlock(blockA) - - await node.wallet.updateHead() - - // create a second account and import it so that its head hash is null - const { node: nodeB } = await nodeTest.createSetup() - const toImport = await useAccountFixture(nodeB.wallet, 'accountB') - const accountB = await node.wallet.importAccount(toImport) - - const blockB = await useMinerBlockFixture(node.chain, 2, accountA) - await node.chain.addBlock(blockB) - - await node.wallet.updateHead() - - await node.wallet.close() - expect(node.wallet['headHashes'].get(accountA.id)).toEqual(undefined) - expect(node.wallet['headHashes'].get(accountB.id)).toEqual(undefined) - - await node.wallet.open() - expect(node.wallet['headHashes'].get(accountA.id)).toEqual(blockB.header.hash) - expect(node.wallet['headHashes'].get(accountB.id)).toEqual(null) - }) - }) - describe('importAccount', () => { it('should not import accounts with duplicate name', async () => { const { node } = nodeTest diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index b92b23c7fc..d28e0e6021 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -57,8 +57,6 @@ export class Wallet { scan: ScanState | null = null updateHeadState: ScanState | null = null - protected readonly headHashes = new Map() - protected readonly accounts = new Map() readonly walletDb: WalletDB readonly logger: Logger @@ -110,7 +108,10 @@ export class Wallet { this.chainProcessor.onAdd.on(async (header) => { this.logger.debug(`AccountHead ADD: ${Number(header.sequence) - 1} => ${header.sequence}`) - const accounts = this.listAccounts().filter((account) => this.isAccountUpToDate(account)) + const accounts = await AsyncUtils.filter( + this.listAccounts(), + async (account) => await this.isAccountUpToDate(account), + ) await this.connectBlock(header, accounts) }) @@ -118,7 +119,10 @@ export class Wallet { this.chainProcessor.onRemove.on(async (header) => { this.logger.debug(`AccountHead DEL: ${header.sequence} => ${Number(header.sequence) - 1}`) - const accounts = this.listAccounts().filter((account) => this.isAccountUpToDate(account)) + const accounts = await AsyncUtils.filter( + this.listAccounts(), + async (account) => await this.isAccountUpToDate(account), + ) await this.disconnectBlock(header, accounts) }) @@ -150,7 +154,7 @@ export class Wallet { } } - get shouldRescan(): boolean { + async shouldRescan(): Promise { if (this.scan) { return false } @@ -160,7 +164,7 @@ export class Wallet { } for (const account of this.accounts.values()) { - if (!this.isAccountUpToDate(account)) { + if (!(await this.isAccountUpToDate(account))) { return true } } @@ -191,16 +195,11 @@ export class Wallet { const meta = await this.walletDb.loadAccountsMeta() this.defaultAccount = meta.defaultAccountId - for await (const { accountId, headHash } of this.walletDb.loadHeadHashes()) { - this.headHashes.set(accountId, headHash) - } - this.chainProcessor.hash = await this.getLatestHeadHash() } private unload(): void { this.accounts.clear() - this.headHashes.clear() this.defaultAccount = null this.chainProcessor.hash = null @@ -235,7 +234,7 @@ export class Wallet { } } - if (this.shouldRescan && !this.scan) { + if (!this.scan && (await this.shouldRescan())) { void this.scanTransactions() } @@ -256,10 +255,6 @@ export class Wallet { this.eventLoopAbortController.abort() await this.eventLoopPromise - - if (this.walletDb.db.isOpen) { - await this.updateHeadHashes(this.chainProcessor.hash) - } } async eventLoop(): Promise { @@ -285,35 +280,8 @@ export class Wallet { this.eventLoopResolve = null } - async updateHeadHashes(headHash: Buffer | null, tx?: IDatabaseTransaction): Promise { - let accounts = this.listAccounts() - - if (headHash) { - accounts = accounts.filter((a) => this.isAccountUpToDate(a)) - } - - await this.walletDb.db.withTransaction(tx, async (tx) => { - for (const account of accounts) { - await this.updateHeadHash(account, headHash, tx) - } - }) - } - - async updateHeadHash( - account: Account, - headHash: Buffer | null, - tx?: IDatabaseTransaction, - ): Promise { - this.headHashes.set(account.id, headHash) - - await this.walletDb.saveHeadHash(account, headHash, tx) - } - async reset(): Promise { - await this.walletDb.db.transaction(async (tx) => { - await this.resetAccounts(tx) - await this.updateHeadHashes(null, tx) - }) + await this.resetAccounts() this.chainProcessor.hash = null } @@ -330,7 +298,11 @@ export class Wallet { accounts?: Array, ): Promise>> { const accountsToCheck = - accounts || this.listAccounts().filter((a) => this.isAccountUpToDate(a)) + accounts || + (await AsyncUtils.filter( + this.listAccounts(), + async (a) => await this.isAccountUpToDate(a), + )) const decryptedNotesByAccountId = new Map>() @@ -423,7 +395,7 @@ export class Wallet { scan?.signal(blockHeader.sequence) } - await this.updateHeadHash(account, blockHeader.hash, tx) + await account.updateHeadHash(blockHeader.hash, tx) }) } } @@ -435,7 +407,7 @@ export class Wallet { await account.disconnectTransaction(header, transaction, tx) } - await this.updateHeadHash(account, header.previousBlockHash, tx) + await account.updateHeadHash(header.previousBlockHash, tx) }) } } @@ -473,7 +445,7 @@ export class Wallet { return } - if (!this.shouldRescan) { + if (!(await this.shouldRescan())) { this.logger.info('Skipping Scan, all accounts up to date.') return } @@ -496,7 +468,7 @@ export class Wallet { let remainingAccounts: Array = [] for (const account of this.accounts.values()) { - const headHash = this.headHashes.get(account.id) + const headHash = await account.getHeadHash() Assert.isNotUndefined( headHash, `scanTransactions: No head hash found for ${account.displayName}`, @@ -504,7 +476,7 @@ export class Wallet { if (BufferUtils.equalsNullable(startHash, headHash)) { accounts.push(account) - } else if (!this.isAccountUpToDate(account)) { + } else if (!(await this.isAccountUpToDate(account))) { remainingAccounts.push(account) } } @@ -549,7 +521,7 @@ export class Wallet { const newRemainingAccounts = [] for (const remainingAccount of remainingAccounts) { - const headHash = this.headHashes.get(remainingAccount.id) + const headHash = await remainingAccount.getHeadHash() Assert.isNotUndefined( headHash, `scanTransactions: No head hash found for remaining account ${remainingAccount.displayName}`, @@ -800,7 +772,7 @@ export class Wallet { try { this.assertHasAccount(sender) - if (!this.isAccountUpToDate(sender)) { + if (!(await this.isAccountUpToDate(sender))) { throw new Error('Your account must finish scanning before sending a transaction.') } @@ -1166,7 +1138,7 @@ export class Wallet { await this.walletDb.db.transaction(async (tx) => { await this.walletDb.setAccount(account, tx) - await this.updateHeadHash(account, this.chainProcessor.hash, tx) + await account.updateHeadHash(this.chainProcessor.hash, tx) }) this.accounts.set(account.id, account) @@ -1179,7 +1151,7 @@ export class Wallet { } async skipRescan(account: Account): Promise { - await this.updateHeadHash(account, this.chainProcessor.hash) + await account.updateHeadHash(this.chainProcessor.hash) } async importAccount(toImport: Omit): Promise { @@ -1201,7 +1173,7 @@ export class Wallet { await this.walletDb.db.transaction(async (tx) => { await this.walletDb.setAccount(account, tx) - await this.updateHeadHash(account, null, tx) + await account.updateHeadHash(null, tx) }) this.accounts.set(account.id, account) @@ -1322,7 +1294,7 @@ export class Wallet { async getEarliestHeadHash(): Promise { let earliestHeader = null for (const account of this.accounts.values()) { - const headHash = this.headHashes.get(account.id) + const headHash = await account.getHeadHash() if (!headHash) { return null @@ -1337,7 +1309,7 @@ export class Wallet { 'hex', )}. This account needs to be rescanned.`, ) - await this.updateHeadHash(account, null) + await account.updateHeadHash(null) continue } @@ -1353,7 +1325,7 @@ export class Wallet { let latestHeader = null for (const account of this.accounts.values()) { - const headHash = this.headHashes.get(account.id) + const headHash = await account.getHeadHash() if (!headHash) { continue @@ -1367,7 +1339,7 @@ export class Wallet { 'hex', )}. This account needs to be rescanned.`, ) - await this.updateHeadHash(account, null) + await account.updateHeadHash(null) continue } @@ -1379,8 +1351,8 @@ export class Wallet { return latestHeader ? latestHeader.hash : null } - isAccountUpToDate(account: Account): boolean { - const headHash = this.headHashes.get(account.id) + async isAccountUpToDate(account: Account): Promise { + const headHash = await account.getHeadHash() Assert.isNotUndefined( headHash, `isAccountUpToDate: No head hash found for account ${account.displayName}`, From da93782bbd518886f205c3802ae2df694da96bf7 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Fri, 6 Jan 2023 14:41:15 -0800 Subject: [PATCH 52/56] displays balance head hash and sequence in CLI (#2839) * displays balance head hash and sequence in CLI the account balance now includes chain state information (blockHash and sequence). includes this chain state in the balance CLI output so that it's clearer where on the chain the balance is reflective of. * fixes test * doesn't show head hash and sequence with balance by default only displays when --all or --explain are passed in * explain balance hash and sequence in --explain output * fixes lint --- ironfish-cli/src/commands/wallet/balance.ts | 8 ++++++++ ironfish/src/rpc/routes/wallet/getBalance.ts | 6 ++++++ .../src/rpc/routes/wallet/sendTransaction.test.ts | 12 ++++++++++++ ironfish/src/wallet/account.ts | 6 +++++- ironfish/src/wallet/wallet.test.ts | 2 +- ironfish/src/wallet/wallet.ts | 4 ++++ 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ironfish-cli/src/commands/wallet/balance.ts b/ironfish-cli/src/commands/wallet/balance.ts index cacc092b1a..b0634f24b3 100644 --- a/ironfish-cli/src/commands/wallet/balance.ts +++ b/ironfish-cli/src/commands/wallet/balance.ts @@ -62,6 +62,8 @@ export class BalanceCommand extends IronfishCommand { if (flags.all) { this.log(`Account: ${response.content.account}`) + this.log(`Head Hash: ${response.content.blockHash || 'NULL'}`) + this.log(`Head Sequence: ${response.content.sequence || 'NULL'}`) this.log( `Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetId)}`, ) @@ -82,6 +84,12 @@ export class BalanceCommand extends IronfishCommand { const unconfirmedDelta = unconfirmed - confirmed this.log(`Account: ${response.account}`) + + this.log( + `Your balance is calculated from transactions on the chain through block ${ + response.blockHash ?? 'NULL' + } at sequence ${response.sequence ?? 'NULL'}`, + ) this.log('') this.log(`Your balance is made of notes on the chain that are safe to spend`) diff --git a/ironfish/src/rpc/routes/wallet/getBalance.ts b/ironfish/src/rpc/routes/wallet/getBalance.ts index e93a657e0d..569869f656 100644 --- a/ironfish/src/rpc/routes/wallet/getBalance.ts +++ b/ironfish/src/rpc/routes/wallet/getBalance.ts @@ -19,6 +19,8 @@ export type GetBalanceResponse = { unconfirmed: string unconfirmedCount: number minimumBlockConfirmations: number + blockHash: string | null + sequence: number | null } export const GetBalanceRequestSchema: yup.ObjectSchema = yup @@ -36,6 +38,8 @@ export const GetBalanceResponseSchema: yup.ObjectSchema = yu unconfirmedCount: yup.number().defined(), confirmed: yup.string().defined(), minimumBlockConfirmations: yup.number().defined(), + blockHash: yup.string().nullable(true).defined(), + sequence: yup.number().nullable(true).defined(), }) .defined() @@ -66,6 +70,8 @@ router.register( unconfirmed: balance.unconfirmed.toString(), unconfirmedCount: balance.unconfirmedCount, minimumBlockConfirmations, + blockHash: balance.blockHash?.toString('hex') ?? null, + sequence: balance.sequence, }) }, ) diff --git a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts index 0ac244cee5..647049cb15 100644 --- a/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts @@ -106,6 +106,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(11), confirmed: BigInt(0), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) await expect(routeTest.client.sendTransaction(TEST_PARAMS)).rejects.toThrow( @@ -122,6 +124,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(21), confirmed: BigInt(0), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) await expect(routeTest.client.sendTransaction(TEST_PARAMS_MULTI)).rejects.toThrow( @@ -148,6 +152,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(11), confirmed: BigInt(11), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) await expect(routeTest.client.sendTransaction(TEST_PARAMS)).rejects.toThrow( @@ -171,6 +177,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(11), confirmed: BigInt(11), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) const result = await routeTest.client.sendTransaction(TEST_PARAMS) @@ -189,6 +197,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(21), confirmed: BigInt(21), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) const result = await routeTest.client.sendTransaction(TEST_PARAMS_MULTI) @@ -206,6 +216,8 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(100000), confirmed: BigInt(100000), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) const sendSpy = jest.spyOn(routeTest.node.wallet, 'send').mockResolvedValue(tx) diff --git a/ironfish/src/wallet/account.ts b/ironfish/src/wallet/account.ts index 3e368ae778..775640a30e 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -462,10 +462,12 @@ export class Account { unconfirmed: bigint unconfirmedCount: number confirmed: bigint + blockHash: Buffer | null + sequence: number | null }> { let unconfirmedCount = 0 - const { unconfirmed } = await this.getUnconfirmedBalance(assetId, tx) + const { unconfirmed, blockHash, sequence } = await this.getUnconfirmedBalance(assetId, tx) let confirmed = unconfirmed if (minimumBlockConfirmations > 0) { @@ -497,6 +499,8 @@ export class Account { unconfirmed, unconfirmedCount, confirmed, + blockHash, + sequence, } } diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index 4c6c9a4390..696a0a7494 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -920,7 +920,7 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(burnBlock) await node.wallet.updateHead() - expect(await node.wallet.getBalance(account, asset.id())).toEqual({ + expect(await node.wallet.getBalance(account, asset.id())).toMatchObject({ unconfirmed: BigInt(8), unconfirmedCount: 0, confirmed: BigInt(8), diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index d28e0e6021..9af0c3d1ba 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -563,6 +563,8 @@ export class Wallet { unconfirmedCount: number unconfirmed: bigint confirmed: bigint + blockHash: Buffer | null + sequence: number | null }> { const minimumBlockConfirmations = Math.max( options?.minimumBlockConfirmations ?? this.config.get('minimumBlockConfirmations'), @@ -579,6 +581,8 @@ export class Wallet { unconfirmed: BigInt(0), confirmed: BigInt(0), unconfirmedCount: 0, + blockHash: null, + sequence: null, } } From 47ad3f89437d2a9321d1d9434fa5482941cb73dd Mon Sep 17 00:00:00 2001 From: jowparks Date: Fri, 6 Jan 2023 14:47:18 -0800 Subject: [PATCH 53/56] fix: error in syncer due to renaming in webapi (#2848) --- ironfish-cli/src/commands/service/sync-multi-asset.ts | 7 +++++-- ironfish/src/webApi.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ironfish-cli/src/commands/service/sync-multi-asset.ts b/ironfish-cli/src/commands/service/sync-multi-asset.ts index 42dad00f02..2bedd92697 100644 --- a/ironfish-cli/src/commands/service/sync-multi-asset.ts +++ b/ironfish-cli/src/commands/service/sync-multi-asset.ts @@ -106,7 +106,6 @@ export default class SyncMultiAsset extends IronfishCommand { incomingViewKey: viewKey, head: head, }) - const speed = new Meter() speed.start() @@ -158,7 +157,11 @@ export default class SyncMultiAsset extends IronfishCommand { while (true) { const headHash = (await api.headMaspTransactions()) || '' - const choices: MultiAssetTypes[] = ['MASP_MINT', 'MASP_BURN', 'MASP_TRANSFER'] + const choices: MultiAssetTypes[] = [ + 'MULTI_ASSET_TRANSFER', + 'MULTI_ASSET_BURN', + 'MULTI_ASSET_TRANSFER', + ] const choice = choices[Math.floor(Math.random() * choices.length)] const connectedblockHash = uuid() await api.uploadMaspTransactions([ diff --git a/ironfish/src/webApi.ts b/ironfish/src/webApi.ts index e89923a685..9ebd7dbf31 100644 --- a/ironfish/src/webApi.ts +++ b/ironfish/src/webApi.ts @@ -15,8 +15,12 @@ type FaucetTransaction = { completed_at: string | null } -export const MaspTransactionTypes = ['MASP_TRANSFER', 'MASP_BURN', 'MASP_MINT'] -export type MultiAssetTypes = typeof MaspTransactionTypes[number] +export const MultiAsssetTransactionTypes = [ + 'MULTI_ASSET_TRANSFER', + 'MULTI_ASSET_BURN', + 'MULTI_ASSET_MINT', +] +export type MultiAssetTypes = typeof MultiAsssetTransactionTypes[number] export type ApiMultiAssetUpload = { type: 'connected' | 'disconnected' | 'fork' From b050d1a13046ee7ac32c9a9f83e5eaff7b8bcea3 Mon Sep 17 00:00:00 2001 From: Hugh Cunningham <57735705+hughy@users.noreply.github.com> Date: Fri, 6 Jan 2023 15:22:22 -0800 Subject: [PATCH 54/56] adds account filtering logic to connect/disconnect (#2820) * adds account filtering logic to connect/disconnect the wallet connectBlock method should only update accounts where the block to connect follows the account head. similarly, the disconnectBlock method should only update accounts whose head is equal to the block to disconnect. instead of filtering accounts outside of these methods and passing a list of accounts in, the methods should execute the filtering themselves to ensure that they don't leave account data in a bad state. - only connects a block for an account if the account's head hash is equal to the block's previousHeadHash or if the block is the genesis block and the account has a null head hash - only disconnects a block for an account if its hash is equal to the account's head hash - simplifies scan logic: do not track accounts during the scan, but rely on connectBlock to only connect blocks where appropriate * fixes lint * updates following rebase --- .../__fixtures__/wallet.test.ts.fixture | 336 ++++++++++++++++++ ironfish/src/wallet/wallet.test.ts | 123 ++++++- ironfish/src/wallet/wallet.ts | 82 ++--- 3 files changed, 477 insertions(+), 64 deletions(-) diff --git a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture index 7831f04555..789305911c 100644 --- a/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture +++ b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture @@ -2760,5 +2760,341 @@ } ] } + ], + "Accounts connectBlock should not connect blocks behind the account head": [ + { + "id": "0f0ecc13-3949-48b4-9d73-a512c7893680", + "name": "a", + "spendingKey": "0b62b1d8f076d62bf8f06c4b9b4f7f61a76c7648d7dfa348eb0883c148baf568", + "incomingViewKey": "0d02be8b9590e8adb54bcbbdeeeeb5bbdc4769cb1e5f0f7efc3f7cdb3ffaa105", + "outgoingViewKey": "e4488fb4097fcb01b1155c9776961a8c205f89d6c3f1acde6da6ab4402218a63", + "publicAddress": "89d0bcdb42b5a9cdf2ee2b2dea9f666f290827e9d067ce761231bac3c27a1338" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:64SyEHFXZToWj2WIVPSoW/q+fOV7LAGtuQ0y7/zASmM=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:TMUJ8nR8oOp4XHJhcBsALB9bR+AEJu4gKKSa1EnaCDQ=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672869653648, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAn+wQXFoQtI6J0JOxP8bWcxSYG2HsVKkih0ywp21Wpcmx8H1XlMQXTiiiFb48BqUbj3Lo7Ga9QJjqz7yuMDTyeL9p23jqizywdB3b7Omzsr2OVJsyVrGx4PmwF8JA7wRwbFLColfhG5YJfWzMVmXf/FMdyheSZVVrI9LPcwoI6JcB2paOwGHTMieO7OdCvWffYOc0U0gYIjhM+2l1FFgIY2HvxLACryzCaXcMS1Uhxq2vwiL1oIX6iQHbl5FX497psd4Wgm2PdTsAcURK1wRRhb8nupfrT3xQJ2XuHu+QhQhqdtqQFMdmQ/TkefUCg+WylKrJyTG0u18k0y8/8kJq2WGe6B4+KDFi0zskwFgm0LU/M+3g2ErSWUQWouIaXvkYx7REMHzyL6VGND6y3vIBreKuqvb7Zl8SCF4+odKgLBEFRyhG6YhEuf90HjMnjrdAJ3ef71UxfCZyfFqvM7H249GOmxVZbym1AwEPwjNjTsENedIiNqrOWrkHvGkoYChRyH2ah1mMMsKqqDycC8G4pTLIuccM3CRkMGuzvaa2QRgkZakMyQJyAQzWuUyANrpjn+FxYeH6VETDBOJUw6Rx9cph1u/uSTuywTr5GKNrs6UQVWfzlMSnDklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwxWuYOI8BAXd6FTFe3VgiZ3UnujP/Uio4/aGtEwAv9qz7/LPdeB2ylWvk8lOrD8LKxSp1pMhITI2ickbrfxFvBA==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "332C83D0AE8085DDABA2E23CA070C8EAEFED1846AB0C27097521D724D8B56A51", + "noteCommitment": { + "type": "Buffer", + "data": "base64:UaNuLfuUvTpJGOVpGH10tlJLswQgxqTkDozF8Evw7EM=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:2UWnGpQWlLHDkDNwxUIq7moTbRo/IPH6g778Qul3xKM=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672869654330, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAcdJzkb45TwwiiCHijgfumFDw9YPdFDZoGh9pRabcEVWmCHq4k1LLaVMlilIpRY6vMxdVJWNorxDj/VFNNd2GvAK7jH9NovZVL6h8SAlzotSUmIGJw54ucjgYzKCIPZX9odVSQ0NONTpZDFHFM7djv8kIb+xNhUPmqXctrOAqv1QRml7LmBed/bzC0o27GzTvNiicAmGg2midh+ECAavp3OHht+yLYxIIiBEuH5A9nlOtva+NlJt1KayDPECd1p4B0glZTpvWW84sjdRvNECWeUXI1NHtcxT/1v5twbsvUVrB4Kc5zityTQjqo1Q/ipMu6OxHp6UYwKqjxXwd2WsUV8ASHerbBwvzNHPVtgUuCH4zJ4AlP+bFFNOxeImwwpJjfpyPNPpmz5HeA1DvP676BSw1lMWHYmGQwlw+CSCBX4LRV3FpL6UOHmbhgp1ySiQL/JE1PgH3AxPogYIl/Nquk8e7D5s/wW+02WAsux+Gn6aXKrGFXC5qCIkaSVeM6OvZ8kxjWBZqXRjdRxRjVzaUy+NneatMMlkQZe2N+vtCHCztUBnoweUXGM2rhSfR9cpx9tT/ny7aa5rlAaRwMS5UAobZ66F32bUH5BL0ataYHXCctJhEFoyXl0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwOhBt1WpufOl/YqE/BKcRBZny4AQq+lyu8wOi3c3KQaUSW6v1sEl7X/m8N4G1hmj/M7eRaRekMpm/ReOERGoxBA==" + } + ] + } + ], + "Accounts connectBlock should not connect blocks equal to the account head": [ + { + "id": "19d03910-e69a-4145-8955-8c28056359c1", + "name": "a", + "spendingKey": "aa119d504fdc04ef1c14833930855d603be78ed8c402c331dd3a017aa9862948", + "incomingViewKey": "99ac7fe60429c890025e258e1c650c959528a06437653dded0fc084deef5aa07", + "outgoingViewKey": "a1644edc246c840f4eb4a89bbd23cf5e1d1540d1739b1ffa7a75696b4d8cccad", + "publicAddress": "60dec9b3cc87e74a8dbe0e3c9fe49d4b80ff8215e18e45a4621e62366d262496" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:Shz814imZF2g0M2lzxbuJiP6yQtUd1Guw2VLQRUTvVk=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:UK8W+DDg885EiCWbx4UFwMGh4nEc3JgMAmBGNlw0K6k=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672869655028, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAVrMmAmw4ZWtGMWO1/EcfpASbRAjDzHIFYgx5L8YPdbSTRjPAoIHdUTOiq/Avo5FlQYTAAJyHCr3go/FnUPABY+y1BESHgPf2bh3GOCwhv/yJdJ2StpE5BAVi6v417sErHb9P/ClK4U/olbrd0hUyD5bg4Bpm2hk1YKI8bFtqvV8P1sRDeASy3GMwVqwZg0JB0XeIqlmyMUjrlJU2XVyKw+FL5ryhbOeifHbKcFPAjDm4elOE9xRDBsUIljwgAQOH4st6g1U9JMQ4BG1cNwxEuWf3vxDK9u0RHWicRX5CBGxiykJcreTGbXB9S0mpDyR2PPCPldUiDvPz3ZjdTnl84o8js5I5tgwm94vfTRiAKLTkGc2v2oaezRsxvgXXnKQ5aHJ9qB3quw4o/hMjvD6RI7jDSrhd9tjC9msmewSta/LMq4mR+b1coKlOopTUWRV1gWtoyACc0Pe4Fs8yk3iuWY7oMBNFwejpSkGC6hS5GlidGHlYblRH8y+LLEwow0T2FLJu6y3S6qqAgF+gI1iD4pQaJssDudZ0FY6yk4V2DaEzplh01dL3lUesL0OxDY8IGlyajG7PjS5FAGwTPTkeRWEifSdBkR06wLKXIrsr3nt+fcIJ+wC1YUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwf5DwY/Psae8w4VrEqTdnJRE1ZP1ooU6RN7fh7eHvjTORCA+wNBpb3rIuedFRAElDjlMX4aWTVoUPYUBNcff+Cw==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "1EB94C626D05A85A8A3E324258C05B466745CDEFD2B4D27732DF90CB802CC2A8", + "noteCommitment": { + "type": "Buffer", + "data": "base64:Q3xiDuJGAD6gsp6xWN0SXoWUWzCl2oYLpySJL/ZFzQU=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:eaTUpc9yPftbhSm3GUM61l5Px2MJcRp+ReBRm9MqtVM=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672869655621, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA7JLu5HesbF7IhR4P8sNpPtAzp6PUebVBcJ5GAcl/Xk2tZyRYc31SMcmp+tpTd0Cw1TUL7ho/5rNFRb5HqpQckH72yalQVWEdmDkFBWhXsNWIkNvCa6XRZpWFDQXwWzX4cLCqUbLPJ2MWzn9P2cP/KDUsw8ucNCENakV30xsopq0C8AfgHyddf4uMgQhnZI9htJSLCEPgJpvB8oAYB9/m6GwdWuz/u898DvuxRNsIR9mj3HhM3qD4JvIHFffrrCJ+V3wP/h7RuFiY7ExXDEG9kk1wbebbo3Yw4sy7rjeHo4vr301TqVj+v8aYQVxueZFbT5HT8FTMhZK+ZfvKhckXyx2ZN8/ti1hMTCB1SMexgBxnBznlpM1KlH437sDo5b8MyWO+Q3ONl+4hFLtGC6wS3x9B1aL8bZ9SxeN6WnEEHo/UzOdLEiHpHKt8BLLIiJ3U7O5atPPygHX5iSGLmkwgIE0Vr1Y2TYfraQ+YEyClE/V5ihMgTPykBVnBDQfzgmQBh5f88RJsEip4xe8wVmgP8dugNlpip3DXjiVyTbw366N5xdjhzrbyU03Dptpy29cQCvnzNK09szL4+NIMwXTunKZZkSB9zl17SAQHKPOoT4ISwg25XgqWv0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwuNSLMnbKVH5jxuOdm7fDmj4uTYecUTWAC5Vj/g04SmgWBcZI5DjDWBAcM656RuDldYdLzJTj9DBo+yJHHMyfCg==" + } + ] + } + ], + "Accounts connectBlock should not connect blocks more than one block ahead of the account head": [ + { + "id": "5962e521-1d81-429e-b653-0a7a00d960a9", + "name": "a", + "spendingKey": "e7dc57187cc3ac8ff2e7c264619ae55d579c0ed6a0c862ac70a68c2a8d17d28a", + "incomingViewKey": "cd5e3283afa5620346457702ab6fa631be7a7d3b60fca280b852af3aab97cb07", + "outgoingViewKey": "986c785cb8f6d9bd084b65ded74cd6d7dbf502d74015db1c2bac02526588e118", + "publicAddress": "038526afcd34206a601fec23f29cd62f2ae31b629c91aa89dba128f1a59fe858" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:ANQMcmQsClbWt/dUko9/5dCixEeO7jbS0U4/FwwXllI=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:yJrbfLnT8Nj8UBLu7SLwPKOS13DUpm29vZKtDcusG6s=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672869656302, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAbeMf3+BqlUhSJONtd6ZUpDuLZRHWvfG6KPKrAQtZ7iWCGyTFOW/czuPnGIxnvnGu2JCZfS5kxoJ2/yvUfoAOlp1JCeab9+nimETaRguJ5puxVBp6Sx0d80sUTq74Xq6YLHt+FH3vvjrP+TgU/wdEA814FFW4ZyHqOE2DKToqRtkFw6QabTHTYekz/NTShO7+Ng9i6RWwSb1iRlKxRtWNtbPASrtHPbc77iMRKiRoqX2SnKPys3D36Ikeb7FMa7kfx8ZShwZlX1k9FbMTzqR3JJdl+s68uPYDb/USdmp66VSZWs0pelYQATdbyss9maTG8tbVbVRR9B176APT09Qfc+5wQtJxtM58gG+1hKPpe9OLJGkM2Df5n1dPsU6QZGIHaLlwZZAx4kl6lG6FMaK5imS8xJPJHxhMe1yuG9wXT7/eD4vepKoImjLsrGWaofWVyOUDAvv/Hs09cNPbipEZgdtHLUJe4s/BM03ijdea0F2uw/LkHiFSwHP0A7fobeErBD1TVmAIl5vKaEfdQpFsgMGps1pgSCIqS92WFcYcb77WAgXtYrNtg+Il2EsCvOX5bh8RgqkEtxEFPQalu1w+iNYAQrD8J09Nbt+CFuHbjcWWEmHsBd4U6Ulyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJDpBC4eDTisCLwiJU3Bx+zyc5sObH533VOSWC+cyuMFGFxb0nDBojPWnSbeZSRLEm+J8/CQqOGbESexv4QLeCw==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "2227963839B5F6025D7710BE32094E05AEA17C0934BD15FFC7AFD7F31FA02C24", + "noteCommitment": { + "type": "Buffer", + "data": "base64:bldJfPPsnMR6YNdKFoEF2aQwEKmuuuFK2msbKGH2cTM=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:66AE4zqyw690CzS2DF1PAVgf3AQh5Ro1MMGoySPANhs=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672869656899, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAyfjdhZ4Wbd1cfxwsFt5DUeWFP2PEbIJgJTvy7oxLB0GFtvr6SwHbCzB30AgZ5g2QHIDVbqfmetm3TPPfykIyky+BUyDLBsdtpv+jLQF28B+kD5MYvBUnfis72WfirlAlka19vtgkWRegqx3DHbIzG17R9myn05Yl8/bF4UYxZpMZt6PR7CQWQ9wMH3kxe/DMlfjft1PnbdqbGz+Faol0hj4zFkQOoUmr9Qo5JlwP8FSycoW5VtXwOxB7nlm4nlgVP6U3jFVtamcWTjCbiDAwK3n59JH4Dl6m4UhnaPEnEW0z1MwKfHT0bFO0RdDkmgM6PuCH5kCRjC9RR0WZdZbjTiP8cfSF06h9chTBWqVuhTngmsjwlOr0QFIVv9w0iDs1RU9P2wC3qY/YVRW4WIBAmnGgUJxYRtHLfr1C/LuZ49QKNkIG5ccx5cjvzzzUL9yRxsyEcVOZcesLmaVIdG/h+MJo0o4HMD+fd+IUN0PqN5c6fQH0qBNU56zcMtdpXVO5Z7+grqVpDHF9NGDx6/8hZZsc8oXVnkN2IzK6+eUwhR93Dbpb8qmKY7IkBxuF1K175NPO5fgpr1g/8x8hxbWhKIcNUrZPh8zCMvIUEDLa0ZZ1TtGGCu9yfklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw0coUKvTUDwgaHw4dIRJOaWdbHDO4gc0HoE67hzHJBGQx3Hetu1boLA1pecAshqOHfFndH0nufv/UBQJioG8JCQ==" + } + ] + }, + { + "header": { + "sequence": 4, + "previousBlockHash": "A670CABE65FB7BC27E2AF68F0D199E5905897E5988A39E4364C599836CED1D31", + "noteCommitment": { + "type": "Buffer", + "data": "base64:CATKTtbmYJLsL2pOwM23RvQ/tLvfCt64gxauROJXIhk=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:rx3fe7EK9SD5eaJKxCR8jCN7lcu72zL7cPDnC8FJI24=" + }, + "target": "878277375889837647326843029495509009809390053592540685978895509768758568", + "randomness": "0", + "timestamp": 1672869657448, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 6, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAATzA73r759YhjcsAnIvmR6uSi2DgCH3Gf13QDUPK0cd6DUxC5zHvvcP0oDM6E1W/bnnI7waxhCZEiIRO8lRDtZK8BUQxuzPKSGU578Cm7Ye+WaVVff4mN2RcKEkyXO6JXlfyaFX3IJ/H3qf6k3ABbkIMRD3s6gvsxjPjHwC7jB+kRUAcdycXKiS9/WSl4lIkrlR475AGLgq6WBg4rSXGAAjD2nMOPS95ovOZuRs2hKRWNuFp+l5Wl6aKj9QCAjsp1j+5Ud7YcwCuGXb5A9WCkFSBKQgIkZNtoZ+St5dLde/UmoHXY9uayprArWYTAt4BivX+qnlk3LETIebphoYHbWGzkRFVftFFH66xuuPcBaRn+wbdtmcDWhMxU1MyFffhbRp7JIjXGGkZ6Xls+hT+geVOhahGQ9KfmEpuxmIDQuSBrRVq1W4JPb5+O6YBGTgATNclYYIPc13uMV5NPMtRFKSkBAPj7MWO3C6xBnJXOMYcr775HJC6l6/4RO/Ok6WxbXttCgp7kZ3Xq/PtZms68kyNxmhQWS3XpuWj1i3pi1N9zhAKs61N3btH4ZwZYG3GYylHxHjQC8JCgLFPSplpc1ClD3poKRvcV0r4PgpdUjbdg0g1ecD0KVklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw/Gt8qGZ/acCWuT6zOkH4moCt6NBWNx2or6egvECf+m3A8AU31a852NktWkjmEF4+ROhwheYkgbGj+68kxb3yCw==" + } + ] + } + ], + "Accounts disconnectBlock should not disconnect blocks before the account head": [ + { + "id": "08dbac9d-1271-4797-8771-a33dd14c8fab", + "name": "a", + "spendingKey": "74568f96f5425974a0b488285a0fd9926536e9e5fcdbc49b822910385195a90d", + "incomingViewKey": "7b1f2a321e28ed11bd1b4f8d4be27eaf94c1683f4b67bfac31d01fa80b020d03", + "outgoingViewKey": "d965a1abe9756c0a83f4a2e2644d1947c01fd3285df59a16047c878938fe072d", + "publicAddress": "8dfb7c3db576fa447061ffa5e984d0bb34a7c08b903f9e7ceb772ad76526c0c6" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:BSZEw8ECebxwNYxgync8zZw4tq+aHxcfUFunRcBx2js=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:VWZ//8f0Ib0yPgopvzICQNfwiaw4GyqcMNaGlydnNSA=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672869658663, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAx+ShcqLPZ2lq+jMQI81mRyJlJbCfmuSUDfazaaWH1Tu1+zDqCqxPmyPYUo8I9ny077QN12q5Z9haVEEMIosqKEWZr/i3FMa5uKO6SymGGum5kfFEC/KLS+D3EFwU6PTfkpaWPn1sYoGPKacy1xMQjhJ4SwDm2/jlwzympDgMZcAKAcFw8VHK/N34JE3ru0MA3Fy38MLYyGcsa979un8ULYE7jbiENG/cR83Z5jBu8RqGmIiyK6UEXR0HBiwwBuAF0hCbt2o2K8IbpJhyTm5yJds2vCSzEu5QvRMHhkaNvSlZw2pEeMZQWL0l2dMMZIJwHtt892bLhE/b+3xstnAnxtbqRETxCm9sqmC7oMBK5P/Nd2c/Xno12w92/+hNg+8RfcpWNGsTzV3vMjC8xk3ffQ/of/xMPIY6DQAfigruoxPEPoT/IsdSc02Zoqeklf7iTyF9QPGCJBFGSKdg5sSbHFpEaHtAsLeaJYFnBkx9wfsPbulf7Yry8BLqNP1KLfn0A7ufHwMLtv7knF3Egici41VilTo1sEHc1p9sGv01GgSyaa/SuJIFNKrNbxOgwWRFHuv5ZNPmlKHfQfryvMKyi22I8Muj5bZneXaE/rgwl2cEENlIekZoXUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwmUvI3ap8des2NGfvRA5WX5C+8q1+fzm7tJguN5oVZSfPLmqwrdQWRvi96X/vf4UWqE12dC7UHNrs9v65nng9Dg==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "86108BA66CB96EA0AEC4464B9E7101AEE3FED4A7E6301AB6582030447133F153", + "noteCommitment": { + "type": "Buffer", + "data": "base64:uxrp3Tf+7f26/ihIo9+YZ2ZCtCmzm2K1TPaNO2y9yR4=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:rVtr2bz4J2duAlOS19KE40EebnlqROvZ7BCsVAVVQCU=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672869659250, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAe8wdW611AIVYxjHuD4zFu0AdqIOayeexlc96tGtYyESLPdq+Yx2EK7up3dmnG3RLMff7WgMBNlDFCJun/wpb3hdKMIP6GXjCShXvW8OXXrWMBIxvkUiV0mDPAVFA81RN+SN1a7CwiZ3tp/ZX+av2myg0Mx0U0F/Mx6RGGTmLMboThq0E+Jps9SFf6RoeF9hdaum71DQMCGWC1zdRSM4lNFlWJh8KfAHB51LLrdlPfvaGT0xfEGX6so/m6DDXlxRHBwpHZdS4uiuapfsIzSk7oKd+YIi9tz7YzcNWYvyw+J158c5KGN71a+o5XL/EQFuHmGzod/NtYuLtI4+1g4EOCkeRb5xMMszy42al7SjDVVVwIK7jSdeJh31AKOvDmXVXKpf4d20ODRMwwb4LvjJnf1XSnHFMH4b9dqqAn2Jvabg+GcAQIN0O9B1oYS49DGqW+Uwck0f7v7gd+u4VCZbXjqzYjLmVT7n6ycAitn9vVud+HSlBgyvO53Og85M10KCJx7LM5gT+7Ot8A+g7IoRks/LMdi6FwQL1U7YiO2xvKqY/uedMdhzuY8t9C4PEzfs5BhQnqM2iQoIU1P2oj7VYvXAJI469DxlxJjyqjVpE+Ss3xJ50gqV2q0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwv16tPmHcENyfTMQSG81jO2vnm9J/cy2Zk7R/euTZ69wQ+oXfaaKlpYXaTWRsAt49sE8erk3cMxMf7Z6ld6qsCQ==" + } + ] + } + ], + "Accounts disconnectBlock should not disconnect blocks ahead of the account head": [ + { + "id": "ecbe8903-04ea-4820-99b0-8c364326af7e", + "name": "a", + "spendingKey": "390af0750d8ee91ff8fb2ec9e929d353268b0db29d5ce25af4258eebc589cb17", + "incomingViewKey": "e4f4afd9da15b5e3bb3e70980e1f514a55343a95961b511d953dcf06d6279203", + "outgoingViewKey": "6eda09209025034e7cc458740ba114f90efd6cbaea6e84a5fb9704e3662e97c1", + "publicAddress": "beb50c384349afd976e5d81e117c25bb838a8230d6b836f6ea47883a035258e7" + }, + { + "header": { + "sequence": 2, + "previousBlockHash": "D179D8B74987D6617267D46F4958554BA0DF02D7E5E6117DB02D6FF38FD0F6DA", + "noteCommitment": { + "type": "Buffer", + "data": "base64:44S3/6Liys8RF8nutw3YXabV9Qq3/olIfx4C65Qj5XE=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:OPNmUUmJx9gYsjjchtNfaE0fkuQbMrJU19qFLj3GtsY=" + }, + "target": "883423532389192164791648750371459257913741948437809479060803100646309888", + "randomness": "0", + "timestamp": 1672869659953, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 4, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA9KabLyjW7kVtrTsUMrwmqV0X+Hkt+M9kZyaeJN5pIGitVADnCfgpR08rheaW1UZrdHp+LVktHvV4UJfeAD/PyJjoMC8ftLPFcla6eFuaayeUdLbB2R68edudlAh617OJvj/EoTmvMIVXT3lUwLgfqEUEASZ46aLyi2OlnP35WuEOH6Gq70K6zMzr1/lAP+RLySZoM0F7qEL+wFZwK5m8xr2XtXKwrqawvgvyD+vHIh62g6tQ0Mxz8+i1c2kASjzGJDwbCd0PwR6Mo6BnygeLsKzyKzuZsXzQKIhB/UsNXEQQR64Bx2yAVkj0FFgKQJ2sM6eelc5RXOC5EDep3Ft/CS/aDo4rM638m5qgEp67BuP3uAPEPnHZUX/EhFfTOqVuYGOgAn9BGgQtKKUbPhLWdQdFKsnQ3EKNgBFtUl16OIfcjhmRd3/oWMrusauwfOvGHiI22WUUOUvr5ErGuRMiz5JthadlSHSZ6LelQLsGnEPPBd4oHwwe+QAq4Rx3bJYbwLds5HKyT1LAnWYhMydDQh7U+i61AJuh5vbRObKnbr3CJl23WajVzHuHlmnxU0byRCcrnrfpKkywBfW/hBsPXeTV+R1klVeIiADqYCgmoTfKNRXXw460N0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYTu6DdHIKkOlWwI8UrxnpOUGGcVIKzCcxWZWw7bm1MFWQ4ZM5NHAkDMyKRfpR3WdKBDstmcABvC/xe6rIxc2Cg==" + } + ] + }, + { + "header": { + "sequence": 3, + "previousBlockHash": "B8F58DC285BAEF4270749E6D108D0002548BD876889F02120DF3C10301741D01", + "noteCommitment": { + "type": "Buffer", + "data": "base64:qthp5YmFSo54cENsc2TzMbz9JAXl+RvwpqEbjS7X+0s=" + }, + "transactionCommitment": { + "type": "Buffer", + "data": "base64:zsxQDpGWG12wlEJYwGp625SAVa3M9pU8wUskSbcQyCU=" + }, + "target": "880842937844725196442695540779332307793253899902937591585455087694081134", + "randomness": "0", + "timestamp": 1672869660526, + "graffiti": "0000000000000000000000000000000000000000000000000000000000000000", + "noteSize": 5, + "work": "0" + }, + "transactions": [ + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA6zsPdPwmfzZ4+ToWkfvtcV4tH1Q8lx5QlOYHXWAl7aSr4mHARirN0WVfVn2pqhtcordFXlnFvnPSxoazb5ly/qbVZ9JGxpP14qzG+PnzA0ai1m9x3dRZxxfQ/zsxCVtY5N7V384w84eIGndmmC7oslC7HgUueQqbPo7p66GXoycOr26Q+EZQRqnqpLbnheyEtKAGjDp0SXltCM4spLKL22hDyoFwfitpGgdu2rVWWxONQiWSOEXd9TVb1LOpJfBUfZqNya3ZI/wJzaAycbTQAUuQPgWqRBNh25qiItt73/NAY+OxujA7ya4cZgidYrKw2KfSwYx/zB8xhhtHOpD5LhBpONWGtTZ23ckh5kkPSGMMCE+kA6ct21TxP9A/o+QfPydXpJ3/9JsHRgJZ9re+NCH6cBkPEbIOt8iEDKN2BseVKWdEDfP/H9lhZ+zFzAT3R34hNUAz8BGjbfSvns2WzUHgzEPwQESf3VOhI/7qaRVjxkUGd+efBhteYfZgmBcBKk+mhaeVVZcFfQqDZfP/vVRKBpvHH8/FUq9+vTjhAFLhVFJTkWl8llsD5oCzvwukp9JMxZfr/s6mb/WCD92fDh2s0R1bRAfSy8Y12z9/uJmNe/VTC8BFCElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBGodviu8Y3GCDHBEVYg8P6obMKDc9xH5wjNW6uxtTCYlPutN3BVlnGNHQXUpTI4H6udWLP/ZQbxlpZGowF7TAQ==" + } + ] + } ] } \ No newline at end of file diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index 696a0a7494..318d7b84f7 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -1043,7 +1043,7 @@ describe('Accounts', () => { const { block: blockA2, transaction } = await useBlockWithTx(node, accountA, accountB) await expect(node.chain).toAddBlock(blockA2) - await node.wallet.connectBlock(blockA2.header, [accountA, accountB]) + await node.wallet.connectBlock(blockA2.header) const transactionValue = await accountA.getTransaction(transaction.hash()) @@ -1065,7 +1065,7 @@ describe('Accounts', () => { const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB) await expect(node.chain).toAddBlock(blockA2) - await node.wallet.connectBlock(blockA2.header, [accountA, accountB]) + await node.wallet.connectBlock(blockA2.header) const accountAHeadHash = await accountA.getHeadHash() @@ -1088,11 +1088,84 @@ describe('Accounts', () => { const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) await expect(node.chain).toAddBlock(blockA2) - await node.wallet.connectBlock(blockA2.header, [accountA, accountB]) + await node.wallet.connectBlock(blockA2.header) const balanceAfter = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceAfter.unconfirmed).toEqual(1999999998n) }) + + it('should not connect blocks behind the account head', async () => { + const { node } = await nodeTest.createSetup() + + const accountA = await useAccountFixture(node.wallet, 'a') + + const blockA1 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA1) + await node.wallet.updateHead() + + const blockA2 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA2) + + await node.wallet.connectBlock(blockA2.header) + + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + + // Try to connect A1 again + await node.wallet.connectBlock(blockA1.header) + + // accountA head hash should be unchanged + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + }) + + it('should not connect blocks equal to the account head', async () => { + const { node } = await nodeTest.createSetup() + + const accountA = await useAccountFixture(node.wallet, 'a') + + const blockA1 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA1) + await node.wallet.updateHead() + + const blockA2 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA2) + + await node.wallet.connectBlock(blockA2.header) + + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + + const updateHeadSpy = jest.spyOn(accountA, 'updateHeadHash') + + // Try to connect A2 again + await node.wallet.connectBlock(blockA1.header) + + expect(updateHeadSpy).not.toHaveBeenCalled() + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + }) + + it('should not connect blocks more than one block ahead of the account head', async () => { + const { node } = await nodeTest.createSetup() + + const accountA = await useAccountFixture(node.wallet, 'a') + + const blockA1 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA1) + await node.wallet.updateHead() + + const blockA2 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA2) + const blockA3 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA3) + + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA1.header.hash) + + const updateHeadSpy = jest.spyOn(accountA, 'updateHeadHash') + + // Try to connect A3 + await node.wallet.connectBlock(blockA3.header) + + expect(updateHeadSpy).not.toHaveBeenCalled() + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA1.header.hash) + }) }) describe('disconnectBlock', () => { @@ -1190,5 +1263,49 @@ describe('Accounts', () => { const balanceAfterDisconnect = await accountA.getUnconfirmedBalance(Asset.nativeId()) expect(balanceAfterDisconnect.unconfirmed).toEqual(2000000000n) }) + + it('should not disconnect blocks before the account head', async () => { + const { node } = await nodeTest.createSetup() + + const accountA = await useAccountFixture(node.wallet, 'a') + + const blockA1 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA1) + await node.wallet.updateHead() + + const blockA2 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA2) + await node.wallet.updateHead() + + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + + // Try to disconnect blockA1 + await node.wallet.disconnectBlock(blockA1.header) + + // Verify accountA head hash unchanged + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA2.header.hash) + }) + + it('should not disconnect blocks ahead of the account head', async () => { + const { node } = await nodeTest.createSetup() + + const accountA = await useAccountFixture(node.wallet, 'a') + + const blockA1 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + await expect(node.chain).toAddBlock(blockA1) + await node.wallet.updateHead() + + const blockA2 = await useMinerBlockFixture(node.chain, undefined, accountA, node.wallet) + + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA1.header.hash) + + const updateHeadSpy = jest.spyOn(accountA, 'updateHeadHash') + + // Try to disconnect blockA2 + await node.wallet.disconnectBlock(blockA2.header) + + expect(updateHeadSpy).not.toHaveBeenCalled() + await expect(accountA.getHeadHash()).resolves.toEqualHash(blockA1.header.hash) + }) }) }) diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 9af0c3d1ba..bd02d94c9d 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -108,23 +108,13 @@ export class Wallet { this.chainProcessor.onAdd.on(async (header) => { this.logger.debug(`AccountHead ADD: ${Number(header.sequence) - 1} => ${header.sequence}`) - const accounts = await AsyncUtils.filter( - this.listAccounts(), - async (account) => await this.isAccountUpToDate(account), - ) - - await this.connectBlock(header, accounts) + await this.connectBlock(header) }) this.chainProcessor.onRemove.on(async (header) => { this.logger.debug(`AccountHead DEL: ${header.sequence} => ${Number(header.sequence) - 1}`) - const accounts = await AsyncUtils.filter( - this.listAccounts(), - async (account) => await this.isAccountUpToDate(account), - ) - - await this.disconnectBlock(header, accounts) + await this.disconnectBlock(header) }) } @@ -361,11 +351,16 @@ export class Wallet { return decryptedNotes } - async connectBlock( - blockHeader: BlockHeader, - accounts: Account[], - scan?: ScanState, - ): Promise { + async connectBlock(blockHeader: BlockHeader, scan?: ScanState): Promise { + const accounts = await AsyncUtils.filter(this.listAccounts(), async (account) => { + const accountHeadHash = await account.getHeadHash() + + return ( + BufferUtils.equalsNullable(accountHeadHash, blockHeader.previousBlockHash) || + (accountHeadHash === null && blockHeader.sequence === 1) + ) + }) + for (const account of accounts) { await this.walletDb.db.transaction(async (tx) => { for await (const { @@ -400,7 +395,11 @@ export class Wallet { } } - async disconnectBlock(header: BlockHeader, accounts: Account[]): Promise { + async disconnectBlock(header: BlockHeader): Promise { + const accounts = await AsyncUtils.filter(this.listAccounts(), async (account) => + BufferUtils.equalsNullable(await account.getHeadHash(), header.hash), + ) + for (const account of accounts) { await this.walletDb.db.transaction(async (tx) => { for await (const { transaction } of this.chain.iterateBlockTransactions(header)) { @@ -459,28 +458,6 @@ export class Wallet { const startHash = await this.getEarliestHeadHash() - const endHash = this.chainProcessor.hash || this.chain.head.hash - const endHeader = await this.chain.getHeader(endHash) - - // Accounts that need to be updated at the current scan sequence - const accounts: Array = [] - // Accounts that need to be updated at future scan sequences - let remainingAccounts: Array = [] - - for (const account of this.accounts.values()) { - const headHash = await account.getHeadHash() - Assert.isNotUndefined( - headHash, - `scanTransactions: No head hash found for ${account.displayName}`, - ) - - if (BufferUtils.equalsNullable(startHash, headHash)) { - accounts.push(account) - } else if (!(await this.isAccountUpToDate(account))) { - remainingAccounts.push(account) - } - } - // Priority: fromHeader > startHeader > genesisBlock const beginHash = fromHash ? fromHash : startHash ? startHash : this.chain.genesis.hash const beginHeader = await this.chain.getHeader(beginHash) @@ -490,6 +467,9 @@ export class Wallet { `scanTransactions: No header found for start hash ${beginHash.toString('hex')}`, ) + const endHash = this.chainProcessor.hash || this.chain.head.hash + const endHeader = await this.chain.getHeader(endHash) + Assert.isNotNull( endHeader, `scanTransactions: No header found for end hash ${endHash.toString('hex')}`, @@ -507,7 +487,6 @@ export class Wallet { this.logger.info( `Scan starting from earliest found account head hash: ${beginHash.toString('hex')}`, ) - this.logger.info(`Accounts to scan for: ${accounts.map((a) => a.displayName).join(', ')}`) // Go through every transaction in the chain and add notes that we can decrypt for await (const blockHeader of this.chain.iterateBlockHeaders( @@ -516,26 +495,7 @@ export class Wallet { undefined, false, )) { - await this.connectBlock(blockHeader, accounts, scan) - - const newRemainingAccounts = [] - - for (const remainingAccount of remainingAccounts) { - const headHash = await remainingAccount.getHeadHash() - Assert.isNotUndefined( - headHash, - `scanTransactions: No head hash found for remaining account ${remainingAccount.displayName}`, - ) - - if (BufferUtils.equalsNullable(headHash, blockHeader.hash)) { - accounts.push(remainingAccount) - this.logger.debug(`Adding ${remainingAccount.displayName} to scan`) - } else { - newRemainingAccounts.push(remainingAccount) - } - } - - remainingAccounts = newRemainingAccounts + await this.connectBlock(blockHeader, scan) } if (this.chainProcessor.hash === null) { From ba4e45bb1e1c7c357bef67ed32cb194f2ac91757 Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Mon, 9 Jan 2023 12:29:30 -0500 Subject: [PATCH 55/56] Bump p2p protocol version to 19 (#2856) --- ironfish/src/network/version.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ironfish/src/network/version.ts b/ironfish/src/network/version.ts index 4b429356f4..d3e624bda5 100644 --- a/ironfish/src/network/version.ts +++ b/ironfish/src/network/version.ts @@ -2,8 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -export const VERSION_PROTOCOL = 18 -export const VERSION_PROTOCOL_MIN = 18 +export const VERSION_PROTOCOL = 19 +export const VERSION_PROTOCOL_MIN = 19 export const MAX_REQUESTED_BLOCKS = 50 export const MAX_MESSAGE_SIZE = 256 * 1024 * 1024 From 07265945081d15987383449e5cd21d641e07520a Mon Sep 17 00:00:00 2001 From: Jason Spafford Date: Mon, 9 Jan 2023 11:57:04 -0500 Subject: [PATCH 56/56] Bump versions (#2855) --- ironfish-cli/package.json | 6 +++--- ironfish-rust-nodejs/npm/darwin-arm64/package.json | 2 +- ironfish-rust-nodejs/npm/darwin-x64/package.json | 2 +- ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json | 2 +- ironfish-rust-nodejs/npm/linux-arm64-musl/package.json | 2 +- ironfish-rust-nodejs/npm/linux-x64-gnu/package.json | 2 +- ironfish-rust-nodejs/npm/linux-x64-musl/package.json | 2 +- ironfish-rust-nodejs/npm/win32-x64-msvc/package.json | 2 +- ironfish-rust-nodejs/package.json | 2 +- ironfish/package.json | 4 ++-- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ironfish-cli/package.json b/ironfish-cli/package.json index dcb536282a..409560cd4c 100644 --- a/ironfish-cli/package.json +++ b/ironfish-cli/package.json @@ -1,6 +1,6 @@ { "name": "ironfish", - "version": "0.1.55", + "version": "0.1.56", "description": "CLI for running and interacting with an Iron Fish node", "author": "Iron Fish (https://ironfish.network)", "main": "build/src/index.js", @@ -57,8 +57,8 @@ "dependencies": { "@aws-sdk/client-cognito-identity": "3.215.0", "@aws-sdk/client-s3": "3.127.0", - "@ironfish/rust-nodejs": "0.1.18", - "@ironfish/sdk": "0.0.32", + "@ironfish/rust-nodejs": "0.1.19", + "@ironfish/sdk": "0.0.33", "@oclif/core": "1.23.1", "@oclif/plugin-help": "5.1.12", "@oclif/plugin-not-found": "2.3.1", diff --git a/ironfish-rust-nodejs/npm/darwin-arm64/package.json b/ironfish-rust-nodejs/npm/darwin-arm64/package.json index dd1dca6fbd..1671258688 100644 --- a/ironfish-rust-nodejs/npm/darwin-arm64/package.json +++ b/ironfish-rust-nodejs/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-darwin-arm64", - "version": "0.1.18", + "version": "0.1.19", "os": [ "darwin" ], diff --git a/ironfish-rust-nodejs/npm/darwin-x64/package.json b/ironfish-rust-nodejs/npm/darwin-x64/package.json index 63c7872e80..a330d478fe 100644 --- a/ironfish-rust-nodejs/npm/darwin-x64/package.json +++ b/ironfish-rust-nodejs/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-darwin-x64", - "version": "0.1.18", + "version": "0.1.19", "os": [ "darwin" ], diff --git a/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json b/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json index 20c79fad11..ce8a9a80dd 100644 --- a/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json +++ b/ironfish-rust-nodejs/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-linux-arm64-gnu", - "version": "0.1.18", + "version": "0.1.19", "os": [ "linux" ], diff --git a/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json b/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json index d7ed74ae8a..aad64ba18e 100644 --- a/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json +++ b/ironfish-rust-nodejs/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-linux-arm64-musl", - "version": "0.1.18", + "version": "0.1.19", "os": [ "linux" ], diff --git a/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json b/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json index 16725e2d51..a3dbc211fa 100644 --- a/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json +++ b/ironfish-rust-nodejs/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-linux-x64-gnu", - "version": "0.1.18", + "version": "0.1.19", "os": [ "linux" ], diff --git a/ironfish-rust-nodejs/npm/linux-x64-musl/package.json b/ironfish-rust-nodejs/npm/linux-x64-musl/package.json index 514c3fc79a..1108860cac 100644 --- a/ironfish-rust-nodejs/npm/linux-x64-musl/package.json +++ b/ironfish-rust-nodejs/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-linux-x64-musl", - "version": "0.1.18", + "version": "0.1.19", "os": [ "linux" ], diff --git a/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json b/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json index 8a6e998a9a..636ad4bdcd 100644 --- a/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json +++ b/ironfish-rust-nodejs/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs-win32-x64-msvc", - "version": "0.1.18", + "version": "0.1.19", "os": [ "win32" ], diff --git a/ironfish-rust-nodejs/package.json b/ironfish-rust-nodejs/package.json index f7910e3675..6cfa8f8c6e 100644 --- a/ironfish-rust-nodejs/package.json +++ b/ironfish-rust-nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/rust-nodejs", - "version": "0.1.18", + "version": "0.1.19", "description": "Node.js bindings for Rust code required by the Iron Fish SDK", "main": "index.js", "types": "index.d.ts", diff --git a/ironfish/package.json b/ironfish/package.json index 64eccd5660..7a31c1bf94 100644 --- a/ironfish/package.json +++ b/ironfish/package.json @@ -1,6 +1,6 @@ { "name": "@ironfish/sdk", - "version": "0.0.32", + "version": "0.0.33", "description": "SDK for running and interacting with an Iron Fish node", "author": "Iron Fish (https://ironfish.network)", "main": "build/src/index.js", @@ -18,7 +18,7 @@ ], "dependencies": { "@ethersproject/bignumber": "5.7.0", - "@ironfish/rust-nodejs": "0.1.18", + "@ironfish/rust-nodejs": "0.1.19", "@napi-rs/blake-hash": "1.3.1", "axios": "0.21.4", "blru": "0.1.6",