Skip to content

Commit

Permalink
ifl-744 add test/updates for calculating raw transaction size
Browse files Browse the repository at this point in the history
  • Loading branch information
jowparks committed Apr 28, 2023
1 parent 621650a commit 31bccef
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 18 deletions.
6 changes: 0 additions & 6 deletions ironfish-rust-nodejs/src/structs/note_encrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ pub const ENCRYPTED_NOTE_PLAINTEXT_LENGTH: u32 = ENCRYPTED_NOTE_SIZE as u32 + MA
#[napi]
pub const ENCRYPTED_NOTE_LENGTH: u32 =
NOTE_ENCRYPTION_KEY_LENGTH + ENCRYPTED_NOTE_PLAINTEXT_LENGTH + 96;
// 32 value commitment
//+ 32 note commitment
//+ 32 ephemeral public key
//+ 120 encrypted note
//+ 80 note encryption keys
//= 296 bytes

#[napi(js_name = "NoteEncrypted")]
pub struct NativeNoteEncrypted {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,44 @@
"publicAddress": "c96cc22b0a0e958c055eb6b357418e4a779b90f85750dfc9e618b36688eab944",
"createdAt": null
}
],
"RawTransaction should equal": [
{
"version": 2,
"id": "fb52a88e-3e8c-466f-bd34-c4dd7d75532d",
"name": "test",
"spendingKey": "4c3d51b6596832c4dc539aa5d6ecd036d338fbc21b6a64d26a7ccc838a87a000",
"viewKey": "a33795eafe7851f52fc4bfbe2a2ff60ad7bb409d6cc4bc19996a4d941a4f8cc526aee6da70f63bcac90ec4bd678b16bbe64299bed09da120bf28e321d3aab1aa",
"incomingViewKey": "cee508b90f3963e4099798a355ed0da0e123b193ff0f7cd6b7b4596caadf1e02",
"outgoingViewKey": "79f6d37e22fd3d9ca88b0d26a1dedebb4ef7e89fa31ac7632c1ee06a3f30628a",
"publicAddress": "6b971b1e7217ff4fe81c457c65d85ce8d7723fa52061a2194041efb556a99c19",
"createdAt": null
},
{
"header": {
"sequence": 2,
"previousBlockHash": "88B6FA8D745A4E53BDA001318E60B04EE2E4EE06A38095688D58049CB6F15ACA",
"noteCommitment": {
"type": "Buffer",
"data": "base64:9DdIBOwIdxNRoPgyIcDSxyCQwTV2oALwWD2w/K2dPEM="
},
"transactionCommitment": {
"type": "Buffer",
"data": "base64:v2mDXwx+HgVnlnZwDaTJfEzBSmmEHpHcvjPYjXbGJOg="
},
"target": "883423532389192164791648750371459257913741948437809479060803100646309888",
"randomness": "0",
"timestamp": 1682541250417,
"graffiti": "0000000000000000000000000000000000000000000000000000000000000000",
"noteSize": 4,
"work": "0"
},
"transactions": [
{
"type": "Buffer",
"data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAqZz03fllUAxM/C47JUjjmcVrt8H1IKtQY662BbzJsHOBBsM9VGn0kEUU/Da9UFfHfzW+n3Zud2xziSEG76e0SpoXl66oysLTkLvWcTycsumpWYVw5JNcPU7SBt2HACwfKN4awPDtSihU8dsjIbE+NBdMfLF6KMdBKjTC5fykZl0AjgmGflqizCNi3uucrM2Nm3HYjXIJvdv/R3AXA4TZD8BhduPvJEagPzLOcFxDwWuKLBAyjSrWU5SOmwrcqvJtvtJCwbIFNiUOIr5CO09PL+5ko/oVP4eZ2EHYNoKZRX0T8iZvPxVLuVIDlocEOn8zt2th/D2Erz1YHVbMw6B2VVoe9pmeJqQwwmI8yg1doZxhvPw8I7YjBPzwSGNQQp9x9vuW/n4O+bcopYA56O+eepc1r8CWU7+qmP9WjBCCskhK745L4B7hI3MTNwAyJ96m4S+PkHydl7m6QIZYIUGCLuYZSXKMd+QFXQJwfiyE8P+0I+gTtjaglmboCIZNCTyLbI4re2Xa2SXzqQk9agNVcyKHqG1j0D4qMVDBMCuvuhVCyFjBIy2yzQ9MCbV4mkE9AEsDjBdn4ehLB6Pi82M43awCFE0SblLFcEjryLy3OoZ3pK3IBVhliUlyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwxGhqNFhJQIu38oTMYoOTmInFtc4F/l21An0Z112s1dWXZ6OIGS8Xsdi8KJwm8vzAtBo7osJ/1NFTnjYT9uznAw=="
}
]
}
]
}
4 changes: 4 additions & 0 deletions ironfish/src/primitives/rawTransaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ describe('RawTransaction', () => {
const mintedValue = valuesByAsset.get(asset.id())
Assert.isNotUndefined(mintedValue)
expect(mintedValue).toEqual(1n)

// should have same size for posted transaction and estimated size from raw transaction
const serializedPost = posted.serialize()
expect(raw.postedSize(account.publicAddress)).toEqual(serializedPost.byteLength)
})

