From e442228dd4ed94ddb3230a585156f2501fe2d79f Mon Sep 17 00:00:00 2001 From: Eric Taylor Date: Thu, 24 Oct 2024 12:07:03 -0600 Subject: [PATCH] fix: circular dependencies Closes #873. --- .../fxs/pvm/convertSubnetValidator.ts | 2 +- src/serializable/pvm/increaseBalanceTx.ts | 2 +- src/serializable/pvm/validator.spec.ts | 9 ++- src/utils/addressMap.spec.ts | 71 +++++++++++++++++- src/utils/addressMap.ts | 43 ++++++++++- src/utils/builderUtils.ts | 2 +- src/utils/matchOwners.spec.ts | 73 ------------------- src/utils/matchOwners.ts | 43 ----------- src/vms/evm/builder.ts | 3 +- src/vms/pvm/etna-builder/builder.ts | 2 +- src/vms/pvm/txs/fee/complexity.ts | 2 +- .../utils/verifySignaturesMatch.ts | 4 +- 12 files changed, 127 insertions(+), 129 deletions(-) delete mode 100644 src/utils/matchOwners.spec.ts delete mode 100644 src/utils/matchOwners.ts diff --git a/src/serializable/fxs/pvm/convertSubnetValidator.ts b/src/serializable/fxs/pvm/convertSubnetValidator.ts index 1b8cc88f1..e10e0ef94 100644 --- a/src/serializable/fxs/pvm/convertSubnetValidator.ts +++ b/src/serializable/fxs/pvm/convertSubnetValidator.ts @@ -3,7 +3,7 @@ import type { Codec } from '../../codec'; import { serializable } from '../../common/types'; import { BigIntPr, Bytes } from '../../primitives'; import { TypeSymbols } from '../../constants'; -import { ProofOfPossession } from '../../pvm'; +import { ProofOfPossession } from '../../pvm/proofOfPossession'; import { NodeId } from '../common'; import { PChainOwner } from './pChainOwner'; diff --git a/src/serializable/pvm/increaseBalanceTx.ts b/src/serializable/pvm/increaseBalanceTx.ts index b72431617..a6df5452a 100644 --- a/src/serializable/pvm/increaseBalanceTx.ts +++ b/src/serializable/pvm/increaseBalanceTx.ts @@ -1,5 +1,5 @@ import { pack, unpack } from '../../utils/struct'; -import { BaseTx } from '../avax'; +import { BaseTx } from '../avax/baseTx'; import type { Codec } from '../codec'; import { serializable } from '../common/types'; import { TypeSymbols } from '../constants'; diff --git a/src/serializable/pvm/validator.spec.ts b/src/serializable/pvm/validator.spec.ts index b138e1866..2e60b611d 100644 --- a/src/serializable/pvm/validator.spec.ts +++ b/src/serializable/pvm/validator.spec.ts @@ -1,5 +1,12 @@ +import { testPVMCodec } from '../../fixtures/codec'; import { validator, validatorBytes } from '../../fixtures/pvm'; import { testSerialization } from '../../fixtures/utils/serializable'; import { Validator } from './validator'; -testSerialization('Validator', Validator, validator, validatorBytes); +testSerialization( + 'Validator', + Validator, + validator, + validatorBytes, + testPVMCodec, +); diff --git a/src/utils/addressMap.spec.ts b/src/utils/addressMap.spec.ts index 2f8b69c45..fecdb57c9 100644 --- a/src/utils/addressMap.spec.ts +++ b/src/utils/addressMap.spec.ts @@ -1,7 +1,10 @@ import { jest } from '@jest/globals'; import { address } from '../fixtures/common'; import { Address } from '../serializable/fxs/common'; -import { AddressMap, AddressMaps } from './addressMap'; +import { AddressMap, AddressMaps, matchOwners } from './addressMap'; +import { addressesFromBytes } from './addressesFromBytes'; +import { OutputOwners } from '../serializable'; +import { hexToBuffer } from './buffer'; describe('AddressMap', () => { const testAddress1 = address(); @@ -240,3 +243,69 @@ describe('AddressMaps', () => { ]); }); }); + +describe('matchOwners', () => { + it('matches owners', () => { + const owner1 = address(); + const owner2 = Address.fromHex('7db97c7cece249c2b98bdc0226cc4c2a57bf52fc'); + const ownerAddresses: Uint8Array[] = [owner1.toBytes(), owner2.toBytes()]; + const goodOwner = OutputOwners.fromNative(ownerAddresses, 0n, 1); + const threasholdTooHigh = OutputOwners.fromNative(ownerAddresses, 0n, 5); + const wrongOwner = OutputOwners.fromNative( + [hexToBuffer('0x12345123451234512345')], + 0n, + 5, + ); + const locked = OutputOwners.fromNative( + ownerAddresses, + 9999999999999999999999999999999999n, + 5, + ); + + const specs = [ + { + testCase: goodOwner, + expectedSigIndices: [0], + expectedAddressMap: new AddressMap([[owner1, 0]]), + }, + { + testCase: threasholdTooHigh, + expectedSigIndices: undefined, + expectedAddressMap: undefined, + }, + { + testCase: locked, + expectedSigIndices: undefined, + expectedAddressMap: undefined, + }, + { + testCase: wrongOwner, + expectedSigIndices: undefined, + expectedAddressMap: undefined, + }, + { + testCase: goodOwner, + sigindices: [1], + expectedSigIndices: [1], + expectedAddressMap: new AddressMap([[owner2, 1]]), + }, + { + testCase: goodOwner, + sigindices: [2], + expectedSigIndices: undefined, + expectedAddressMap: undefined, + }, + ]; + + specs.forEach((spec) => { + const result = matchOwners( + spec.testCase, + addressesFromBytes(ownerAddresses), + 50n, + spec.sigindices, + ); + expect(result?.sigIndicies).toEqual(spec.expectedSigIndices); + expect(result?.addressMap).toEqual(spec.expectedAddressMap); + }); + }); +}); diff --git a/src/utils/addressMap.ts b/src/utils/addressMap.ts index b1bba060a..8e3deb5a2 100644 --- a/src/utils/addressMap.ts +++ b/src/utils/addressMap.ts @@ -1,9 +1,48 @@ -import type { TransferableInput } from '../serializable'; +import type { OutputOwners, TransferableInput } from '../serializable'; import type { Utxo } from '../serializable/avax/utxo'; import { Address } from '../serializable/fxs/common'; import { addressesFromBytes } from './addressesFromBytes'; import { hexToBuffer } from './buffer'; -import { matchOwners } from './matchOwners'; + +export type MatchOwnerResult = { + sigIndicies: number[]; + addressMap: AddressMap; +}; +export const matchOwners = ( + owners: OutputOwners, + inputAddrs: Address[], + minIssuanceTime: bigint, + sigindices?: number[], +): MatchOwnerResult | undefined => { + if (owners.locktime.value() > minIssuanceTime) { + return undefined; + } + + const inputAddrSet = new Set(inputAddrs.map((a) => a.toString())); + const addressMap = owners.addrs.reduce((agg, addr, i) => { + if ( + agg.size() < owners.threshold.value() && + inputAddrSet.has(addr.value()) + ) { + // only add actual signer addresses if sigindices are known + if (sigindices?.length && !sigindices.includes(i)) { + return agg; + } + + return agg.set(addr, i); + } + return agg; + }, new AddressMap()); + + if (addressMap.size() < owners.threshold.value()) { + return undefined; + } + + return { + sigIndicies: Array.from(addressMap.values()), + addressMap: addressMap, + }; +}; export class AddressMap { constructor(initialData: [Address, number][] = []) { diff --git a/src/utils/builderUtils.ts b/src/utils/builderUtils.ts index d60be0387..2d8b16c87 100644 --- a/src/utils/builderUtils.ts +++ b/src/utils/builderUtils.ts @@ -1,7 +1,7 @@ import { TransferableInput } from '../serializable/avax'; import type { Utxo } from '../serializable/avax/utxo'; +import { matchOwners } from './addressMap'; import { addressesFromBytes } from './addressesFromBytes'; -import { matchOwners } from './matchOwners'; import { isTransferOut } from './typeGuards'; type GetImportedInputsFromUtxosOutput = { diff --git a/src/utils/matchOwners.spec.ts b/src/utils/matchOwners.spec.ts deleted file mode 100644 index 63f77ec64..000000000 --- a/src/utils/matchOwners.spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Address } from '../serializable/fxs/common'; -import { address } from '../fixtures/common'; -import { OutputOwners } from '../serializable/fxs/secp256k1'; -import { addressesFromBytes } from './addressesFromBytes'; -import { AddressMap } from './addressMap'; -import { hexToBuffer } from './buffer'; -import { matchOwners } from './matchOwners'; - -describe('matchOwners', () => { - it('matches owners', () => { - const owner1 = address(); - const owner2 = Address.fromHex('7db97c7cece249c2b98bdc0226cc4c2a57bf52fc'); - const ownerAddresses: Uint8Array[] = [owner1.toBytes(), owner2.toBytes()]; - const goodOwner = OutputOwners.fromNative(ownerAddresses, 0n, 1); - const threasholdTooHigh = OutputOwners.fromNative(ownerAddresses, 0n, 5); - const wrongOwner = OutputOwners.fromNative( - [hexToBuffer('0x12345123451234512345')], - 0n, - 5, - ); - const locked = OutputOwners.fromNative( - ownerAddresses, - 9999999999999999999999999999999999n, - 5, - ); - - const specs = [ - { - testCase: goodOwner, - expectedSigIndices: [0], - expectedAddressMap: new AddressMap([[owner1, 0]]), - }, - { - testCase: threasholdTooHigh, - expectedSigIndices: undefined, - expectedAddressMap: undefined, - }, - { - testCase: locked, - expectedSigIndices: undefined, - expectedAddressMap: undefined, - }, - { - testCase: wrongOwner, - expectedSigIndices: undefined, - expectedAddressMap: undefined, - }, - { - testCase: goodOwner, - sigindices: [1], - expectedSigIndices: [1], - expectedAddressMap: new AddressMap([[owner2, 1]]), - }, - { - testCase: goodOwner, - sigindices: [2], - expectedSigIndices: undefined, - expectedAddressMap: undefined, - }, - ]; - - specs.forEach((spec) => { - const result = matchOwners( - spec.testCase, - addressesFromBytes(ownerAddresses), - 50n, - spec.sigindices, - ); - expect(result?.sigIndicies).toEqual(spec.expectedSigIndices); - expect(result?.addressMap).toEqual(spec.expectedAddressMap); - }); - }); -}); diff --git a/src/utils/matchOwners.ts b/src/utils/matchOwners.ts deleted file mode 100644 index 2a4bd55c6..000000000 --- a/src/utils/matchOwners.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { Address } from '../serializable/fxs/common'; -import type { OutputOwners } from '../serializable/fxs/secp256k1'; -import { AddressMap } from './addressMap'; - -export type MatchOwnerResult = { - sigIndicies: number[]; - addressMap: AddressMap; -}; -export const matchOwners = ( - owners: OutputOwners, - inputAddrs: Address[], - minIssuanceTime: bigint, - sigindices?: number[], -): MatchOwnerResult | undefined => { - if (owners.locktime.value() > minIssuanceTime) { - return undefined; - } - - const inputAddrSet = new Set(inputAddrs.map((a) => a.toString())); - const addressMap = owners.addrs.reduce((agg, addr, i) => { - if ( - agg.size() < owners.threshold.value() && - inputAddrSet.has(addr.value()) - ) { - // only add actual signer addresses if sigindices are known - if (sigindices?.length && !sigindices.includes(i)) { - return agg; - } - - return agg.set(addr, i); - } - return agg; - }, new AddressMap()); - - if (addressMap.size() < owners.threshold.value()) { - return undefined; - } - - return { - sigIndicies: Array.from(addressMap.values()), - addressMap: addressMap, - }; -}; diff --git a/src/vms/evm/builder.ts b/src/vms/evm/builder.ts index 10629beb8..ba9e2605a 100644 --- a/src/vms/evm/builder.ts +++ b/src/vms/evm/builder.ts @@ -9,9 +9,8 @@ import { } from '../../serializable/fxs/secp256k1'; import { BigIntPr, Int } from '../../serializable/primitives'; import { addressesFromBytes } from '../../utils'; -import { AddressMap, AddressMaps } from '../../utils/addressMap'; +import { AddressMap, AddressMaps, matchOwners } from '../../utils/addressMap'; import { costCorethTx } from '../../utils/costs'; -import { matchOwners } from '../../utils/matchOwners'; import { compareEVMOutputs } from '../../utils/sort'; import { EVMUnsignedTx } from '../common/evmUnsignedTx'; import type { UnsignedTx } from '../common/unsignedTx'; diff --git a/src/vms/pvm/etna-builder/builder.ts b/src/vms/pvm/etna-builder/builder.ts index 9572c489a..749bb98fa 100644 --- a/src/vms/pvm/etna-builder/builder.ts +++ b/src/vms/pvm/etna-builder/builder.ts @@ -49,8 +49,8 @@ import { addressesFromBytes, bytesCompare, isTransferOut, + matchOwners, } from '../../../utils'; -import { matchOwners } from '../../../utils/matchOwners'; import { compareTransferableOutputs } from '../../../utils/sort'; import { baseTxUnsafePvm, UnsignedTx } from '../../common'; import { addDimensions, createDimensions } from '../../common/fees/dimensions'; diff --git a/src/vms/pvm/txs/fee/complexity.ts b/src/vms/pvm/txs/fee/complexity.ts index ad52e1740..64b2da25d 100644 --- a/src/vms/pvm/txs/fee/complexity.ts +++ b/src/vms/pvm/txs/fee/complexity.ts @@ -48,7 +48,7 @@ import { isStakeableLockIn, isStakeableLockOut, isTransferOut, -} from '../../../../utils'; +} from '../../../../utils/typeGuards'; import type { Dimensions } from '../../../common/fees/dimensions'; import { FeeDimensions, diff --git a/src/vms/utils/calculateSpend/utils/verifySignaturesMatch.ts b/src/vms/utils/calculateSpend/utils/verifySignaturesMatch.ts index 67f13ebd5..a01a1468b 100644 --- a/src/vms/utils/calculateSpend/utils/verifySignaturesMatch.ts +++ b/src/vms/utils/calculateSpend/utils/verifySignaturesMatch.ts @@ -1,6 +1,6 @@ -import type { MatchOwnerResult } from '../../../../utils/matchOwners'; -import { matchOwners } from '../../../../utils/matchOwners'; import type { Address, TransferOutput } from '../../../../serializable'; +import type { MatchOwnerResult } from '../../../../utils'; +import { matchOwners } from '../../../../utils'; export type verifySigMatchItem = Required<{ sigData: MatchOwnerResult;