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/.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 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/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..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", @@ -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", @@ -57,9 +57,9 @@ "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", - "@oclif/core": "1.16.1", + "@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", "@types/tar": "6.1.1", diff --git a/ironfish-cli/src/commands/chain/asset.ts b/ironfish-cli/src/commands/chain/asset.ts new file mode 100644 index 0000000000..cb947bfb29 --- /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.id) + const assetId = args.id + + const client = await this.sdk.connectRpc() + 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.id}`) + this.log(`Transaction Created: ${data.content.createdTransactionHash}`) + } +} 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/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/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/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-cli/src/commands/service/faucet.ts b/ironfish-cli/src/commands/service/faucet.ts index 374ce5c13c..171a8a074c 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}`, + assetId: Asset.nativeId().toString('hex'), } }) diff --git a/ironfish-cli/src/commands/service/sync-masp-transactions.ts b/ironfish-cli/src/commands/service/sync-multi-asset.ts similarity index 76% rename from ironfish-cli/src/commands/service/sync-masp-transactions.ts rename to ironfish-cli/src/commands/service/sync-multi-asset.ts index 13db644433..2bedd92697 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,11 +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 { - static aliases = ['service:syncMaspTransactions'] +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, @@ -54,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() @@ -105,14 +106,13 @@ export default class SyncMaspTransactions extends IronfishCommand { incomingViewKey: viewKey, head: head, }) - const speed = new Meter() speed.start() 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) } @@ -157,7 +157,11 @@ 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[] = [ + 'MULTI_ASSET_TRANSFER', + 'MULTI_ASSET_BURN', + 'MULTI_ASSET_TRANSFER', + ] const choice = choices[Math.floor(Math.random() * choices.length)] const connectedblockHash = uuid() await api.uploadMaspTransactions([ @@ -172,8 +176,7 @@ export default class SyncMaspTransactions extends IronfishCommand { transactions: [ { hash: uuid(), - type: choice, - assetName: 'jowparks', + multiAssets: [{ type: choice, assetName: 'jowparks' }], }, ], }, @@ -199,14 +202,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-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/ironfish-cli/src/commands/accounts/address.ts b/ironfish-cli/src/commands/wallet/address.ts similarity index 96% rename from ironfish-cli/src/commands/accounts/address.ts rename to ironfish-cli/src/commands/wallet/address.ts index b009546f1f..964148f9e9 100644 --- a/ironfish-cli/src/commands/accounts/address.ts +++ b/ironfish-cli/src/commands/wallet/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/balance.ts b/ironfish-cli/src/commands/wallet/balance.ts similarity index 73% rename from ironfish-cli/src/commands/accounts/balance.ts rename to ironfish-cli/src/commands/wallet/balance.ts index 9e7d295ba2..b0634f24b3 100644 --- a/ironfish-cli/src/commands/accounts/balance.ts +++ b/ironfish-cli/src/commands/wallet/balance.ts @@ -27,6 +27,10 @@ export class BalanceCommand extends IronfishCommand { required: false, description: 'Minimum number of blocks confirmations for a note', }), + assetId: Flags.string({ + required: false, + description: 'Asset identifier to check the balance for', + }), } static args = [ @@ -46,44 +50,57 @@ export class BalanceCommand extends IronfishCommand { const response = await client.getAccountBalance({ account, + assetId: flags.assetId, minimumBlockConfirmations: flags.confirmations, }) + const assetId = response.content.assetId if (flags.explain) { - this.explainBalance(response.content) + this.explainBalance(response.content, assetId) 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(`Head Hash: ${response.content.blockHash || 'NULL'}`) + this.log(`Head Sequence: ${response.content.sequence || 'NULL'}`) + this.log( + `Balance: ${CurrencyUtils.renderIron(response.content.confirmed, true, assetId)}`, + ) + this.log( + `Unconfirmed: ${CurrencyUtils.renderIron(response.content.unconfirmed, true, assetId)}`, + ) 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, assetId)}`) } - explainBalance(response: GetBalanceResponse): void { + explainBalance(response: GetBalanceResponse, assetId: string): void { const unconfirmed = CurrencyUtils.decode(response.unconfirmed) const confirmed = CurrencyUtils.decode(response.confirmed) 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`) - this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true)}`) + this.log(`Balance: ${CurrencyUtils.renderIron(confirmed, true, assetId)}`) 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, assetId)}`) } } diff --git a/ironfish-cli/src/commands/wallet/burn.ts b/ironfish-cli/src/commands/wallet/burn.ts new file mode 100644 index 0000000000..8252721653 --- /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 "assetId" -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, + }), + assetId: 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, + assetId: flags.assetId, + fee: flags.fee, + value: flags.amount, + }) + + stopProgressBar() + + const response = result.content + this.log(` + Burned asset ${response.assetId} 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) + } + } +} diff --git a/ironfish-cli/src/commands/accounts/create.ts b/ironfish-cli/src/commands/wallet/create.ts similarity index 93% rename from ironfish-cli/src/commands/accounts/create.ts rename to ironfish-cli/src/commands/wallet/create.ts index cf8791b058..1de79637ac 100644 --- a/ironfish-cli/src/commands/accounts/create.ts +++ b/ironfish-cli/src/commands/wallet/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/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 84% rename from ironfish-cli/src/commands/accounts/import.ts rename to ironfish-cli/src/commands/wallet/import.ts index 5a24c3042b..c1c8e8e4ef 100644 --- a/ironfish-cli/src/commands/accounts/import.ts +++ b/ironfish-cli/src/commands/wallet/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/index.ts b/ironfish-cli/src/commands/wallet/index.ts similarity index 96% rename from ironfish-cli/src/commands/accounts/index.ts rename to ironfish-cli/src/commands/wallet/index.ts index fc6a86f2f6..c32c2e1397 100644 --- a/ironfish-cli/src/commands/accounts/index.ts +++ b/ironfish-cli/src/commands/wallet/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/wallet/mint.ts b/ironfish-cli/src/commands/wallet/mint.ts new file mode 100644 index 0000000000..7568c1884f --- /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.assetId} + 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) + } + } +} diff --git a/ironfish-cli/src/commands/accounts/notes.ts b/ironfish-cli/src/commands/wallet/notes.ts similarity index 87% rename from ironfish-cli/src/commands/accounts/notes.ts rename to ironfish-cli/src/commands/wallet/notes.ts index c822183705..94ada67c89 100644 --- a/ironfish-cli/src/commands/accounts/notes.ts +++ b/ironfish-cli/src/commands/wallet/notes.ts @@ -36,9 +36,15 @@ export class NotesCommand extends IronfishCommand { CliUx.ux.table( [note], { - amount: { - header: 'Amount ($IRON)', - get: (row) => CurrencyUtils.renderIron(row.amount), + value: { + header: 'Amount', + get: (row) => CurrencyUtils.renderIron(row.value), + }, + assetName: { + header: 'Asset Name', + }, + assetId: { + header: 'Asset Id', }, memo: { header: 'Memo', diff --git a/ironfish-cli/src/commands/accounts/remove.ts b/ironfish-cli/src/commands/wallet/remove.ts similarity index 93% rename from ironfish-cli/src/commands/accounts/remove.ts rename to ironfish-cli/src/commands/wallet/remove.ts index dd3e788592..37141f59c0 100644 --- a/ironfish-cli/src/commands/accounts/remove.ts +++ b/ironfish-cli/src/commands/wallet/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/accounts/repair.ts b/ironfish-cli/src/commands/wallet/repair.ts similarity index 79% rename from ironfish-cli/src/commands/accounts/repair.ts rename to ironfish-cli/src/commands/wallet/repair.ts index 90c951a088..dc8fa2c022 100644 --- a/ironfish-cli/src/commands/accounts/repair.ts +++ b/ironfish-cli/src/commands/wallet/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) @@ -81,16 +72,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) { @@ -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.expirationSequence(), - 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`, ) 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/pay.ts b/ironfish-cli/src/commands/wallet/send.ts similarity index 81% rename from ironfish-cli/src/commands/accounts/pay.ts rename to ironfish-cli/src/commands/wallet/send.ts index f2a184904b..3a1070766d 100644 --- a/ironfish-cli/src/commands/accounts/pay.ts +++ b/ironfish-cli/src/commands/wallet/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 = { @@ -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.', @@ -53,15 +53,19 @@ export class Pay extends IronfishCommand { description: 'The priority level for transaction fee estimation.', options: ['low', 'medium', 'high'], }), + assetId: Flags.string({ + char: 'i', + 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() 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) @@ -78,17 +82,17 @@ export class Pay extends IronfishCommand { amount = CurrencyUtils.decodeIron(flags.amount) } + const assetId = flags.assetId + if (amount === null) { - const response = await client.getAccountBalance({ account: from }) + const response = await client.getAccountBalance({ account: from, assetId }) - const input = (await CliUx.ux.prompt( - `Enter the amount in $IRON (balance: ${CurrencyUtils.renderIron( - response.content.confirmed, - )})`, + const input = await CliUx.ux.prompt( + `Enter the amount (balance: ${CurrencyUtils.renderIron(response.content.confirmed)})`, { required: true, }, - )) as string + ) amount = CurrencyUtils.decodeIron(input) } @@ -112,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`) @@ -154,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})`, @@ -162,7 +166,7 @@ export class Pay extends IronfishCommand { required: true, default: suggestedFee, }, - )) as string + ) fee = CurrencyUtils.decodeIron(input) } @@ -171,7 +175,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) } @@ -179,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, + assetId, +)} plus a transaction fee of ${CurrencyUtils.renderIron( fee, true, )} to ${to} from the account ${from} @@ -226,11 +234,12 @@ ${CurrencyUtils.renderIron(amount, true)} plus a transaction fee of ${CurrencyUt { publicAddress: to, amount: CurrencyUtils.encode(amount), - memo: memo, + memo, + assetId, }, ], fee: CurrencyUtils.encode(fee), - expirationSequence, + expiration: expiration, }) stopProgressBar() @@ -238,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, assetId)} to ${recipients} from ${ transaction.fromAccountName } Transaction Hash: ${transaction.hash} diff --git a/ironfish-cli/src/commands/accounts/status.ts b/ironfish-cli/src/commands/wallet/status.ts similarity index 97% rename from ironfish-cli/src/commands/accounts/status.ts rename to ironfish-cli/src/commands/wallet/status.ts index 983fdd5cbd..bad820f963 100644 --- a/ironfish-cli/src/commands/accounts/status.ts +++ b/ironfish-cli/src/commands/wallet/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/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 85% rename from ironfish-cli/src/commands/accounts/transactions.ts rename to ironfish-cli/src/commands/wallet/transactions.ts index 4e3d734441..db63793588 100644 --- a/ironfish-cli/src/commands/accounts/transactions.ts +++ b/ironfish-cli/src/commands/wallet/transactions.ts @@ -47,9 +47,13 @@ export class TransactionsCommand extends IronfishCommand { CliUx.ux.table( [transaction], { + timestamp: { + header: 'Timestamp', + get: (transaction) => new Date(transaction.timestamp).toLocaleString(), + }, status: { header: 'Status', - minWidth: 11, + minWidth: 12, }, creator: { header: 'Creator', @@ -75,8 +79,16 @@ export class TransactionsCommand extends IronfishCommand { header: 'Spends', minWidth: 5, }, - expirationSequence: { - header: 'Expiration Sequence', + mintsCount: { + header: 'Mints', + minWidth: 5, + }, + burnsCount: { + header: 'Burns', + minWidth: 5, + }, + expiration: { + header: 'Expiration', }, }, { 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 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.d.ts b/ironfish-rust-nodejs/index.d.ts index e0bb7f1589..15877f5a49 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 @@ -18,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 @@ -70,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 } @@ -93,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. */ @@ -106,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 */ @@ -132,7 +126,7 @@ export class TransactionPosted { fee(): bigint transactionSignature(): Buffer hash(): Buffer - expirationSequence(): number + expiration(): number } export type NativeTransaction = Transaction export class Transaction { @@ -146,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 @@ -168,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/index.js b/ironfish-rust-nodejs/index.js index 1228b0a7e3..c87871cab3 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 } @@ -101,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')) @@ -236,7 +246,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 @@ -245,7 +255,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/npm/darwin-arm64/package.json b/ironfish-rust-nodejs/npm/darwin-arm64/package.json index 463a3e5b3d..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" ], @@ -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..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" ], @@ -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..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" ], @@ -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..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" ], @@ -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..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" ], @@ -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..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" ], @@ -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..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" ], @@ -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..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", @@ -30,10 +30,10 @@ } }, "engines": { - "node": ">= 16" + "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/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 387fb82641..ba53b23371 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() } } @@ -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,21 +200,24 @@ 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. #[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); + self.transaction + .add_burn(asset_id, value_u64) + .map_err(to_napi_err)?; Ok(()) } @@ -260,9 +271,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..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,16 +78,16 @@ 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()) 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()) + 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) => { @@ -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/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 5779662767..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}, @@ -96,7 +95,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 +119,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()), } @@ -133,33 +132,44 @@ 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_id(), 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_id(), 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.id(), value as i64)?; self.mints.push(MintBuilder::new(asset, value)); + + Ok(()) } - pub fn add_burn(&mut self, asset_identifier: AssetIdentifier, value: u64) { - 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_id, value)); - self.burns.push(BurnBuilder::new(asset_identifier, value)); + Ok(()) } /// Post the transaction. This performs a bit of validation, and signs @@ -179,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, @@ -197,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(), ); @@ -206,7 +216,7 @@ impl ProposedTransaction { } for change_note in change_notes { - self.add_output(change_note); + self.add_output(change_note)?; } self._partial_post() @@ -234,13 +244,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 +328,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 +358,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 +494,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 +516,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 +549,7 @@ impl Transaction { mints, burns, binding_signature, - expiration_sequence, + expiration, randomized_public_key, }) } @@ -555,7 +563,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 +632,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 +651,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()) @@ -731,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 e6a6dd630e..12c42c1ff6 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.id, burn_value).unwrap(); assert_eq!(transaction.burns.len(), 1); let public_transaction = transaction @@ -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 @@ -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,11 +234,11 @@ 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_sequence(1337); + transaction.set_expiration(1337); let public_transaction = transaction .post(None, 0) @@ -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..ede3361e9f 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,30 @@ impl ValueBalances { ValueBalances { values: hash_map } } - pub fn add(&mut self, asset_identifier: &AssetIdentifier, value: i64) { - let current_value = self.values.entry(*asset_identifier).or_insert(0); - *current_value += value + 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)?; + + *current_value = new_value; + + Ok(()) } - pub fn subtract(&mut self, asset_identifier: &AssetIdentifier, value: i64) { - let current_value = self.values.entry(*asset_identifier).or_insert(0); - *current_value -= value + pub fn subtract( + &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_sub(value) + .ok_or(IronfishError::InvalidBalance)?; + + *current_value = new_value; + + Ok(()) } pub fn iter(&self) -> hash_map::Iter { @@ -57,8 +76,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 +86,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()); } } 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/package.json b/ironfish/package.json index 07030c4837..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", @@ -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/blockchain/__fixtures__/blockchain.test.ts.fixture b/ironfish/src/blockchain/__fixtures__/blockchain.test.ts.fixture index aed0464a78..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: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" + "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: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" } ] } ], "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:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAcKGSm/E2i1I20HNm3Z3npC+npVMStH1qHe/SlaLDb4OTNe7MbnQlbu6MhRI+jRGuHGjLg3XNqhmL3Kw8WdyjrQpNuqhptESLuV+9RdUz3kOG8bQC/Y2T4lNwgDnuFaxYTClhltfaz9FHa+NLJ2cfXDvI2Bz3uxMvPjEf9iuzu54U/dU6DG8+E6y/cadhZfq0Xb3Iqzsu7rFV170Oqx7cNuWy0aR/kVvgo2dp8UUzSgGuh4jVlU9eiisPXNV1JZOv2vtkjMX5rfy55fSa5+ekzW0W/LYs2goZiZgqdkTsdX3P6o+VKhhlJAUTDmIgp5F+TeBzg8uCvGa55msEeG3IEaIORzZJmQHNtEWac/W2pI6Pg2WuEkHCObfJ6Lv+7J9WBgAAAKdSF6bkqCmYQ6g+LgKrglWyUip1bNMNZWvNYQGrVS1txidabZikg8g92M8aYetmK+xcKQSzg8qHMi+dPhPA8E22ahhcIxA5PQLNO21B4wkHe43YDIzkrKVuuilHWGsnBoxkBJwiHmSEP1cSis5zChcH950jrrWr3E3YVyn7dJBqIdigJYIIt48p0lCgSP1mYJIu+1zfCIwSVyD2grYO/xSmOoRSwGf+EsK4TUQfqRNPkBB/bIaABs3IaFB60DPcixIXtbxPzkeVELuGSGfhRu84b30e9/OI3lU8wscVZeAz0ndBX0G9HRalk8PHKVCxJqEt8a2tBRCG6nxkKscg1d5SFtbw26EIDa5TaOPxjY9Q4UInR1gcTxR8LX8EkJ29v8ymAmVJqW2jIMXSc2nTTFCNmGofz2YYeFJ5nAg5sRNJKDhUZlP8fZqVx7Sn8+j/a0RUbdwBTDRmlwyEPXrON2VvVgg1rU1K/iRUsHGsa9Sfrm6Cu3PW1EHzRQaLXKYFUkyfQp3XfFSgH8KqCOnSyE4rxK2mE7rk9bqc/50wZDKPyCaP9WM4oOXMIfrHzDxQzQ4pikSgHM5oJMATAWtrWj5EVzIqFXJsRvLxbriDdzW/rPjnf3Vd1bNlmcWLdo6S51rnEWjep5Jp5oNy/ywyZYtBRzj6GCvMuI4eehfQNLoQbeyIoiJT1Pe4cqwOUExwxlvZv+UJjMHfE9CImMlIt/7zTlqshgdf7g17n/q9YmPSyOUkpJBdVIbAJeqdCyzicl5/tUSp1SpszbOt5rRmqmU514tGOoI0sz/B++bkPaYb9DfwfUznC6eKOu9M4TWn9LITrlusXimo2D9+pHoyonKPGUZ/+S0p0TCXj/TCP/zE8VY8FxvrMyyUI0X+nRz2vmQDwVF+XJVO5ol8q3GDVhyqga7DjREWwFh5ZBiFmOwRtnnT5LEOFEsQY/4k+dw8wgSpiI5dv53kAo52dtXRxTC+SwFnejtFqUvdaQVDCaN65miMHDyqzG6ix3np5mDHLQtVdToGoGFS7Vk7rj/BdUkeTBVS9elY5uiohIGqJ+u4pPaTQATru0TJSJFPegBScxsjXHBPKcmvl6ZwrlO7NybAI7qBjS2rw/umiXFqfOnkK0tO2bzeETp2q0lHHf+H89eU+6qwAdMAk6pY8JWTFcwjK3jg11NcrDihB02Z96c4WbWb1qx0Bd4aBy712qCF6a1b3XaJzgkbcagzi/jO579QXLUO5U+n3AQUr+2kRdoF5OgybzEFTMMUf6aeKh6XupUY7xaboYVzKxc70iJ2GUC4K6+CdC3HBY2B1Er63VPIQnUIafA+xdUpFGlTHcw7mj5pplMC8agFFvsdx0GmdJGDxLgki/J6ZinXfBRhOkyk6wcUarfqtWd19d8taurlK5l3SCGhZJKJmM6huX5gku6cPhM5zm8iEdR5p5zUIpVt/55EklpA20kE1n0GfXllqyuTRIGCYlkfqjC5ZVgdJ+cC2wPPcdyQOmmndG4VAARp3b6wBUw8khaJrdMiCGrtokxLIHVoqX5r2xUzr97HGdcbqtBti0AH6fMPtqOhCw62Rs6fZCyFHKVQuwYryZObCQ==" + "data": "base64:AQEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAADQwqs7y7f6pvXb13N8YPR7JZ3rZ7SKj0DH3K0OQHQlipYOVlGQMKvfr/SVPMIldlSDOuNRr+dMdir6jK3g8kCIuxgT5j3UUNpp7ZOF6gadmh9uNUJACZXTVU8wV+3CCVO8dl5hkNXsh3FE6YH4AzAYhLTSLEYCfNRvai3PMOuLIGFD2b4FiKHVXap5XW8srwH9Djb+cPSOAZRODpMkH3AR3iyVSVsMlzDA2rP6qkPTqFQHa+QfgctOG/ykxn7guzSMnDmBP/OjCdrWBZyf1ThI4pVY9iYBlHf9n+99TEOkFC/7NJQTeg2dm6zFIGux6wa/pY928WfFhr4gdXLb60tECRXkkuthtTc4PjL36j/FIc6V3wWOLMQxKSgGhPfPMxBgAAAKiF+MQ7SYr2ud0Q23ZH6W2E9e3IYFlZQaqKaeeu2JclwQUyItnBNkrdDaCch//Ccajc/J5SNS3nyizV68EpcEsw7EfWouUcnyQTgvjpiUWU9boMDXkX92c90OZ1V0+tAIrnwGdWORf9LL8sufUMvdSnqrwxjjruh+yCcDrTTCCCHak/1tXT1aC0jDcz/0nmCIfomI1w6nwdaLD9K1davRps/u10+kJ88Cj67bxP+Ea7GwBbLH7URtFEJCcvoDDprA7OUZL9VNBbn5Ln5jzDpsvU0zG128POBaCUeAbDOMNtaGx7kKppubbHz/ozAN/XEq869fNYAzxPi7NqktvZBosNCLqPADfHOgvmfbxtC9HvZ2uwwa/OwUlozmWcY3cNDhTaekHDRhMWxajioOxE+jpAov9iK5odu3B8gZ+qGJbKxHWbTt4p+DyvBSAnvJJ/jXNt0zyRK9cf6eWhpsC/GVu3Mojx45QuY+zhED9ZW1NuNWYXQjvXAk8x89pVrQYi7LJrK087HG3ZNISf0MwTUxoKMPQNe7BeqROAXaAPKc+OIdMMqaxXVbSns/ltHurc/siFXyPg/hPH+OIXqJAMHdk8SRbQXU+gbpX3lN8ZgLTeJzCqdXkcVsfsZ2y2pA8RaFQgeeFas40t9YcmlZHIp5UARylAYDlpWknauYLvHbaetJIsnS6sJVP/y7OVfauaKoI9HGuDvAs8T0w2+RG/HR7u/dWoAI0HkNpA9cxpc59gX7Fxbzk8yHDL6MR04829W7r9eAndoAwC7i5IfHQFUL7HyTGF9cKWaXtl8fiIKbhXKC8yvHd+1aCtgxhvWylVW1vkn38yuGkDtuoSObSGRsJ+YBcezrzvITaFM/ASsQV6eHmJRMKu2ImD6rio1FB8mNf2tBC1biuM8YV088UV9yyir7tmkUKWyAuRYn/XPvE+YxrQkXVw+04KghVJk8R43lsIPLRQ+2AkuX/WWFZhu31XHLf//1SG2lmWblcDUbYQau9DgEKSiM65bDla3+MsPR3+mdiJPfvBJlOGhDcaPfXD7VRWtVRI9IfSxxNz9gdj28ihtz60RB6Y75BwgG1DECgVJ0o4tUUGvpQ3t/H0PG1WgaxuK6gBwRxiQaS1CtgIiinIZzfHX3fhbUG4KA6jBgIzLl2RdB0WtBIwwZBx9Pqx85/v8yecQDXCzhW/+3dOHJRRxs1yXIpOzxa2j9KDfuE+SgX5RnJJdpwgm9pvDpVMGRK80AWFQQIM4hKbNAWGrqg2jdfHCbTTjFw/FNilIfrlmqQwc5OvkjAYZxgCc1YLbUXELHaLdoI4PfQI5eZ7abdAhKPJ5N6seBSjF1HtGRsbleK9SF23u8lbb8rYYWNHDioKb3qzNKKJTJFTXpwHxxvQ6NyGT/0Jzaw/R//k7wY56JHd+4PbZwQ5XvmmEGHpXh+OiMASQqJYIbfYYaY3RUggO+cAcJHqdk+2Dhfxia6B1BvJ37fjnH/S7GB9fJNfo4xAMPKM8ttLYn83RbNjVto5/dv0XLNUZ+9p/OUSZEp7qggEYW726x7avl+12zqOU252Al3UDHZwXEaZKChCHQrE6pUWj5dyHHUaYWJeDA==" } ] } @@ -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: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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" } ] } @@ -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: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" }, { "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,19 +2064,19 @@ "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==" } ] } ], - "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 +2084,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 +2100,251 @@ "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: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" } ] + } + ], + "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////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: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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" + } + ] + } + ], + "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////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////8AAAAA5G7tXY+MWZCpZ+4xh1xucculOqILsIrgGaq79jQL3POhR0QqvsMnokCnewDEa7oECYlVnrirczD6ayFKccyuRpD287E3mFLl3hOILRWeYiSWs95gH3YyfkwHjVKEWTUrggaD5HamOTCiQu8DX4k+pYPIDU2u+dAql4xoUWufppcZwfe58dxpPZ5iffARWRCJaujWjHtJsrLPP4C3ia8lSUo2wzHrRrD9UHrgFRNKO7Gv+oiprxtB1+PT2o1uk3SffJBgJ4dxvFHp3tVwtRtLg5mtghJvuvivqgtMdyf6cTkGg4bjx9E7xC6soOJ3nhYwOR8OgAVNdRmwZJ45Rt8HbxKZLC7pFde5763OgEISELJiyxMMliB+aOFd8qH0QVBFgmP4m8feqDsls2hIUHIryuzfFrzyyxtX8QOWHsZcE6wEJez1sTq/6NSPFGBA9CEFUl2FbY9/98zGn27ANK2notfNoyKcav/NSe9aZRFM7PgElnAPxEsxLIVCEC4KyId3qRUwMmpyGPoLSA8c8juHjOruxIVSVLG+z6KmRBJ/PwInJsHWCpUxgD7AHhduBSyK99PRxYxcvWSEd3RrQyaAAGdzucQzZtqqsc7Pu8xn7DhZXMvqze9MsElyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwjuitSvZqHL0tjJnClkDIKi6OlfUjraqigFgFumH5XjIkjfHiTb10bCeTkCZXEAmmSqZEXCKUlzQIy8+4RAr1CQ==" }, { "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: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: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" + "data": "base64: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" } ] } 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 c3492b5d6c..8eef69a505 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, @@ -16,10 +17,11 @@ import { useBlockWithTx, useMinerBlockFixture, useMinersTxFixture, + useMintBlockFixture, + usePostTxFixture, useTxFixture, } from '../testUtilities' import { makeBlockAfter } from '../testUtilities/helpers/blockchain' -import { buildRawTransaction } from '../testUtilities/helpers/transaction' import { AsyncUtils } from '../utils' import { Account } from '../wallet' @@ -843,25 +845,6 @@ describe('Blockchain', () => { }) describe('asset updates', () => { - async function mintAsset( - node: IronfishNode, - account: Account, - sequence: number, - asset: Asset, - value: bigint, - ): Promise { - return useBlockWithRawTxFixture( - node.chain, - node.workerPool, - account, - [], - [], - [{ asset, value }], - [], - sequence, - ) - } - async function burnAsset( node: IronfishNode, account: Account, @@ -877,7 +860,7 @@ describe('Blockchain', () => { [noteToBurn], [], [], - [{ assetIdentifier: asset.identifier(), value }], + [{ assetId: asset.id(), value }], sequence, ) } @@ -885,28 +868,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) + const mint = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + mints: [{ asset, value: 10n }], + }) + + const block = await useMinerBlockFixture(node.chain, 2, undefined, undefined, [mint]) await expect(node.chain).toAddBlock(block) - const transactions = block.transactions - expect(transactions).toHaveLength(2) - const mintTransaction = transactions[1] + const mintedAsset = await node.chain.assets.get(asset.id()) - const mintedAsset = await node.chain.assets.get(asset.identifier()) expect(mintedAsset).toEqual({ - createdTransactionHash: mintTransaction.hash(), - identifier: asset.identifier(), + createdTransactionHash: mint.hash(), + id: asset.id(), metadata: asset.metadata(), name: asset.name(), nonce: asset.nonce(), owner: asset.owner(), - supply: value, + supply: 10n, }) }) }) @@ -921,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] @@ -932,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, @@ -949,18 +941,30 @@ 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()) + 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(), @@ -979,12 +983,18 @@ 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) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toBeUndefined() }) }) @@ -998,16 +1008,28 @@ 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) - const mintedAsset = await node.chain.assets.get(asset.identifier()) + const mintedAsset = await node.chain.assets.get(asset.id()) expect(mintedAsset).toMatchObject({ supply: mintValueA, }) @@ -1023,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) @@ -1033,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, }) @@ -1047,10 +1075,16 @@ 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 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 @@ -1059,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) @@ -1077,20 +1111,26 @@ 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 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) + 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), }) @@ -1109,14 +1149,20 @@ 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) - 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) + let record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1125,10 +1171,16 @@ 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) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1141,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(), @@ -1151,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(), @@ -1164,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(), @@ -1173,10 +1225,16 @@ 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) + record = await node.chain.assets.get(assetId) Assert.isNotUndefined(record) expect(record).toMatchObject({ createdTransactionHash: blockA.transactions[1].hash(), @@ -1186,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(), @@ -1204,15 +1262,21 @@ 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 - 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 - 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(), @@ -1225,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 @@ -1234,66 +1298,64 @@ 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() }) }) 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 minedBlock = await useMinerBlockFixture(node.chain, 2, account) - await expect(node.chain).toAddBlock(minedBlock) + const account = await useAccountFixture(node.wallet) - // 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 = [{ assetId: Asset.nativeId(), 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.nativeId(), + 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, }) diff --git a/ironfish/src/blockchain/blockchain.ts b/ironfish/src/blockchain/blockchain.ts index 5e4910a67e..52a9ecf746 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' @@ -701,6 +702,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 +763,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) { @@ -1177,6 +1187,7 @@ export class Blockchain { sequence: number blockHash: Buffer previousBlockHash: Buffer + timestamp: Date }, void, unknown @@ -1202,6 +1213,7 @@ export class Blockchain { blockHash: header.hash, sequence: header.sequence, previousBlockHash: header.previousBlockHash, + timestamp: header.timestamp, } } } @@ -1309,7 +1321,6 @@ export class Blockchain { } if (!this.hasGenesisBlock || isBlockLater(block.header, this.latest)) { - this.latest = block.header await this.meta.put('latest', hash, tx) } } @@ -1319,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) @@ -1330,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(), @@ -1349,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 @@ -1358,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, @@ -1377,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, @@ -1405,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 @@ -1419,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(), @@ -1454,6 +1465,23 @@ export class Blockchain { this.synced = true this.onSynced.emit() } + + async getAssetById(assetId: Buffer): Promise { + if (Asset.nativeId().equals(assetId)) { + return { + createdTransactionHash: GENESIS_BLOCK_PREVIOUS, + id: Asset.nativeId(), + 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, + } + } + + const asset = await this.assets.get(assetId) + return asset || null + } } export class VerifyError extends Error { 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/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/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/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/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/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/poolShares.ts b/ironfish/src/mining/poolShares.ts index b2399f4f87..bb079e12cc 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()}`, + assetId: Asset.nativeId().toString('hex'), } }, ) 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/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 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/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 4668f45c3f..eaf464a740 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' @@ -32,10 +29,10 @@ 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.nativeId()) const burn = { - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), value: 2n, } @@ -44,7 +41,7 @@ describe('RawTransaction', () => { value: 1n, } - const raw = await useRawTxFixture({ + const raw = await createRawTransaction({ wallet: nodeTest.wallet, from: account, to: account, @@ -58,7 +55,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) @@ -70,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(balance - raw.fee - mint.value - 1n) + 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) }) @@ -94,7 +91,7 @@ describe('RawTransaction', () => { generateKey().public_address, 5n, 'memo', - asset.identifier(), + asset.id(), account.publicAddress, ).serialize(), ) @@ -112,7 +109,7 @@ describe('RawTransaction', () => { const raw = new RawTransaction() raw.spendingKey = account.spendingKey - raw.expirationSequence = 60 + raw.expiration = 60 raw.fee = 1337n raw.mints = [ @@ -124,7 +121,7 @@ describe('RawTransaction', () => { raw.burns = [ { - assetIdentifier: asset.identifier(), + assetId: asset.id(), value: 5n, }, ] @@ -142,13 +139,13 @@ describe('RawTransaction', () => { expect(deserialized).toMatchObject({ spendingKey: raw.spendingKey, - expirationSequence: raw.expirationSequence, + expiration: raw.expiration, fee: raw.fee, }) 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 0ed587d621..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' @@ -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[] = [] @@ -53,11 +53,11 @@ export class RawTransaction { } for (const burn of this.burns) { - builder.burn(burn.assetIdentifier, burn.value) + builder.burn(burn.assetId, burn.value) } - if (this.expirationSequence !== null) { - builder.setExpirationSequence(this.expirationSequence) + if (this.expiration !== null) { + builder.setExpiration(this.expiration) } const serialized = builder.post(null, this.fee) @@ -107,13 +107,13 @@ 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) } - 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() @@ -160,14 +160,14 @@ 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() if (hasExpiration) { - raw.expirationSequence = reader.readU64() + raw.expiration = reader.readU64() } return raw @@ -205,13 +205,13 @@ 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 } 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/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/primitives/transaction.test.slow.ts b/ironfish/src/primitives/transaction.test.slow.ts index b5e03cbef1..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, @@ -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 917e7dc272..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, @@ -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) @@ -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) @@ -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/clients/client.ts b/ironfish/src/rpc/clients/client.ts index 47fb27edf8..b5f16afb70 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, @@ -60,6 +62,10 @@ import { UseAccountRequest, UseAccountResponse, } from '../routes' +import { + EstimateFeeRatesRequest, + EstimateFeeRatesResponse, +} from '../routes/chain/estimateFeeRates' import { ExportChainStreamRequest, ExportChainStreamResponse, @@ -69,19 +75,17 @@ 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, 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' +import { MintAssetRequest, MintAssetResponse } from '../routes/wallet/mintAsset' import { RemoveAccountRequest, RemoveAccountResponse } from '../routes/wallet/removeAccount' import { RescanAccountRequest, RescanAccountResponse } from '../routes/wallet/rescanAccount' @@ -327,11 +331,25 @@ export abstract class RpcClient { return this.request(`${ApiNamespace.event}/onGossip`, params) } + async mintAsset(params: MintAssetRequest): Promise> { + return this.request( + `${ApiNamespace.wallet}/mintAsset`, + params, + ).waitForEnd() + } + + async burnAsset(params: BurnAssetRequest): Promise> { + return this.request( + `${ApiNamespace.wallet}/burnAsset`, + params, + ).waitForEnd() + } + async sendTransaction( params: SendTransactionRequest, ): Promise> { return this.request( - `${ApiNamespace.transaction}/sendTransaction`, + `${ApiNamespace.wallet}/sendTransaction`, params, ).waitForEnd() } @@ -363,7 +381,7 @@ export abstract class RpcClient { params?: EstimateFeeRatesRequest, ): Promise> { return this.request( - `${ApiNamespace.fees}/estimateFeeRates`, + `${ApiNamespace.chain}/estimateFeeRates`, params, ).waitForEnd() } @@ -372,7 +390,7 @@ export abstract class RpcClient { params: EstimateFeeRequest, ): Promise> { return this.request( - `${ApiNamespace.fees}/estimateFee`, + `${ApiNamespace.chain}/estimateFee`, params, ).waitForEnd() } @@ -468,4 +486,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/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/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/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/getAsset.test.ts b/ironfish/src/rpc/routes/chain/getAsset.test.ts new file mode 100644 index 0000000000..f18f354b69 --- /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.nativeId()) + Assert.isNotNull(asset) + + const response = await routeTest.client.getAsset({ + id: asset.id.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) + 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..e0b5305b5b --- /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_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 = { + id: string +} + +export type GetAssetResponse = { + createdTransactionHash: string + id: string + metadata: string + name: string + nonce: number + owner: string + supply: string +} + +export const GetAssetRequestSchema: yup.ObjectSchema = yup + .object() + .shape({ + id: yup.string(), + }) + .defined() + +export const GetAssetResponse: yup.ObjectSchema = yup + .object({ + createdTransactionHash: yup.string().defined(), + id: 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 id = Buffer.from(request.data.id, 'hex') + + if (id.byteLength !== ASSET_ID_LENGTH) { + throw new ValidationError( + `Asset identifier is invalid length, expected ${ASSET_ID_LENGTH} but got ${id.byteLength}`, + ) + } + + const asset = await node.chain.getAssetById(id) + + if (!asset) { + throw new ValidationError(`No asset found with identifier ${request.data.id}`) + } + + request.end({ + createdTransactionHash: asset.createdTransactionHash.toString('hex'), + id: asset.id.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/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/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/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 3270bdc392..61829ff542 100644 --- a/ironfish/src/rpc/routes/chain/getTransactionStream.ts +++ b/ironfish/src/rpc/routes/chain/getTransactionStream.ts @@ -6,36 +6,73 @@ 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' 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() @@ -105,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: decryptedNote.value().toString(), + 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, }) } } @@ -149,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() diff --git a/ironfish/src/rpc/routes/chain/index.ts b/ironfish/src/rpc/routes/chain/index.ts index c9e62315de..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' @@ -11,3 +13,4 @@ export * from './getTransaction' export * from './getTransactionStream' export * from './showChain' export * from './getConsensusParameters' +export * from './getAsset' diff --git a/ironfish/src/rpc/routes/index.ts b/ironfish/src/rpc/routes/index.ts index 817f44388a..ad3d630a6f 100644 --- a/ironfish/src/rpc/routes/index.ts +++ b/ironfish/src/rpc/routes/index.ts @@ -10,7 +10,5 @@ export * from './peers' export * from './router' 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 bd1d2c2351..9db651a8b8 100644 --- a/ironfish/src/rpc/routes/router.ts +++ b/ironfish/src/rpc/routes/router.ts @@ -15,11 +15,9 @@ export enum ApiNamespace { config = 'config', event = 'event', faucet = 'faucet', - fees = 'fees', miner = 'miner', node = 'node', peer = 'peer', - transaction = 'transaction', wallet = 'wallet', worker = 'worker', rpc = 'rpc', diff --git a/ironfish/src/rpc/routes/transactions/__fixtures__/sendTransaction.test.ts.fixture b/ironfish/src/rpc/routes/transactions/__fixtures__/sendTransaction.test.ts.fixture deleted file mode 100644 index d3d6b55270..0000000000 --- a/ironfish/src/rpc/routes/transactions/__fixtures__/sendTransaction.test.ts.fixture +++ /dev/null @@ -1,54 +0,0 @@ -{ - "Transactions sendTransaction throws if pay throws NotEnoughFundsError": [ - { - "id": "8525a599-26ba-4454-8e7b-91029a58cd2a", - "name": "account-throw-error", - "spendingKey": "db85ee55b4ddcc5376293ea55cf4919d0a390fe80da7576cc50040d8a78b4440", - "incomingViewKey": "8174a4fc78e6f81af16faf34d6b36095db8f217da7329dad5188545c2f354f00", - "outgoingViewKey": "b4aa58f2b60dc91069d472281cd49cb66bc4269dd2bd89b352cd59684f346a0b", - "publicAddress": "efe5fd8edc8d7f8fa920e7f04632aea0af0b8c7e47c46326cf5e996be753af5c" - } - ], - "Transactions sendTransaction calls the pay method on the node with single recipient": [ - { - "id": "a0f87a49-d0f0-48d8-a8a0-365c5084bbfe", - "name": "account", - "spendingKey": "ff0ae50289562ba734314db1b7e3b2bc8dcf224c34bd6309e254bb0e3ac9e177", - "incomingViewKey": "0ceaff1dc8b9bb68b538dcd52e64ed50f522621f860c7a7acb41ce3883714403", - "outgoingViewKey": "c77155f8a3747abb39d5645f5e1caf07009b8e3aa71f5d92ace3dbbbc50fec8e", - "publicAddress": "25e6c0f63fc5c48c91933a456ff66a78b86b24568e9fad1fb40931adec94bb39" - }, - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAPkkvGKv19hDe6HebUAB7NFxn9927aH89XtEMi2/38yqofUJsS3/aTeBdG4fb5u5TMyjaiCTm57+b11bwl+4luNPT6NA++pGYuPAqx7tRcuaPMnPi0hI4WyTR19c03y4RqDpHC16v6cYvcecxpm4tJgDIrwynZOwfcWVosk8UZakCYd9WUNkvKraXLF1D9GpeicgH8a0Uz1Wvi7Jbr4O7nUATWNzbTiFG5GFK0Le7NP6L++GrB3MHjTTvv6PZx/EeaAFJo75kLFk0+Hs+QoNr00EdEMiClFt3WW2VNtf3utZRA1ajU+p0xvL4tfHxVFrspq1CV+PahZaPKhQhQX0+llYdP8b65MzOVXsDAgx5jPALR+8XDx2IUegt/q9PdSgMUHZPztg4X8kuXW6N0QdSRjEowkyBQiG5RruYanJBRsnBD4UnuvEfD17oUHGQuDDA7uLrmL/A+i9eXZfMp9MFq5mNTI8IBnfV5jkbI0XSM6RtQBgoL3EhdtzAzNl+jp0n6yVBIsHJQZWsK8GjfTVwcrDsOyHFb9ZgrsUguJs+GRpd0FhZEHSJUp6pwpE1vWrzRw4lVkOA7G1Fif/K7eq+eCyg3jM4KS/jMjszntJvCqdYK25EseafR0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLdoimwcIAyRx1eqXoazZlxOGF+G/4l1ExCXUhfiUwY7yNJyNi0q6fAqDVuauhFNZG4qriRNuC7PFOXVc2IslDA==" - } - ], - "Transactions sendTransaction calls the pay method on the node with multiple recipient": [ - { - "id": "9216cd8b-5e7d-49a2-af8c-b5f077271104", - "name": "account_multi-output", - "spendingKey": "16302d3d33c94b92fd4f13d673a751632bfb82981c10dcc27236458b533de252", - "incomingViewKey": "78de699372af00a58f6919875e76b166d6b0e7ed1f26ca62061498916eeeae05", - "outgoingViewKey": "9977ec0e39d04a7e2611d8fc17d1cc531f4b70ca3611e8fbbcbf76a6f59401e7", - "publicAddress": "88bdc4d984700d7afc817753cea5bb4e5eaa06d4edf2dce383dfc34b0aa2a9a5" - }, - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1sVq6C/BUO3H1exNtsYrHD9uMzgyLC/HzRMOSj+wsNKvErjVNYd1neFOwQUc5L4q8XQLCzk0kpzC0DrTTa1W7+6E6aeQPHkcrEyvSN/Vb2SoqjoT1fpW0bb//LqImOEn9yJAMWIvOw1cDz001b6TDV9wmNuqnRkFa9qsKP4s09QWC4gXA8+8Se2O8nly2OP78S1/wGt/aI/bixariUeaFtJ76JxunuOSxSvUDZ9CRdiGKg9mijyDpJLYmsLiQeS+HUJyiFSyinnWMpTCkENLnL0qs8dt37HAYfqx6oOnzfUaxRAjCpH1ON/uVd+mjDwFUQWBG1edHaPfqGsj+1DsIm+iEJOXVmwhzMA+LDf64WdiG+KOLid03SekeWhNIrgBOIYy5gQ3xc582J8RVgc+Nx/ODVNQT4zrLwj6IRbK8NIt7piXydp78bT1njS7u0Oh7tm4cnfXjcXbUGkbJvUhhqwvwQgYbo9v5KfLHLLfLa/iT7KWotW+J0OMHog3gRRIguMVtQGo1hC5TtMH4PJ9o5fW1O/dfjskpx2uFl9To1Ns10Uh5SGBSZiewztwXibSKI8r+Bs8QI/Qqs/KdGT8XZJqvqyOFBbBmcY5utCyp4jyzBzS4k+C7Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwuHeKyiUhPLxY6YqGoKPb1R1ukSJkjCcgqpHxDlG3SFnRzbe55prQ0SEsMIIzijFjECtLz0Wx/VN571Zj3ysuDQ==" - } - ], - "Transactions sendTransaction lets you configure the expiration": [ - { - "id": "76e7c23f-ca98-442a-8faf-af198d28d0b9", - "name": "expiration", - "spendingKey": "540175ed6f7bad754823793631a0430c6904cc5eb1dde119dff7f86cd93edf1a", - "incomingViewKey": "29fd678fb3652df9f385093d74f93888808ed9c238c92730d7c3f8a22c155e05", - "outgoingViewKey": "e6c9568e251c34d4f377b9d21c33990004a7792100ad89e20ecd832223938ac2", - "publicAddress": "ab16fa4e8f06d080eabc7419198eca3deab31c635f117ddc4d481d3a61e290d9" - }, - { - "type": "Buffer", - "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAZNSIDX+0CxJ2wToT1u1xyEcPkCtZbWM2Qbx/11tDEUiD1bRlo1hFr/J3KTiVI3ld/6+eG8aTCOHlYiZ7LEgadKwurq5XcRCDBF7XMdZ2/pKDEYpXzYceiR+ZUEbIh07mcF9xm3Kb+7jtMfZ4jzWvyGVsvyjJ3H8pygqdXQd6rjQXwMWWxJ5dXm5e/M0OeWqzqb4bgHOBM9zPdNfFWaxA2DH42e6fZG+75ib/OE+/xAqlZj9oeuqsGbw1mmFbAENIPBKklYyDlo7plMyVeaU4EEshPgSs99SAZzzcMl7he0QD0EzffjrsGXwB9AIfOmJGhlXcHOkKlt3d3qbpOBt67lYTR4U5NqxhQgH7HSBhToc79xevGvrAvCK40Vh8IFlXgGGVAJYr32Aw+p1Nbet7zhucFG+YGG0M8qjTvgDmEcZEAzXAt3JkCjMIivDOi9oHkD4AeJZgr2KfANs3qLSNdCVBuHnIqawbPqjx7RE9s04TOG6Q71URy0pEegQk2ORnbXbo8AqPUhgq05tM6BMn2y5EsKGtPtkj3VXOf7F+rrwIfu8kiIsihsmrXFtf6dBINqmlbrfwsD5qLtX5/LFNXkl6e5PZgwF9zLI7cpD94Sm0mOBhLE66aklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw2VW03n8VfIrXzwVRt3II6yL1EJoNhKliSF+ugkw8q54fPcmnOgLbeyMkQWflN8sYJFp3AIpTJRs1uruJAO6RBw==" - } - ] -} \ No newline at end of file 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/__fixtures__/mintAsset.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/mintAsset.test.ts.fixture new file mode 100644 index 0000000000..01713fe71e --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/__fixtures__/mintAsset.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/wallet/__fixtures__/sendTransaction.test.ts.fixture b/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture new file mode 100644 index 0000000000..9c77fff588 --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/__fixtures__/sendTransaction.test.ts.fixture @@ -0,0 +1,92 @@ +{ + "Transactions sendTransaction throws if pay throws NotEnoughFundsError": [ + { + "id": "8525a599-26ba-4454-8e7b-91029a58cd2a", + "name": "account-throw-error", + "spendingKey": "db85ee55b4ddcc5376293ea55cf4919d0a390fe80da7576cc50040d8a78b4440", + "incomingViewKey": "8174a4fc78e6f81af16faf34d6b36095db8f217da7329dad5188545c2f354f00", + "outgoingViewKey": "b4aa58f2b60dc91069d472281cd49cb66bc4269dd2bd89b352cd59684f346a0b", + "publicAddress": "efe5fd8edc8d7f8fa920e7f04632aea0af0b8c7e47c46326cf5e996be753af5c" + } + ], + "Transactions sendTransaction calls the pay method on the node with single recipient": [ + { + "id": "a0f87a49-d0f0-48d8-a8a0-365c5084bbfe", + "name": "account", + "spendingKey": "ff0ae50289562ba734314db1b7e3b2bc8dcf224c34bd6309e254bb0e3ac9e177", + "incomingViewKey": "0ceaff1dc8b9bb68b538dcd52e64ed50f522621f860c7a7acb41ce3883714403", + "outgoingViewKey": "c77155f8a3747abb39d5645f5e1caf07009b8e3aa71f5d92ace3dbbbc50fec8e", + "publicAddress": "25e6c0f63fc5c48c91933a456ff66a78b86b24568e9fad1fb40931adec94bb39" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAPkkvGKv19hDe6HebUAB7NFxn9927aH89XtEMi2/38yqofUJsS3/aTeBdG4fb5u5TMyjaiCTm57+b11bwl+4luNPT6NA++pGYuPAqx7tRcuaPMnPi0hI4WyTR19c03y4RqDpHC16v6cYvcecxpm4tJgDIrwynZOwfcWVosk8UZakCYd9WUNkvKraXLF1D9GpeicgH8a0Uz1Wvi7Jbr4O7nUATWNzbTiFG5GFK0Le7NP6L++GrB3MHjTTvv6PZx/EeaAFJo75kLFk0+Hs+QoNr00EdEMiClFt3WW2VNtf3utZRA1ajU+p0xvL4tfHxVFrspq1CV+PahZaPKhQhQX0+llYdP8b65MzOVXsDAgx5jPALR+8XDx2IUegt/q9PdSgMUHZPztg4X8kuXW6N0QdSRjEowkyBQiG5RruYanJBRsnBD4UnuvEfD17oUHGQuDDA7uLrmL/A+i9eXZfMp9MFq5mNTI8IBnfV5jkbI0XSM6RtQBgoL3EhdtzAzNl+jp0n6yVBIsHJQZWsK8GjfTVwcrDsOyHFb9ZgrsUguJs+GRpd0FhZEHSJUp6pwpE1vWrzRw4lVkOA7G1Fif/K7eq+eCyg3jM4KS/jMjszntJvCqdYK25EseafR0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwLdoimwcIAyRx1eqXoazZlxOGF+G/4l1ExCXUhfiUwY7yNJyNi0q6fAqDVuauhFNZG4qriRNuC7PFOXVc2IslDA==" + } + ], + "Transactions sendTransaction calls the pay method on the node with multiple recipient": [ + { + "id": "9216cd8b-5e7d-49a2-af8c-b5f077271104", + "name": "account_multi-output", + "spendingKey": "16302d3d33c94b92fd4f13d673a751632bfb82981c10dcc27236458b533de252", + "incomingViewKey": "78de699372af00a58f6919875e76b166d6b0e7ed1f26ca62061498916eeeae05", + "outgoingViewKey": "9977ec0e39d04a7e2611d8fc17d1cc531f4b70ca3611e8fbbcbf76a6f59401e7", + "publicAddress": "88bdc4d984700d7afc817753cea5bb4e5eaa06d4edf2dce383dfc34b0aa2a9a5" + }, + { + "type": "Buffer", + "data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA1sVq6C/BUO3H1exNtsYrHD9uMzgyLC/HzRMOSj+wsNKvErjVNYd1neFOwQUc5L4q8XQLCzk0kpzC0DrTTa1W7+6E6aeQPHkcrEyvSN/Vb2SoqjoT1fpW0bb//LqImOEn9yJAMWIvOw1cDz001b6TDV9wmNuqnRkFa9qsKP4s09QWC4gXA8+8Se2O8nly2OP78S1/wGt/aI/bixariUeaFtJ76JxunuOSxSvUDZ9CRdiGKg9mijyDpJLYmsLiQeS+HUJyiFSyinnWMpTCkENLnL0qs8dt37HAYfqx6oOnzfUaxRAjCpH1ON/uVd+mjDwFUQWBG1edHaPfqGsj+1DsIm+iEJOXVmwhzMA+LDf64WdiG+KOLid03SekeWhNIrgBOIYy5gQ3xc582J8RVgc+Nx/ODVNQT4zrLwj6IRbK8NIt7piXydp78bT1njS7u0Oh7tm4cnfXjcXbUGkbJvUhhqwvwQgYbo9v5KfLHLLfLa/iT7KWotW+J0OMHog3gRRIguMVtQGo1hC5TtMH4PJ9o5fW1O/dfjskpx2uFl9To1Ns10Uh5SGBSZiewztwXibSKI8r+Bs8QI/Qqs/KdGT8XZJqvqyOFBbBmcY5utCyp4jyzBzS4k+C7Elyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwuHeKyiUhPLxY6YqGoKPb1R1ukSJkjCcgqpHxDlG3SFnRzbe55prQ0SEsMIIzijFjECtLz0Wx/VN571Zj3ysuDQ==" + } + ], + "Transactions sendTransaction lets you configure the expiration": [ + { + "id": "99ddf850-539b-45b8-bfb8-8e95d71710b6", + "name": "expiration", + "spendingKey": "f138147e8727c2ecdf8f4dc56c146cfeb7405fe42de698bc8ec2d21e55e82cfe", + "incomingViewKey": "4915d934ca2f08055110d701b2facb0d1125a4ac8744c509c455b84fe547e105", + "outgoingViewKey": "f8f157f95e68400aec1bac0b6c928612f9c9f8d63e922f0d09da655721059f7a", + "publicAddress": "c52dcc2b3ab2d020c92ddfb158fe517f132a8554271625b462b9a08856567dc8" + }, + { + "type": "Buffer", + "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/burnAsset.test.ts b/ironfish/src/rpc/routes/wallet/burnAsset.test.ts new file mode 100644 index 0000000000..0f4a1cc0c8 --- /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', + assetId: '{ 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', + assetId: '{ 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', + assetId: '{ 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 assetId = asset.id() + 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: [{ assetId: asset.id(), value: burnValue }], + }) + jest.spyOn(wallet, 'burn').mockResolvedValueOnce(burnTransaction) + + const response = await routeTest.client.burnAsset({ + account: account.name, + assetId: assetId.toString('hex'), + fee: '1', + value: CurrencyUtils.encode(value), + }) + + expect(response.content).toEqual({ + 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 new file mode 100644 index 0000000000..2fe42e4ac0 --- /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 + assetId: string + fee: string + value: string + expiration?: number + expirationDelta?: number +} + +export interface BurnAssetResponse { + assetId: string + hash: string +} + +export const BurnAssetRequestSchema: yup.ObjectSchema = yup + .object({ + account: yup.string().required(), + assetId: 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({ + assetId: 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.assetId, '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({ + 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 2d0a819db0..569869f656 100644 --- a/ironfish/src/rpc/routes/wallet/getBalance.ts +++ b/ironfish/src/rpc/routes/wallet/getBalance.ts @@ -8,32 +8,38 @@ import { getAccount } from './utils' export type GetBalanceRequest = { account?: string - assetIdentifier?: string + assetId?: string minimumBlockConfirmations?: number } export type GetBalanceResponse = { account: string + assetId: string confirmed: string unconfirmed: string unconfirmedCount: number minimumBlockConfirmations: number + blockHash: string | null + sequence: number | null } 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(), + assetId: yup.string().defined(), unconfirmed: yup.string().defined(), 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() @@ -48,21 +54,24 @@ 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, + assetId: assetId.toString('hex'), confirmed: balance.confirmed.toString(), 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/getNotes.ts b/ironfish/src/rpc/routes/wallet/getNotes.ts index 383eee7bd2..4b43c1dcfd 100644 --- a/ironfish/src/rpc/routes/wallet/getNotes.ts +++ b/ironfish/src/rpc/routes/wallet/getNotes.ts @@ -3,13 +3,16 @@ * 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 { ApiNamespace, router } from '../router' import { getAccount } from './utils' export type GetAccountNotesStreamRequest = { account?: string } export type GetAccountNotesStreamResponse = { - amount: string + value: string + assetId: string + assetName: string memo: string sender: string transactionHash: string @@ -26,7 +29,9 @@ export const GetAccountNotesStreamRequestSchema: yup.ObjectSchema = yup .object({ - amount: yup.string().defined(), + value: yup.string().defined(), + assetId: yup.string().defined(), + assetName: yup.string().defined(), memo: yup.string().trim().defined(), sender: yup.string().defined(), transactionHash: yup.string().defined(), @@ -48,8 +53,12 @@ router.register = @@ -44,7 +47,10 @@ 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/index.ts b/ironfish/src/rpc/routes/wallet/index.ts index b58b3f3d78..c38586b69a 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' @@ -13,6 +14,9 @@ export * from './getStatus' export * from './getTransaction' export * from './getTransactions' export * from './importAccount' +export * from './mintAsset' export * from './removeAccount' export * from './rescanAccount' +export * from './sendTransaction' +export * from './sendTransaction' export * from './useAccount' diff --git a/ironfish/src/rpc/routes/wallet/mintAsset.test.ts b/ironfish/src/rpc/routes/wallet/mintAsset.test.ts new file mode 100644 index 0000000000..15810f6849 --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/mintAsset.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, useTxFixture } from '../../../testUtilities' +import { createRouteTest } from '../../../testUtilities/routeTest' +import { CurrencyUtils } from '../../../utils' + +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: CurrencyUtils.encode(value), + }) + + expect(response.content).toEqual({ + 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 new file mode 100644 index 0000000000..439542f167 --- /dev/null +++ b/ironfish/src/rpc/routes/wallet/mintAsset.ts @@ -0,0 +1,81 @@ +/* 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 + expiration?: number + expirationDelta?: number +} + +export interface MintAssetResponse { + assetId: 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(), + expiration: yup.number().optional(), + expirationDelta: yup.number().optional(), + }) + .defined() + +export const MintAssetResponseSchema: yup.ObjectSchema = yup + .object({ + assetId: yup.string().required(), + hash: yup.string().required(), + }) + .defined() + +router.register( + `${ApiNamespace.wallet}/mintAsset`, + 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, + request.data.expirationDelta ?? node.config.get('transactionExpirationDelta'), + request.data.expiration, + ) + Assert.isEqual(transaction.mints.length, 1) + const mint = transaction.mints[0] + + request.end({ + assetId: mint.asset.id().toString('hex'), + hash: transaction.hash().toString('hex'), + }) + }, +) 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/rpc/routes/transactions/sendTransaction.test.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts similarity index 81% rename from ironfish/src/rpc/routes/transactions/sendTransaction.test.ts rename to ironfish/src/rpc/routes/wallet/sendTransaction.test.ts index e7ea390156..647049cb15 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.test.ts +++ b/ironfish/src/rpc/routes/wallet/sendTransaction.test.ts @@ -15,6 +15,7 @@ const TEST_PARAMS = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', + assetId: Asset.nativeId().toString('hex'), }, ], fee: BigInt(1).toString(), @@ -27,11 +28,13 @@ const TEST_PARAMS_MULTI = { publicAddress: 'test2', amount: BigInt(10).toString(), memo: '', + assetId: Asset.nativeId().toString('hex'), }, { publicAddress: 'test3', amount: BigInt(10).toString(), memo: '', + assetId: Asset.nativeId().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, @@ -103,12 +106,14 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(11), confirmed: BigInt(0), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) 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, @@ -119,12 +124,14 @@ 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( 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, @@ -132,21 +139,21 @@ 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') - .mockRejectedValue( - new NotEnoughFundsError(Asset.nativeIdentifier(), BigInt(0), BigInt(1)), - ) + .spyOn(routeTest.node.wallet, 'send') + .mockRejectedValue(new NotEnoughFundsError(Asset.nativeId(), BigInt(0), BigInt(1))) jest.spyOn(routeTest.node.wallet, 'getBalance').mockResolvedValueOnce({ unconfirmed: BigInt(11), confirmed: BigInt(11), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) await expect(routeTest.client.sendTransaction(TEST_PARAMS)).rejects.toThrow( @@ -158,36 +165,40 @@ 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), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) const result = await routeTest.client.sendTransaction(TEST_PARAMS) 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), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) const result = await routeTest.client.sendTransaction(TEST_PARAMS_MULTI) @@ -205,28 +216,30 @@ describe('Transactions sendTransaction', () => { unconfirmed: BigInt(100000), confirmed: BigInt(100000), unconfirmedCount: 0, + blockHash: null, + sequence: null, }) - 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(), 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( + expect(sendSpy).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.anything(), diff --git a/ironfish/src/rpc/routes/transactions/sendTransaction.ts b/ironfish/src/rpc/routes/wallet/sendTransaction.ts similarity index 71% rename from ironfish/src/rpc/routes/transactions/sendTransaction.ts rename to ironfish/src/rpc/routes/wallet/sendTransaction.ts index c3f9085ea1..48e00c245d 100644 --- a/ironfish/src/rpc/routes/transactions/sendTransaction.ts +++ b/ironfish/src/rpc/routes/wallet/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,10 +15,11 @@ export type SendTransactionRequest = { publicAddress: string amount: string memo: string + assetId?: string }[] fee: string - expirationSequence?: number | null - expirationSequenceDelta?: number | null + expiration?: number | null + expirationDelta?: number | null } export type SendTransactionResponse = { @@ -25,6 +27,7 @@ export type SendTransactionResponse = { publicAddress: string amount: string memo: string + assetId?: string }[] fromAccountName: string hash: string @@ -40,13 +43,14 @@ export const SendTransactionRequestSchema: yup.ObjectSchema( - `${ApiNamespace.transaction}/sendTransaction`, + `${ApiNamespace.wallet}/sendTransaction`, SendTransactionRequestSchema, async (request, node): Promise => { const transaction = request.data @@ -94,48 +99,56 @@ router.register( } const receives = transaction.receives.map((receive) => { + 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: Asset.nativeIdentifier(), + assetId, } }) 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.nativeId(), fee) + for (const { assetId, amount } of receives) { + if (amount < 0) { + throw new ValidationError(`Invalid transaction amount ${amount}.`) } + + const sum = totalByAssetIdentifier.get(assetId) ?? BigInt(0) + totalByAssetIdentifier.set(assetId, 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 [assetId, sum] of totalByAssetIdentifier) { + const balance = await node.wallet.getBalance(account, assetId) - 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 { - const transactionPosted = await node.wallet.pay( + const transactionPosted = await node.wallet.send( node.memPool, 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/types.ts b/ironfish/src/rpc/routes/wallet/types.ts index 744931bc43..61dfcf05d3 100644 --- a/ironfish/src/rpc/routes/wallet/types.ts +++ b/ironfish/src/rpc/routes/wallet/types.ts @@ -11,7 +11,10 @@ export type RpcAccountTransaction = { blockSequence?: number notesCount: number spendsCount: number - expirationSequence: number + mintsCount: number + burnsCount: number + expiration: number + timestamp: number } export type RpcAccountDecryptedNote = { @@ -33,6 +36,9 @@ export function serializeRpcAccountTransaction( blockSequence: transaction.sequence ?? undefined, notesCount: transaction.transaction.notes.length, spendsCount: transaction.transaction.spends.length, - expirationSequence: transaction.transaction.expirationSequence(), + mintsCount: transaction.transaction.mints.length, + burnsCount: transaction.transaction.burns.length, + expiration: transaction.transaction.expiration(), + timestamp: transaction.timestamp.getTime(), } } 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/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/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/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.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/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/encoding.ts b/ironfish/src/storage/database/encoding.ts index b852a41828..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,31 +150,40 @@ export class NullableStringEncoding implements IDatabaseEncoding export class ArrayEncoding extends JsonEncoding {} -export default class BufferToStringEncoding implements Serde { - serialize(element: Buffer): string { - return hexArray.toString(element) +export class BigIntLEEncoding implements IDatabaseEncoding { + serialize(value: bigint): Buffer { + return BigIntUtils.toBytesLE(value) } - deserialize(data: string): Buffer { - return Buffer.from(hexArray.fromString(data)) + deserialize(buffer: Buffer): bigint { + return BigIntUtils.fromBytesLE(buffer) } +} - equals(): boolean { - throw new Error('You should never use this') +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 class BigIntLEEncoding implements IDatabaseEncoding { - serialize(value: bigint): Buffer { - return BigIntUtils.toBytesLE(value) +export class BufferToStringEncoding { + static serialize(element: Buffer): string { + return element.toString('hex') } - deserialize(buffer: Buffer): bigint { - return BigIntUtils.fromBytesLE(buffer) + static deserialize(data: string): Buffer { + return Buffer.from(data, 'hex') } } -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/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 e453cf47e1..fe24949e95 100644 --- a/ironfish/src/storage/database/types.ts +++ b/ironfish/src/storage/database/types.ts @@ -11,6 +11,12 @@ export interface DatabaseKeyRange { lte?: Buffer } +export interface DatabaseIteratorOptions { + reverse?: boolean + limit?: number + ordered?: boolean +} + 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..d1cc7b2459 100644 --- a/ironfish/src/storage/levelup/store.ts +++ b/ironfish/src/storage/levelup/store.ts @@ -3,10 +3,12 @@ * 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' import { + DatabaseIteratorOptions, DatabaseKeyRange, DatabaseSchema, DatabaseStore, @@ -16,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' @@ -74,6 +76,7 @@ export class LevelupStore extends DatabaseStore, SchemaValue]> { if (keyRange) { keyRange = StorageUtils.addPrefixToRange(keyRange, this.prefixBuffer) @@ -82,13 +85,17 @@ 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) await transaction.acquireLock() for (const [keyString, value] of transaction.cache.entries()) { - const key = BUFFER_TO_STRING_ENCODING.deserialize(keyString) + const key = BufferToStringEncoding.deserialize(keyString) if (!StorageUtils.hasPrefix(key, this.prefixBuffer)) { continue @@ -104,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)) { + 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 } } @@ -136,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 } } @@ -152,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 { diff --git a/ironfish/src/storage/levelup/transaction.ts b/ironfish/src/storage/levelup/transaction.ts index 7cd3b31d3a..20516577ce 100644 --- a/ironfish/src/storage/levelup/transaction.ts +++ b/ironfish/src/storage/levelup/transaction.ts @@ -5,7 +5,7 @@ import type { LevelupDatabase } from './database' import type { LevelupStore } from './store' import { MutexUnlockFunction } from '../../mutex' import { - BUFFER_TO_STRING_ENCODING, + BufferToStringEncoding, DatabaseSchema, DuplicateKeyError, IDatabaseTransaction, @@ -81,7 +81,7 @@ export class LevelupTransaction implements IDatabaseTransaction { this.assertCanRead() const [encodedKey] = store.encode(key) - const cacheKey = BUFFER_TO_STRING_ENCODING.serialize(encodedKey) + const cacheKey = BufferToStringEncoding.serialize(encodedKey) if (this.cacheDelete.has(cacheKey)) { return undefined @@ -107,7 +107,7 @@ export class LevelupTransaction implements IDatabaseTransaction { this.assertCanWrite() const [encodedKey, encodedValue] = store.encode(key, value) - const cacheKey = BUFFER_TO_STRING_ENCODING.serialize(encodedKey) + const cacheKey = BufferToStringEncoding.serialize(encodedKey) this.batch.putEncoded(encodedKey, encodedValue) this.cache.set(cacheKey, value) @@ -128,7 +128,7 @@ export class LevelupTransaction implements IDatabaseTransaction { } const [encodedKey, encodedValue] = store.encode(key, value) - const cacheKey = BUFFER_TO_STRING_ENCODING.serialize(encodedKey) + const cacheKey = BufferToStringEncoding.serialize(encodedKey) this.batch.putEncoded(encodedKey, encodedValue) this.cache.set(cacheKey, value) this.cacheDelete.delete(cacheKey) @@ -143,7 +143,7 @@ export class LevelupTransaction implements IDatabaseTransaction { this.assertCanWrite() const [encodedKey] = store.encode(key) - const cacheKey = BUFFER_TO_STRING_ENCODING.serialize(encodedKey) + const cacheKey = BufferToStringEncoding.serialize(encodedKey) this.batch.delEncoded(encodedKey) this.cache.set(cacheKey, undefined) this.cacheDelete.add(cacheKey) 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 deleted file mode 100644 index ead5b9da3e..0000000000 --- a/ironfish/src/testUtilities/fixtures.ts +++ /dev/null @@ -1,528 +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 { 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 { 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 { 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 - }, - }) -} - -/* - * We need the workaround because transactions related to us - * 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 - * cached, both have the same flow where we manually sync - * them afterwards. - */ -export async function restoreBlockFixtureToAccounts( - block: Block, - wallet: Wallet, -): Promise { - for (const transaction of block.transactions) { - await restoreTransactionFixtureToAccounts(transaction, wallet) - } -} - -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 - */ -export async function useBlockFixture( - chain: Blockchain, - generate: FixtureGenerate, - addTransactionsTo?: Wallet, -): Promise { - return useFixture(generate, { - process: async (block: Block): Promise => { - if (addTransactionsTo) { - await restoreBlockFixtureToAccounts(block, addTransactionsTo) - } - }, - serialize: (block: Block): SerializedBlock => { - return BlockSerde.serialize(block) - }, - deserialize: (serialized: SerializedBlock): Block => { - return BlockSerde.deserialize(serialized) - }, - }) -} - -/** - * Generates a block with a miners fee transaction on the current chain state - */ -export async function useMinerBlockFixture( - chain: Blockchain, - sequence?: number, - account?: Account, - addTransactionsTo?: Wallet, - transactions: Transaction[] = [], -): Promise { - const spendingKey = account ? account.spendingKey : generateKey().spending_key - const transactionFees = transactions.reduce((a, t) => a + t.fee(), BigInt(0)) - - return await useBlockFixture( - chain, - async () => - chain.newBlock( - transactions, - await chain.strategy.createMinersFee( - transactionFees, - sequence || chain.head.sequence + 1, - spendingKey, - ), - ), - addTransactionsTo, - ) -} - -export async function useRawTxFixture(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 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) - }, - }) -} - -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: '', - assetIdentifier: Asset.nativeIdentifier(), - }, - ], - [], - [], - 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, - sender: Account, - notesToSpend: NoteEncrypted[], - receives: { publicAddress: string; amount: bigint; memo: string; assetIdentifier: Buffer }[], - mints: MintDescription[], - burns: BurnDescription[], - sequence: number, -): Promise { - const generate = async () => { - const transaction = await buildRawTransaction( - chain, - pool, - sender, - notesToSpend, - receives, - mints, - burns, - ) - return chain.newBlock( - [transaction], - await chain.strategy.createMinersFee(transaction.fee(), sequence, sender.spendingKey), - ) - } - - 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 - * {@link from} account and adds it to the chain. - * - * Returned block has 1 spend, 3 notes - */ -export async function useBlockWithTx( - node: IronfishNode, - from?: Account, - to?: Account, - useFee = true, - options: { - expiration?: number - fee?: number - } = { expiration: 0 }, -): Promise<{ account: Account; previous: Block; block: Block; transaction: Transaction }> { - if (!from) { - from = await useAccountFixture(node.wallet, () => node.wallet.createAccount('test')) - } - - if (!to) { - to = from - } - - let previous: Block - if (useFee) { - previous = await useMinerBlockFixture(node.chain, 2, from) - await node.chain.addBlock(previous) - await node.wallet.updateHead() - } else { - const head = await node.chain.getBlock(node.chain.head) - Assert.isNotNull(head) - previous = head - } - - const block = await useBlockFixture(node.chain, async () => { - Assert.isNotUndefined(from) - Assert.isNotUndefined(to) - - const raw = await node.wallet.createTransaction( - from, - [ - { - publicAddress: to.publicAddress, - amount: BigInt(1), - memo: '', - assetIdentifier: Asset.nativeIdentifier(), - }, - ], - [], - [], - BigInt(options.fee ?? 1), - options.expiration ?? 0, - ) - - const transaction = await node.wallet.postTransaction(raw) - - return node.chain.newBlock( - [transaction], - await node.strategy.createMinersFee(transaction.fee(), 3, generateKey().spending_key), - ) - }) - - return { block, previous, account: from, transaction: block.transactions[1] } -} - -/** - * Produces a block with a multiple transaction that have 1 spend, and 3 notes - * It first produces {@link numTransactions} blocks all with mining fees to fund - * the transactions - * - * Returned block has {@link numTransactions} transactions - */ -export async function useBlockWithTxs( - node: IronfishNode, - numTransactions: number, - from?: Account, -): Promise<{ account: Account; block: Block; transactions: Transaction[] }> { - if (!from) { - from = await useAccountFixture(node.wallet, () => node.wallet.createAccount('test')) - } - const to = from - - let previous - for (let i = 0; i < numTransactions; i++) { - previous = await useMinerBlockFixture(node.chain, node.chain.head.sequence + 1, from) - await node.chain.addBlock(previous) - } - - await node.wallet.updateHead() - - const block = await useBlockFixture(node.chain, async () => { - const transactions: Transaction[] = [] - for (let i = 0; i < numTransactions; i++) { - Assert.isNotUndefined(from) - - const raw = await node.wallet.createTransaction( - from, - [ - { - publicAddress: to.publicAddress, - amount: BigInt(1), - memo: '', - assetIdentifier: Asset.nativeIdentifier(), - }, - ], - [], - [], - BigInt(1), - 0, - ) - - const transaction = await node.wallet.postTransaction(raw) - - await node.wallet.addPendingTransaction(transaction) - transactions.push(transaction) - } - - const transactionFees: bigint = transactions.reduce((sum, t) => { - return BigInt(sum) + t.fee() - }, BigInt(0)) - - return node.chain.newBlock( - transactions, - await node.strategy.createMinersFee(transactionFees, 3, generateKey().spending_key), - ) - }) - - return { block, account: from, transactions: block.transactions.slice(1) } -} diff --git a/ironfish/src/testUtilities/fixtures/account.ts b/ironfish/src/testUtilities/fixtures/account.ts new file mode 100644 index 0000000000..59fb5210a9 --- /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 account.updateHeadHash(wallet.chainProcessor.hash) + return account + }, + }) +} diff --git a/ironfish/src/testUtilities/fixtures/blocks.ts b/ironfish/src/testUtilities/fixtures/blocks.ts new file mode 100644 index 0000000000..bd5c444715 --- /dev/null +++ b/ironfish/src/testUtilities/fixtures/blocks.ts @@ -0,0 +1,346 @@ +/* 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, generateKey } from '@ironfish/rust-nodejs' +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 + * 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.send(), so if its generated, and if its + * cached, both have the same flow where we manually sync + * them afterwards. + */ +export async function restoreBlockFixtureToAccounts( + block: Block, + wallet: Wallet, +): Promise { + for (const transaction of block.transactions) { + await restoreTransactionFixtureToAccounts(transaction, wallet) + } +} + +/** + * Executes a generator function which creates a block and + * caches that in the fixtures folder next to the current test + */ +export async function useBlockFixture( + chain: Blockchain, + generate: FixtureGenerate, + addTransactionsTo?: Wallet, +): Promise { + return useFixture(generate, { + process: async (block: Block): Promise => { + if (addTransactionsTo) { + await restoreBlockFixtureToAccounts(block, addTransactionsTo) + } + }, + serialize: (block: Block): SerializedBlock => { + return BlockSerde.serialize(block) + }, + deserialize: (serialized: SerializedBlock): Block => { + return BlockSerde.deserialize(serialized) + }, + }) +} + +/** + * Generates a block with a miners fee transaction on the current chain state + */ +export async function useMinerBlockFixture( + chain: Blockchain, + sequence?: number, + account?: Account, + addTransactionsTo?: Wallet, + transactions: Transaction[] = [], +): Promise { + const spendingKey = account ? account.spendingKey : generateKey().spending_key + const transactionFees = transactions.reduce((a, t) => a + t.fee(), BigInt(0)) + + return await useBlockFixture( + chain, + async () => + chain.newBlock( + transactions, + await chain.strategy.createMinersFee( + transactionFees, + sequence || chain.head.sequence + 1, + spendingKey, + ), + ), + addTransactionsTo, + ) +} + +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 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: [{ assetId: options.asset.id(), value: options.value }], + }) + + return useMinerBlockFixture(options.node.chain, options.sequence, undefined, undefined, [ + burn, + ]) +} + +export async function useBlockWithRawTxFixture( + chain: Blockchain, + pool: WorkerPool, + sender: Account, + notesToSpend: NoteEncrypted[], + receives: { publicAddress: string; amount: bigint; memo: string; assetId: Buffer }[], + mints: MintDescription[], + burns: BurnDescription[], + sequence: number, +): Promise { + const generate = async () => { + 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), + ) + } + + return useBlockFixture(chain, generate) +} + +/** + * 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 + * {@link from} account and adds it to the chain. + * + * Returned block has 1 spend, 3 notes + */ +export async function useBlockWithTx( + node: IronfishNode, + from?: Account, + to?: Account, + useFee = true, + options: { + expiration?: number + fee?: number + } = { expiration: 0 }, +): Promise<{ account: Account; previous: Block; block: Block; transaction: Transaction }> { + if (!from) { + from = await useAccountFixture(node.wallet, () => node.wallet.createAccount('test')) + } + + if (!to) { + to = from + } + + let previous: Block + if (useFee) { + previous = await useMinerBlockFixture(node.chain, 2, from) + await node.chain.addBlock(previous) + await node.wallet.updateHead() + } else { + const head = await node.chain.getBlock(node.chain.head) + Assert.isNotNull(head) + previous = head + } + + const block = await useBlockFixture(node.chain, async () => { + Assert.isNotUndefined(from) + Assert.isNotUndefined(to) + + const raw = await node.wallet.createTransaction( + from, + [ + { + publicAddress: to.publicAddress, + amount: BigInt(1), + memo: '', + assetId: Asset.nativeId(), + }, + ], + [], + [], + BigInt(options.fee ?? 1), + options.expiration ?? 0, + ) + + const transaction = await node.wallet.postTransaction(raw) + + return node.chain.newBlock( + [transaction], + await node.strategy.createMinersFee(transaction.fee(), 3, generateKey().spending_key), + ) + }) + + return { block, previous, account: from, transaction: block.transactions[1] } +} + +/** + * Produces a block with a multiple transaction that have 1 spend, and 3 notes + * It first produces {@link numTransactions} blocks all with mining fees to fund + * the transactions + * + * Returned block has {@link numTransactions} transactions + */ +export async function useBlockWithTxs( + node: IronfishNode, + numTransactions: number, + from?: Account, +): Promise<{ account: Account; block: Block; transactions: Transaction[] }> { + if (!from) { + from = await useAccountFixture(node.wallet, () => node.wallet.createAccount('test')) + } + const to = from + + let previous + for (let i = 0; i < numTransactions; i++) { + previous = await useMinerBlockFixture(node.chain, node.chain.head.sequence + 1, from) + await node.chain.addBlock(previous) + } + + await node.wallet.updateHead() + + const block = await useBlockFixture(node.chain, async () => { + const transactions: Transaction[] = [] + for (let i = 0; i < numTransactions; i++) { + Assert.isNotUndefined(from) + + const raw = await node.wallet.createTransaction( + from, + [ + { + publicAddress: to.publicAddress, + amount: BigInt(1), + memo: '', + assetId: Asset.nativeId(), + }, + ], + [], + [], + BigInt(1), + 0, + ) + + const transaction = await node.wallet.postTransaction(raw) + + await node.wallet.addPendingTransaction(transaction) + transactions.push(transaction) + } + + const transactionFees: bigint = transactions.reduce((sum, t) => { + return BigInt(sum) + t.fee() + }, BigInt(0)) + + return node.chain.newBlock( + transactions, + await node.strategy.createMinersFee(transactionFees, 3, generateKey().spending_key), + ) + }) + + 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/rpc/routes/fees/index.ts b/ironfish/src/testUtilities/fixtures/index.ts similarity index 71% rename from ironfish/src/rpc/routes/fees/index.ts rename to ironfish/src/testUtilities/fixtures/index.ts index da6be9cbfd..5d83fe9474 100644 --- a/ironfish/src/rpc/routes/fees/index.ts +++ b/ironfish/src/testUtilities/fixtures/index.ts @@ -1,6 +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 './estimateFeeRates' -export * from './estimateFee' +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, + ) + }) +} diff --git a/ironfish/src/testUtilities/helpers/transaction.ts b/ironfish/src/testUtilities/helpers/transaction.ts index 3871b0cb9b..1e79124eca 100644 --- a/ironfish/src/testUtilities/helpers/transaction.ts +++ b/ironfish/src/testUtilities/helpers/transaction.ts @@ -2,14 +2,12 @@ * 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 { Blockchain } from '../../blockchain' +import { Asset } from '@ironfish/rust-nodejs' 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 { WorkerPool } from '../../workerPool' +import { Account, Wallet } from '../../wallet' export function isTransactionMine(transaction: Transaction, account: Account): boolean { for (const note of transaction.notes) { @@ -27,40 +25,40 @@ 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) +export async function createRawTransaction(options: { + 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 { + const receives = options.receives ?? [] - return { - note, - treeSize: witness.treeSize(), - authPath: witness.authenticationPath, - rootHash: witness.rootHash, - } - }), - ) + if (options.to) { + receives.push({ + publicAddress: options.to.publicAddress, + amount: options.amount ?? 1n, + memo: '', + assetId: options.assetId ?? Asset.nativeId(), + }) + } - return pool.createTransaction( - sender.spendingKey, - spends, + return await options.wallet.createTransaction( + options.from, receives, - mints, - burns, - BigInt(0), - 0, + options.mints ?? [], + options.burns ?? [], + options.fee ?? 0n, + options.expiration ?? 0, ) } 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/typedefs/hex-array.d.ts b/ironfish/src/typedefs/hex-array.d.ts deleted file mode 100644 index 9a214b6e58..0000000000 --- a/ironfish/src/typedefs/hex-array.d.ts +++ /dev/null @@ -1,11 +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/. */ - -declare module 'hex-array' { - export function toString( - array: Uint8Array, - options?: { grouping: number; rowLength: number; uppercase: boolean }, - ): string - export function fromString(value: string): Uint8Array -} diff --git a/ironfish/src/rpc/routes/transactions/index.ts b/ironfish/src/utils/asset.ts similarity index 54% rename from ironfish/src/rpc/routes/transactions/index.ts rename to ironfish/src/utils/asset.ts index 989a6fac4c..c0133c27dd 100644 --- a/ironfish/src/rpc/routes/transactions/index.ts +++ b/ironfish/src/utils/asset.ts @@ -1,5 +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 * from './sendTransaction' +export function isNativeIdentifier(assetId: string): boolean { + return Buffer.from(assetId, 'hex').equals(Asset.nativeId()) +} 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/utils/currency.ts b/ironfish/src/utils/currency.ts index 3bb288a525..89fb6ba1ea 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,19 @@ 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, assetId?: 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 (assetId && !isNativeIdentifier(assetId)) { + ticker = assetId + } + return `${ticker} ${iron}` } return iron @@ -56,15 +61,19 @@ export class CurrencyUtils { /* * Renders ore for human-readable purposes */ - static renderOre(amount: bigint | string, ticker = false): string { + static renderOre(amount: bigint | string, includeTicker = false, assetId?: 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 (assetId && !isNativeIdentifier(assetId)) { + ticker = assetId + } + return `${ticker} ${ore}` } return ore 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: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" } ] } ], "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/__fixtures__/wallet.test.ts.fixture b/ironfish/src/wallet/__fixtures__/wallet.test.ts.fixture index aa8f49e7c2..789305911c 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", @@ -2786,5 +2582,519 @@ } ] } + ], + "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:AQEAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKplSfHu4uXy9Wl0v955wcdqjnenvKyMvm5neLVckr8m1YuJp2+K734SXJqPX10xFg5C0Y3K10AOdJjJSqkcEvvuFX/oz8upIQtJKmOtfIiazJauJNBdCPBGjEWvLhesvIL3uRSS9GYRPN7QuibEd8U7fHf1ZP0gpinyktp893akDKAWcupnowkWKp6DXqcA96ns+GkGPIHAz3YjaHYlw+nygMnL6AOmxlDTFiLRXlf2HODuE+4dnwE5mxbUHhc90qSYbPf3QOJUp5vtipQ7Az6do4Y1sS7a5uFSudyzfvlhVAApLRllPTxrWuVTrUsXR7EFKuMG38nJffCxUQyHTsAUO5eGVJXGzYkYnhjmxcPzgMdFyz9htWgkuoLke4WFIBAAAAAEolEAOpJIxKQE6P38OF3mK944N75+wHKBKr8tvlFJgxHAkLJRE5CSBpuq6YvUO5Bw8Yc0f8j7phLd5jL1WDjNJSJRyqvHPMe9FlB++0axvMsxR2YUyP8mce1RrfE/NBJakCq9hesv722CEeR7b6G6JRTzQ7z4UnFmU/DSswOdec6NaZje/C1EyLAmk/NuA3aw7j3Q02xuAFFkxeUcQFqSnWDDhTTcS3P+sesHCovPg/2Wu+RZZJxoXzy8NuQpJlgE11aLBAUKjJmCjNCWJaj6u5Iz7tVXZV5FXYT2RuvtZ1nLThtP6y76RQNL2icoy3LIUulKOwlEYlsg05S8hiZ+k2rI8GQVtUNLphs53mQr4szCa5rB9a3mgCCMpwqOWTYUFsy11WXxM2hRNzXerCj/IhpXWl83au7pNMdiJ//VBVPsomHFb7WPgMqKrksVwhfYQ3ilUxkFay9WERHXXtRYpGXNehQI8Xo8a75PFksN97EqCzqRueFT3A6nVo7dg8NU2B/pms29H5y8i5Mgc8tGDg6DOiUy6Rg+BQtAbJSDvgRre5cMnwrz0JFfpO4Xn0d0O8nUqahXlMQDDxx7bgKmBxFJ1KyvP6AHc7l7wfIDP4c1dLCLXpECe79qA6fRJlqHOS5SPRd11XMGAQJh577UiA456f83ttZjUMiRdoYbCCpNbESDKez3SlPTMtDOiv+yLjTw59EaOicxyhJ1u0HPr5wipKSkhVM7lfsfK+ku2CYzQ+PmTvf9xGZy3TAoCnf3wujAnahcwSTzSoSTjRXU6kDZGyRyMMJBeZSUYgKi4Rr+YoyB7HSKPCRN3NZ4XaEj79jwe8g14RLztDvSlsLDG2P1x3u6KR+4YpyBAoZvUSVbobtIK8bKFlRyH5mmc77VBH80QfZ+yLtsj2EJmYSuRaWwMH3BMC/kQAX/pX/xbDsLJGRBPSOgKX9wrci7BPFLGLb/lYgUpEOwAnhzwFjhuveUvzizCZMZt9VNlooH7soHNo3b7Kg6C9FejTkTGJpibXxh46GO9dMeZGPhWPpTfTTJWuT6shBHyT98MStXp8GWmv6zcMPYgtT+1Q5RrUV/AE5s2p/Vdkjbfx73n+Tk8vhBh9MTRQ2cut3LKr7cSwHGxgE+YfUqocASaqLtIArfmCOFA4Qoa2P956toxHZE9Bck84ZW6RZ4bnEKmwkuPI1r30UK7AjXCtbl1GR/mwcUQct5GOQ9iPOBOUh2iKKpMvM/X0eTD2YaKIYkbX/gcQR6NHi1zNI77vt+/jIvOCTlC0f69kcVNOoluwJGfaujhQjr5CtfB3IPvgeZ+KUBE2zsu+18Rh54HTAWDeOuIBcYq5vagnuH5XdwoSllpJlhnNAoGcV9J2UtzZLPMxNSU5vjN4vPWegt4aAS3wf/1yH0KFnSyllCdhynXEVUpJftEFzCKwOUUPqDfcYfpnDpNHkyZHJ3TnjQyrIEbXLQuweHbJpj3zj1boDN/PhGf4eA32qWWXUZV3JR5APG1m0MPhUfrS7WHGA5pIJkVm85YoROIapmKocsgHd5UI9un3qSYC4xM6NN8//brG2veVzT6lNF3pJqNZrYUj25tW2E7OM2Bso/70SboMyCf+iQg8pBrhfQzZArMSZKQqxJqH6usAUpLB1ugNCP0GtUoRnP+c5W+cSxRwwDZnawhXTQqVv5ejyNt84d7quLzcZvboB92mDC+8bFEHunAPepvdNZ77oLFRRrzzAMmrRx0wxOK/+SgmXwri8Gs3oD7a29e8hX4icdjUuYO/UlGmJhfVbRW9B1hK/xaAEfgScPGv4Rh1LJtaW50LWFzc2V0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1ldGFkYXRhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAABNWOM1cXXuQSC57CfLhgJgLh7PL/H+G+zjK1jpJzDsS3UbyWDGszD6STcpj+c9LCJpUx2rto4n+sSAk3FWe5FEB1DE5CJe38DfdRy2m1nVGkDu8WuT83IOoom0UyvWIQL53GnrZg9T9wSaDkWBsK67wJ+wLgKbMrsb0aivS8QBrt+D+OlyuhybvZFBRj+0mFzFvSBhcisqTbuv9FAr0TcK" + } + ] + }, + { + "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: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" + } + ] + } + ], + "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/account.test.ts b/ironfish/src/wallet/account.test.ts index 670048dcf8..46197bc2f9 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() @@ -115,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), }) @@ -128,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), }) @@ -201,17 +202,25 @@ 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) + 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], + const expectedBalances = new BufferMap([ + [Asset.nativeId(), nativeBalance], + [asset.id(), mintedAssetBalance], ]) expect(balances.size).toBe(expectedBalances.size) @@ -297,7 +306,7 @@ describe('Accounts', () => { const pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeDefined() @@ -404,7 +413,7 @@ describe('Accounts', () => { const pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeUndefined() @@ -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) @@ -533,17 +542,17 @@ describe('Accounts', () => { let pendingHashEntry = await accountA['walletDb'].pendingTransactionHashes.get([ accountA.prefix, - [transaction.expirationSequence(), transaction.hash()], + [transaction.expiration(), transaction.hash()], ]) expect(pendingHashEntry).toBeUndefined() // disconnect transaction - await accountA.disconnectTransaction(transaction) + await accountA.disconnectTransaction(block3.header, transaction) 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..775640a30e 100644 --- a/ironfish/src/wallet/account.ts +++ b/ironfish/src/wallet/account.ts @@ -9,10 +9,9 @@ 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 { BalanceValue } from './walletdb/balanceValue' import { DecryptedNoteValue } from './walletdb/decryptedNoteValue' import { TransactionValue } from './walletdb/transactionValue' import { WalletDB } from './walletdb/walletdb' @@ -83,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 { @@ -92,10 +92,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 } @@ -118,72 +118,25 @@ 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, decryptedNotes: Array, tx?: IDatabaseTransaction, ): Promise { - const balanceDeltas = new AssetBalanceDeltas() + const blockHash = blockHeader.hash + const sequence = blockHeader.sequence + const assetBalanceDeltas = new AssetBalanceDeltas() + let submittedSequence = sequence + 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) { if (decryptedNote.forSpender) { continue @@ -198,11 +151,11 @@ 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()) + assetBalanceDeltas.increment(note.note.assetId(), note.note.value()) await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -217,7 +170,7 @@ export class Account { Assert.isNotUndefined(note) - balanceDeltas.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) @@ -228,23 +181,27 @@ export class Account { transaction.hash(), { transaction, - blockHash: blockHeader.hash, - sequence: blockHeader.sequence, - submittedSequence: blockHeader.sequence, + blockHash, + sequence, + submittedSequence, + timestamp, + assetBalanceDeltas: assetBalanceDeltas, }, tx, ) - await this.updateUnconfirmedBalances(balanceDeltas, tx) + await this.updateUnconfirmedBalances(assetBalanceDeltas, blockHash, sequence, tx) }) } async addPendingTransaction( transaction: Transaction, decryptedNotes: Array, - submittedSequence: number | null, + submittedSequence: number, tx?: IDatabaseTransaction, ): Promise { + const assetBalanceDeltas = new AssetBalanceDeltas() + await this.walletDb.db.withTransaction(tx, async (tx) => { if (await this.hasTransaction(transaction.hash(), tx)) { return @@ -266,6 +223,8 @@ export class Account { sequence: null, } + assetBalanceDeltas.increment(note.note.assetId(), note.note.value()) + await this.walletDb.saveDecryptedNote(this, decryptedNote.hash, note, tx) } @@ -279,6 +238,8 @@ export class Account { Assert.isNotUndefined(note) + assetBalanceDeltas.increment(note.note.assetId(), -note.note.value()) + const spentNote = { ...note, spent: true } await this.walletDb.saveDecryptedNote(this, spentNoteHash, spentNote, tx) } @@ -291,6 +252,8 @@ export class Account { blockHash: null, sequence: null, submittedSequence, + timestamp: new Date(), + assetBalanceDeltas, }, tx, ) @@ -298,6 +261,7 @@ export class Account { } async disconnectTransaction( + blockHeader: BlockHeader, transaction: Transaction, tx?: IDatabaseTransaction, ): Promise { @@ -317,7 +281,7 @@ export class Account { } balanceDeltas.increment( - decryptedNoteValue.note.assetIdentifier(), + decryptedNoteValue.note.assetId(), -decryptedNoteValue.note.value(), ) @@ -352,12 +316,12 @@ 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( this, - transaction.expirationSequence(), + transaction.expiration(), transaction.hash(), tx, ) @@ -369,104 +333,15 @@ export class Account { tx, ) - await this.updateUnconfirmedBalances(balanceDeltas, tx) - }) - } - - 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) + await this.updateUnconfirmedBalances( + balanceDeltas, + blockHeader.previousBlockHash, + blockHeader.sequence - 1, + 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, @@ -507,6 +382,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, @@ -548,7 +427,8 @@ export class Account { 'nullifierToNote mappings must have a corresponding decryptedNote', ) - await this.updateDecryptedNote( + await this.walletDb.saveDecryptedNote( + this, noteHash, { ...decryptedNote, @@ -561,7 +441,7 @@ export class Account { await this.walletDb.deletePendingTransactionHash( this, - transaction.expirationSequence(), + transaction.expiration(), transactionHash, tx, ) @@ -575,17 +455,19 @@ export class Account { */ async getBalance( headSequence: number, - assetIdentifier: Buffer, + assetId: Buffer, minimumBlockConfirmations: number, tx?: IDatabaseTransaction, ): Promise<{ unconfirmed: bigint unconfirmedCount: number confirmed: bigint + blockHash: Buffer | null + sequence: number | null }> { let unconfirmedCount = 0 - const unconfirmed = await this.getUnconfirmedBalance(assetIdentifier, tx) + const { unconfirmed, blockHash, sequence } = await this.getUnconfirmedBalance(assetId, tx) let confirmed = unconfirmed if (minimumBlockConfirmations > 0) { @@ -602,7 +484,7 @@ export class Account { unconfirmedSequenceEnd, tx, )) { - if (!note.note.assetIdentifier().equals(assetIdentifier)) { + if (!note.note.assetId().equals(assetId)) { continue } @@ -617,55 +499,64 @@ export class Account { unconfirmed, unconfirmedCount, confirmed, + blockHash, + sequence, } } - async getUnconfirmedBalances(tx?: IDatabaseTransaction): Promise> { - const unconfirmedBalances = new BufferMap() - for await (const { assetIdentifier, balance } of this.walletDb.getUnconfirmedBalances( - this, - tx, - )) { - unconfirmedBalances.set(assetIdentifier, balance) + async getUnconfirmedBalances(tx?: IDatabaseTransaction): Promise> { + const unconfirmedBalances = new BufferMap() + 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) + ): Promise { + return this.walletDb.getUnconfirmedBalance(this, assetId, tx) } async updateUnconfirmedBalances( balanceDeltas: BufferMap, + blockHash: Buffer | null, + 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, - currentUnconfirmedBalance + balanceDelta, + assetId, + { + unconfirmed: currentUnconfirmedBalance.unconfirmed + balanceDelta, + blockHash, + sequence, + }, tx, ) } } async saveUnconfirmedBalance( - assetIdentifier: Buffer, - balance: bigint, + 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 { 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> { @@ -697,8 +588,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 ee8cbd7864..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,15 +64,13 @@ 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), }) }) - 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 @@ -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,15 +99,13 @@ 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), }) // Spend the balance - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -125,11 +113,11 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), 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,15 +168,13 @@ 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), }) // Spend the balance - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -202,15 +182,15 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], 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 @@ -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,14 +240,12 @@ 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), }) - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -281,27 +253,27 @@ 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), - 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 @@ -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), }) @@ -330,7 +300,7 @@ describe('Accounts', () => { // Spend the balance with an invalid expiration await expect( - node.wallet.pay( + node.wallet.send( node.memPool, account, [ @@ -338,11 +308,11 @@ describe('Accounts', () => { publicAddress: generateKey().public_address, amount: BigInt(2), memo: '', - assetIdentifier: Asset.nativeIdentifier(), + assetId: Asset.nativeId(), }, ], BigInt(0), - node.config.get('defaultTransactionExpirationSequenceDelta'), + node.config.get('transactionExpirationDelta'), 1, ), ).rejects.toThrow(Error) @@ -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,15 +350,13 @@ 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), }) // Spend the balance, setting expiry soon - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -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,15 +437,13 @@ 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), }) // Spend the balance, setting expiry soon - const transaction = await node.wallet.pay( + const transaction = await node.wallet.send( node.memPool, account, [ @@ -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 aa415fe358..318d7b84f7 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' @@ -51,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), }) @@ -83,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), }) @@ -144,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, }) @@ -182,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), }) @@ -199,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), }) @@ -264,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 @@ -313,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 () => { @@ -373,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() @@ -427,11 +393,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), }) }) @@ -451,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) }) @@ -473,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 @@ -684,7 +620,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,118 +869,61 @@ 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() + describe('burn', () => { + it('returns a transaction with matching burn descriptions', async () => { + const { node } = await nodeTest.createSetup() + const account = await useAccountFixture(node.wallet) - await accountA.expireTransaction(tx) + const mined = await useMinerBlockFixture(node.chain, 2, account) + await expect(node.chain).toAddBlock(mined) + await node.wallet.updateHead() - // 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() - } + 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() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - unconfirmed: BigInt(2000000000), // minersFee from blockA1 + const burnValue = BigInt(2) + const transaction = await usePostTxFixture({ + node: node, + wallet: node.wallet, + from: account, + burns: [{ assetId: asset.id(), value: burnValue }], }) - // 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 - }) + expect(transaction.burns).toEqual([{ assetId: asset.id(), value: burnValue }]) }) - 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() + it('subtracts balance for the asset from the wallet', async () => { + const { node } = await nodeTest.createSetup() + const account = await useAccountFixture(node.wallet) - await accountA.expireTransaction(tx) + const mined = await useMinerBlockFixture(node.chain, 2, account) + await expect(node.chain).toAddBlock(mined) + await node.wallet.updateHead() - // 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() - } + 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() - await expect( - nodeA.wallet.getBalance(accountA, Asset.nativeIdentifier()), - ).resolves.toMatchObject({ - confirmed: BigInt(2000000000), - unconfirmed: BigInt(2000000000), // minersFee from blockA1 + 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() - // 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 + expect(await node.wallet.getBalance(account, asset.id())).toMatchObject({ + unconfirmed: BigInt(8), + unconfirmedCount: 0, + confirmed: BigInt(8), }) }) }) @@ -1060,7 +939,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 () => { @@ -1082,7 +961,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, }) @@ -1094,7 +973,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) @@ -1164,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()) @@ -1186,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() @@ -1203,16 +1082,89 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(blockA1) await node.wallet.updateHead() - const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceBefore).toEqual(2000000000n) + const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeId()) + expect(balanceBefore.unconfirmed).toEqual(2000000000n) 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.nativeIdentifier()) - expect(balanceAfter).toEqual(1999999998n) + 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) }) }) @@ -1291,16 +1243,16 @@ describe('Accounts', () => { await expect(node.chain).toAddBlock(blockA1) await node.wallet.updateHead() - const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceBefore).toEqual(2000000000n) + const balanceBefore = await accountA.getUnconfirmedBalance(Asset.nativeId()) + expect(balanceBefore.unconfirmed).toEqual(2000000000n) const { block: blockA2 } = await useBlockWithTx(node, accountA, accountB, false) await expect(node.chain).toAddBlock(blockA2) await node.wallet.updateHead() - const balanceAfterConnect = await accountA.getUnconfirmedBalance(Asset.nativeIdentifier()) - expect(balanceAfterConnect).toEqual(1999999998n) + const balanceAfterConnect = await accountA.getUnconfirmedBalance(Asset.nativeId()) + expect(balanceAfterConnect.unconfirmed).toEqual(1999999998n) await node.chain.db.transaction(async (tx) => { await node.chain.disconnect(blockA2, tx) @@ -1308,10 +1260,52 @@ describe('Accounts', () => { await node.wallet.updateHead() - const balanceAfterDisconnect = await accountA.getUnconfirmedBalance( - Asset.nativeIdentifier(), - ) - expect(balanceAfterDisconnect).toEqual(2000000000n) + 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 bee556164a..bd02d94c9d 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]>() @@ -65,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 @@ -118,17 +108,13 @@ 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)) - - 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 = this.listAccounts().filter((account) => this.isAccountUpToDate(account)) - - await this.disconnectBlock(header, accounts) + await this.disconnectBlock(header) }) } @@ -158,7 +144,7 @@ export class Wallet { } } - get shouldRescan(): boolean { + async shouldRescan(): Promise { if (this.scan) { return false } @@ -168,7 +154,7 @@ export class Wallet { } for (const account of this.accounts.values()) { - if (!this.isAccountUpToDate(account)) { + if (!(await this.isAccountUpToDate(account))) { return true } } @@ -199,16 +185,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 @@ -243,7 +224,7 @@ export class Wallet { } } - if (this.shouldRescan && !this.scan) { + if (!this.scan && (await this.shouldRescan())) { void this.scanTransactions() } @@ -264,10 +245,6 @@ export class Wallet { this.eventLoopAbortController.abort() await this.eventLoopPromise - - if (this.walletDb.db.isOpen) { - await this.updateHeadHashes(this.chainProcessor.hash) - } } async eventLoop(): Promise { @@ -293,35 +270,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 } @@ -338,7 +288,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>() @@ -397,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 { @@ -431,19 +390,23 @@ export class Wallet { scan?.signal(blockHeader.sequence) } - await this.updateHeadHash(account, blockHeader.hash, tx) + await account.updateHeadHash(blockHeader.hash, tx) }) } } - 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)) { - await account.disconnectTransaction(transaction, tx) + await account.disconnectTransaction(header, transaction, tx) } - await this.updateHeadHash(account, header.previousBlockHash, tx) + await account.updateHeadHash(header.previousBlockHash, tx) }) } } @@ -471,43 +434,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.expirationSequence(), - 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') @@ -518,7 +444,7 @@ export class Wallet { return } - if (!this.shouldRescan) { + if (!(await this.shouldRescan())) { this.logger.info('Skipping Scan, all accounts up to date.') return } @@ -532,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 = this.headHashes.get(account.id) - Assert.isNotUndefined( - headHash, - `scanTransactions: No head hash found for ${account.displayName}`, - ) - - if (BufferUtils.equalsNullable(startHash, headHash)) { - accounts.push(account) - } else if (!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) @@ -563,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')}`, @@ -580,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( @@ -589,26 +495,7 @@ export class Wallet { undefined, false, )) { - await this.connectBlock(blockHeader, accounts, scan) - - const newRemainingAccounts = [] - - for (const remainingAccount of remainingAccounts) { - const headHash = this.headHashes.get(remainingAccount.id) - 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) { @@ -630,12 +517,14 @@ export class Wallet { async getBalance( account: Account, - assetIdentifier: Buffer, + assetId: Buffer, options?: { minimumBlockConfirmations?: number }, ): Promise<{ unconfirmedCount: number unconfirmed: bigint confirmed: bigint + blockHash: Buffer | null + sequence: number | null }> { const minimumBlockConfirmations = Math.max( options?.minimumBlockConfirmations ?? this.config.get('minimumBlockConfirmations'), @@ -652,16 +541,18 @@ export class Wallet { unconfirmed: BigInt(0), confirmed: BigInt(0), unconfirmedCount: 0, + blockHash: null, + sequence: null, } } - 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 }, @@ -674,22 +565,13 @@ export class Wallet { return } - for await (const decryptedNote of account.getUnspentNotes(assetIdentifier)) { + for await (const decryptedNote of account.getUnspentNotes(assetId)) { 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 @@ -700,28 +582,27 @@ export class Wallet { } } - async pay( + async send( memPool: MemPool, sender: Account, receives: { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: 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 +612,95 @@ export class Wallet { [], [], transactionFee, - expirationSequence, + 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 mint( + memPool: MemPool, + account: Account, + name: string, + 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, + 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 burn( + memPool: MemPool, + account: Account, + assetId: 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, + [], + [], + [{ assetId, value }], + fee, + expiration, ) const transaction = await this.postTransaction(raw) @@ -755,25 +724,25 @@ export class Wallet { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], fee: bigint, - expirationSequence: number, + expiration: number, ): Promise { const unlock = await this.createTransactionMutex.lock() 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.') } const raw = new RawTransaction() raw.spendingKey = sender.spendingKey - raw.expirationSequence = expirationSequence + raw.expiration = expiration raw.mints = mints raw.burns = burns raw.fee = fee @@ -783,7 +752,7 @@ export class Wallet { receive.publicAddress, receive.amount, receive.memo, - receive.assetIdentifier, + receive.assetId, sender.publicAddress, ) @@ -840,16 +809,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 @@ -861,15 +830,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) @@ -880,13 +845,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 } @@ -958,7 +923,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, }) @@ -1008,13 +973,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 - } - // 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 @@ -1030,7 +988,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, @@ -1116,7 +1075,7 @@ export class Wallet { return isConfirmed ? TransactionStatus.CONFIRMED : TransactionStatus.UNCONFIRMED } else { const isExpired = this.chain.verifier.isExpiredSequence( - transaction.transaction.expirationSequence(), + transaction.transaction.expiration(), headSequence, ) @@ -1143,7 +1102,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) @@ -1156,7 +1115,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 { @@ -1178,7 +1137,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) @@ -1299,7 +1258,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 @@ -1314,7 +1273,7 @@ export class Wallet { 'hex', )}. This account needs to be rescanned.`, ) - await this.updateHeadHash(account, null) + await account.updateHeadHash(null) continue } @@ -1330,7 +1289,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 @@ -1344,7 +1303,7 @@ export class Wallet { 'hex', )}. This account needs to be rescanned.`, ) - await this.updateHeadHash(account, null) + await account.updateHeadHash(null) continue } @@ -1356,8 +1315,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}`, 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/__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/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/transactionValue.test.ts b/ironfish/src/wallet/walletdb/transactionValue.test.ts index f7e8ed375a..8007079b75 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,11 +21,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) + const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: null, sequence: null, - submittedSequence: null, + submittedSequence: 123, + assetBalanceDeltas, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -37,11 +44,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeId(), -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) @@ -55,11 +67,16 @@ describe('TransactionValueEncoding', () => { const transaction = await useMinersTxFixture(nodeTest.wallet) + const assetBalanceDeltas = new BufferMap() + assetBalanceDeltas.set(Asset.nativeId(), -transaction.fee()) + const value: TransactionValue = { transaction, + timestamp: new Date(), blockHash: Buffer.alloc(32, 1), sequence: 124, - submittedSequence: null, + submittedSequence: 123, + assetBalanceDeltas, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -67,17 +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: 123, + 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.nativeId(), -transaction.fee()) + assetBalanceDeltas.set(testAsset.id(), 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.nativeId(), -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 82f27b5b65..9b58713f88 100644 --- a/ironfish/src/wallet/walletdb/transactionValue.ts +++ b/ironfish/src/wallet/walletdb/transactionValue.ts @@ -2,85 +2,110 @@ * 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_ID_LENGTH } from '@ironfish/rust-nodejs' +import { BufferMap } from 'buffer-map' import bufio from 'bufio' 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 // 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 } 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 - flags |= Number(!!submittedSequence) << 1 - flags |= Number(!!sequence) << 2 + flags |= Number(!!sequence) << 1 bw.writeU8(flags) if (blockHash) { bw.writeHash(blockHash) } - if (submittedSequence) { - bw.writeU32(submittedSequence) - } if (sequence) { bw.writeU32(sequence) } + bw.writeU32(submittedSequence) + + const assetCount = value.assetBalanceDeltas.size + bw.writeU32(assetCount) + + for (const [assetId, balanceDelta] of value.assetBalanceDeltas) { + bw.writeHash(assetId) + bw.writeBigU64(balanceDelta) + } + return bw.render() } deserialize(buffer: Buffer): TransactionValue { const reader = bufio.read(buffer, true) const transaction = new Transaction(reader.readVarBytes()) + const timestamp = new Date(reader.readU64()) const flags = reader.readU8() const hasBlockHash = flags & (1 << 0) - const hasSubmittedSequence = flags & (1 << 1) - const hasSequence = flags & (1 << 2) + const hasSequence = flags & (1 << 1) let blockHash = null if (hasBlockHash) { blockHash = reader.readHash() } - let submittedSequence = null - if (hasSubmittedSequence) { - submittedSequence = reader.readU32() - } - let sequence = null if (hasSequence) { sequence = reader.readU32() } - return { transaction, blockHash, submittedSequence, sequence } + const submittedSequence = reader.readU32() + + const assetBalanceDeltas = new BufferMap() + const assetCount = reader.readU32() + + for (let i = 0; i < assetCount; i++) { + const assetId = reader.readHash() + const balanceDelta = reader.readBigU64() + assetBalanceDeltas.set(assetId, balanceDelta) + } + + return { + transaction, + blockHash, + submittedSequence, + sequence, + timestamp, + assetBalanceDeltas, + } } getSize(value: TransactionValue): number { let size = bufio.sizeVarBytes(value.transaction.serialize()) + size += 8 size += 1 if (value.blockHash) { size += 32 } - if (value.submittedSequence) { - size += 4 - } if (value.sequence) { size += 4 } + size += 4 + size += 4 + size += value.assetBalanceDeltas.size * (ASSET_ID_LENGTH + 8) return size } } diff --git a/ironfish/src/wallet/walletdb/walletdb.ts b/ironfish/src/wallet/walletdb/walletdb.ts index debc7c3d35..3e36f83777 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, @@ -21,12 +20,14 @@ import { PrefixEncoding, StringEncoding, U32_ENCODING, + U64_ENCODING, } from '../../storage' import { StorageUtils } from '../../storage/database/utils' 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' @@ -57,7 +58,7 @@ export class WalletDB { balances: IDatabaseStore<{ key: [Account['prefix'], Buffer] - value: bigint + value: BalanceValue }> decryptedNotes: IDatabaseStore<{ @@ -95,6 +96,11 @@ export class WalletDB { value: null }> + timestampToTransactionHash: IDatabaseStore<{ + key: [Account['prefix'], number] + value: TransactionHash + }> + constructor({ files, location, @@ -133,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({ @@ -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 { @@ -202,11 +214,20 @@ export class WalletDB { await this.accounts.put(account.id, account.serialize(), tx) const nativeUnconfirmedBalance = await this.balances.get( - [account.prefix, Asset.nativeIdentifier()], + [account.prefix, Asset.nativeId()], tx, ) if (nativeUnconfirmedBalance === undefined) { - await this.saveUnconfirmedBalance(account, Asset.nativeIdentifier(), BigInt(0), tx) + await this.saveUnconfirmedBalance( + account, + Asset.nativeId(), + { + unconfirmed: BigInt(0), + blockHash: null, + sequence: null, + }, + tx, + ) } }) } @@ -278,23 +299,28 @@ 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, ) } await this.transactions.put([account.prefix, transactionHash], transactionValue, tx) + await this.timestampToTransactionHash.put( + [account.prefix, transactionValue.timestamp.getTime()], + transactionHash, + tx, + ) }) } @@ -303,11 +329,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 { @@ -357,9 +391,9 @@ export class WalletDB { return false } - const expirationSequence = transactionValue.transaction.expirationSequence() + const expiration = transactionValue.transaction.expiration() return this.pendingTransactionHashes.has( - [account.prefix, [expirationSequence, transactionHash]], + [account.prefix, [expiration, transactionHash]], tx, ) } @@ -599,32 +633,39 @@ export class WalletDB { async getUnconfirmedBalance( account: Account, - assetIdentifier: Buffer, + assetId: Buffer, tx?: IDatabaseTransaction, - ): Promise { - const unconfirmedBalance = await this.balances.get([account.prefix, assetIdentifier], tx) - return unconfirmedBalance ?? BigInt(0) + ): Promise { + const unconfirmedBalance = await this.balances.get([account.prefix, assetId], tx) + + return ( + unconfirmedBalance ?? { + unconfirmed: BigInt(0), + blockHash: null, + sequence: null, + } + ) } async *getUnconfirmedBalances( account: Account, tx?: IDatabaseTransaction, - ): AsyncGenerator<{ assetIdentifier: Buffer; balance: bigint }> { - 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, - balance: bigint, + 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 { @@ -693,12 +734,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 +747,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( @@ -736,6 +774,7 @@ export class WalletDB { this.nullifierToNoteHash, this.pendingTransactionHashes, this.decryptedNotes, + this.timestampToTransactionHash, ] for (const [accountId] of await this.accountIdsToCleanup.getAll()) { @@ -756,4 +795,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 + } + } } diff --git a/ironfish/src/webApi.ts b/ironfish/src/webApi.ts index 77fa413b95..9ebd7dbf31 100644 --- a/ironfish/src/webApi.ts +++ b/ironfish/src/webApi.ts @@ -15,9 +15,14 @@ type FaucetTransaction = { completed_at: string | null } -export type MaspTransactionTypes = 'MASP_TRANSFER' | 'MASP_BURN' | 'MASP_MINT' - -export type ApiMaspUpload = { +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' block: { hash: string @@ -27,8 +32,10 @@ export type ApiMaspUpload = { } transactions: { hash: string - type: MaspTransactionTypes - assetName: string + multiAssets: { + type: MultiAssetTypes + assetName: string + }[] }[] } @@ -78,7 +85,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 +113,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 { diff --git a/ironfish/src/workerPool/pool.ts b/ironfish/src/workerPool/pool.ts index 20ffe8b940..c428285d00 100644 --- a/ironfish/src/workerPool/pool.ts +++ b/ironfish/src/workerPool/pool.ts @@ -158,12 +158,12 @@ export class WorkerPool { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], 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/createMinersFee.ts b/ironfish/src/workerPool/tasks/createMinersFee.ts index 984721ec45..3aad179e23 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') ) @@ -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..5d83ad26ad 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, }, ], @@ -190,23 +190,23 @@ 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), ).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 = outputValuesByAssetId.get(id) || BigInt(0) + outputValuesByAssetId.set(id, value + decryptedNote.value()) } - const nativeAssetValue = outputValuesByAssetIdentifier.get(Asset.nativeIdentifier()) + const nativeAssetValue = outputValuesByAssetId.get(Asset.nativeId()) Assert.isNotUndefined(nativeAssetValue) expect(nativeAssetValue).toEqual(2000000000n - fee) - const mintedAssetValue = outputValuesByAssetIdentifier.get(asset.identifier()) + const mintedAssetValue = outputValuesByAssetId.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 79395e93f3..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' @@ -25,7 +19,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 @@ -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[] @@ -47,7 +41,7 @@ export class CreateTransactionRequest extends WorkerMessage { constructor( spendKey: string, transactionFee: bigint, - expirationSequence: number, + expiration: number, spends: { note: Buffer treeSize: number @@ -58,7 +52,7 @@ export class CreateTransactionRequest extends WorkerMessage { publicAddress: string amount: bigint memo: string - assetIdentifier: Buffer + assetId: Buffer }[], mints: MintDescription[], burns: BurnDescription[], @@ -67,7 +61,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 +72,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) { @@ -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)) } @@ -126,8 +120,8 @@ 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 expirationSequence = reader.readU64() + const transactionFee = BigIntUtils.fromBytesBE(reader.readVarBytes()) + const expiration = reader.readU64() const spendsLength = reader.readU64() const spends = [] @@ -151,32 +145,32 @@ 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 }) + const assetId = reader.readBytes(ASSET_ID_LENGTH) + receives.push({ publicAddress, amount, memo, assetId }) } const mintsLength = reader.readU64() 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 }) } const burnsLength = reader.readU64() const burns = [] for (let i = 0; i < burnsLength; i++) { - const assetIdentifier = reader.readBytes(ASSET_IDENTIFIER_LENGTH) - const value = BigIntUtils.fromBytes(reader.readVarBytes()) - burns.push({ assetIdentifier, value }) + const assetId = reader.readBytes(ASSET_ID_LENGTH) + const value = BigIntUtils.fromBytesBE(reader.readVarBytes()) + burns.push({ assetId, value }) } return new CreateTransactionRequest( spendKey, transactionFee, - expirationSequence, + expiration, spends, receives, mints, @@ -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,14 +212,13 @@ 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 ( bufio.sizeVarString(this.spendKey) + bufio.sizeVarBytes(BigIntUtils.toBytesBE(this.transactionFee)) + - 8 + // expirationSequence + 8 + // expiration 8 + // spends length spendsSize + 8 + // receives length @@ -282,10 +275,10 @@ export class CreateTransactionTask extends WorkerTask { receives, mints, burns, - expirationSequence, + expiration, }: CreateTransactionRequest): CreateTransactionResponse { const transaction = new Transaction(spendKey) - transaction.setExpirationSequence(expirationSequence) + transaction.setExpiration(expiration) for (const spend of spends) { const note = Note.deserialize(spend.note) @@ -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) diff --git a/ironfish/src/workerPool/tasks/postTransaction.test.ts b/ironfish/src/workerPool/tasks/postTransaction.test.ts index d8a60c39a9..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, @@ -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) }) }) diff --git a/yarn.lock b/yarn.lock index 1eec9e6343..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" @@ -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" @@ -4002,10 +4007,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" @@ -6812,11 +6817,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hex-array@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hex-array/-/hex-array-1.0.0.tgz#e5c24eea0383f2d9e8491f2e815bda0ce02233ae" - integrity sha1-5cJO6gOD8tnoSR8ugVvaDOAiM64= - hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -10805,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"