it('should throw an error if the max mint value is exceeded', async () => {
Expand Down
43 changes: 37 additions & 6 deletions ironfish/src/primitives/rawTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import {
AMOUNT_VALUE_LENGTH,
ASSET_LENGTH,
generateKeyFromPrivateKey,
PROOF_LENGTH,
Transaction as NativeTransaction,
TRANSACTION_EXPIRATION_LENGTH,
TRANSACTION_FEE_LENGTH,
TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH,
TRANSACTION_SIGNATURE_LENGTH,
} from '@ironfish/rust-nodejs'
import { Asset, ASSET_ID_LENGTH } from '@ironfish/rust-nodejs'
import bufio from 'bufio'
import { Witness } from '../merkletree'
import { NoteHasher } from '../merkletree/hasher'
import { Side } from '../merkletree/merkletree'
import { CurrencyUtils } from '../utils/currency'
import { AssetBalances } from '../wallet/assetBalances'
import { BurnDescription } from './burnDescription'
import { Note } from './note'
import {
Expand Down Expand Up @@ -54,17 +58,44 @@ export class RawTransaction {
>
}[] = []

size(): number {
postedSize(publicAddress: string): number {
let size = 0
size += 1 // version
size += 8 // spends length
size += 8 // notes length
size += 8 // fee
size += 4 // expiration
size += 64 // signature
size += 8 // mints length
size += 8 // burns length
size += TRANSACTION_FEE_LENGTH // fee
size += TRANSACTION_EXPIRATION_LENGTH // expiration
size += TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH // public key randomness
size += this.spends.length * SPEND_SERIALIZED_SIZE_IN_BYTE
size += this.outputs.length * NOTE_ENCRYPTED_SERIALIZED_SIZE_IN_BYTE
size += this.mints.length * (ASSET_LENGTH + 8)
size +=
this.mints.length *
(PROOF_LENGTH + ASSET_LENGTH + AMOUNT_VALUE_LENGTH + TRANSACTION_SIGNATURE_LENGTH)
size += this.burns.length * (ASSET_ID_LENGTH + 8)
size += this.spends.length * SPEND_SERIALIZED_SIZE_IN_BYTE
size += TRANSACTION_SIGNATURE_LENGTH // signature

// Each asset might have a change note, which would need to be accounted for
const assetTotals = new AssetBalances()
for (const mint of this.mints) {
const asset = new Asset(publicAddress, mint.name, mint.metadata)
assetTotals.increment(asset.id(), mint.value)
}
for (const burn of this.burns) {
assetTotals.increment(burn.assetId, -burn.value)
}
for (const spend of this.spends) {
assetTotals.increment(spend.note.assetId(), -spend.note.value())
}
for (const output of this.outputs) {
assetTotals.increment(output.note.assetId(), output.note.value())
}
for (const [, value] of assetTotals) {
if (value !== 0n) {
size += NOTE_ENCRYPTED_SERIALIZED_SIZE_IN_BYTE
}
}
return size
}

Expand Down
2 changes: 1 addition & 1 deletion ironfish/src/primitives/spend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { Nullifier } from './nullifier'

export const SPEND_SERIALIZED_SIZE_IN_BYTE = 388
export const SPEND_SERIALIZED_SIZE_IN_BYTE = 356

export interface Spend {
nullifier: Nullifier
Expand Down
6 changes: 3 additions & 3 deletions ironfish/src/primitives/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Transaction {

// spend description
this.spends = Array.from({ length: _spendsLength }, () => {
// proof
// proof 192
reader.seek(PROOF_LENGTH)
// value commitment
reader.seek(32)
Expand All @@ -68,10 +68,10 @@ export class Transaction {
const treeSize = reader.readU32() // 4
const nullifier = reader.readHash() // 32

// signature
// signature 64
reader.seek(TRANSACTION_SIGNATURE_LENGTH)

// total serialized size: 192 + 32 + 32 + 32 + 4 + 32 + 64 = 388 bytes
// total serialized size: 192 + 32 + 32 + 4 + 32 + 64 = 356 bytes
return {
size: treeSize,
commitment: rootHash,
Expand Down
4 changes: 2 additions & 2 deletions ironfish/src/wallet/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ export class Wallet {
}

if (options.feeRate) {
raw.fee = getFee(options.feeRate, raw.size())
raw.fee = getFee(options.feeRate, raw.postedSize(options.account.publicAddress))
}

await this.fund(raw, {
Expand All @@ -928,7 +928,7 @@ export class Wallet {
})

if (options.feeRate) {
raw.fee = getFee(options.feeRate, raw.size())
raw.fee = getFee(options.feeRate, raw.postedSize(options.account.publicAddress))
raw.spends = []

await this.fund(raw, {
Expand Down

0 comments on commit 31bccef

Please sign in to comment.