Skip to content

Commit c69e1e6

Browse files
committed
feat: add convertSubnetValidator tests and fix for passing
1 parent e301e0b commit c69e1e6

File tree

8 files changed

+169
-59
lines changed

8 files changed

+169
-59
lines changed

src/fixtures/pvm.ts

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ import {
2929
transferableOutputBytes,
3030
} from './avax';
3131
import {
32-
address,
33-
addressBytes,
32+
addresses,
33+
addressesBytes,
3434
id,
3535
idBytes,
3636
nodeId,
@@ -65,6 +65,7 @@ import { makeList, makeListBytes } from './utils/makeList';
6565
import type { FeeState } from '../vms/pvm';
6666
import { ConvertSubnetTx } from '../serializable/pvm/convertSubnetTx';
6767
import { ConvertSubnetValidator } from '../serializable/fxs/pvm/convertSubnetValidator';
68+
import { PChainOwner } from '../serializable/fxs/pvm/pChainOwner';
6869

6970
export const validator = () =>
7071
new Validator(nodeId(), bigIntPr(), bigIntPr(), bigIntPr());
@@ -306,33 +307,45 @@ export const transformSubnetTxBytes = () =>
306307

307308
export const convertSubnetValidator = () =>
308309
new ConvertSubnetValidator(
309-
nodeId(),
310+
// nodeId(),
311+
bytes(),
310312
bigIntPr(),
311313
bigIntPr(),
312-
signer(),
313-
outputOwner(),
314-
outputOwner(),
314+
315+
// signer(),
316+
// outputOwner(),
317+
// outputOwner(),
318+
proofOfPossession(),
319+
pChainOwner(),
320+
pChainOwner(),
315321
);
316322

317323
export const convertSubnetValidatorBytes = () =>
318324
concatBytes(
319-
nodeIdBytes(),
325+
// nodeIdBytes(),
326+
bytesBytes(),
320327
bigIntPrBytes(),
321328
bigIntPrBytes(),
322-
bytesForInt(28),
323-
signerBytes(),
324-
bytesForInt(11),
325-
outputOwnerBytes(),
326-
bytesForInt(11),
327-
outputOwnerBytes(),
329+
330+
// bytesForInt(28),
331+
// signerBytes(),
332+
// bytesForInt(11),
333+
// outputOwnerBytes(),
334+
// bytesForInt(11),
335+
// outputOwnerBytes(),
336+
337+
proofOfPossessionBytes(),
338+
pChainOwnerBytes(),
339+
pChainOwnerBytes(),
328340
);
329341

330342
export const convertSubnetTx = () =>
331343
new ConvertSubnetTx(
332344
baseTx(),
333345
id(),
334346
id(),
335-
address(),
347+
// address(),
348+
bytes(),
336349
makeList(convertSubnetValidator)(),
337350
input(),
338351
);
@@ -342,12 +355,21 @@ export const convertSubnetTxBytes = () =>
342355
baseTxbytes(),
343356
idBytes(),
344357
idBytes(),
345-
addressBytes(),
358+
// addressBytes(),
359+
bytesBytes(),
346360
makeListBytes(convertSubnetValidatorBytes)(),
347361
bytesForInt(10),
348362
inputBytes(),
349363
);
350364

365+
export const pChainOwner = () => new PChainOwner(int(), addresses()());
366+
367+
export const pChainOwnerBytes = () =>
368+
concatBytes(
369+
intBytes(), // threshold
370+
addressesBytes(),
371+
);
372+
351373
export const feeState = (): FeeState => ({
352374
capacity: 1n,
353375
excess: 1n,
Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { pack, unpack } from '../../../utils/struct';
2-
import { Codec } from '../../codec/codec';
2+
import type { Codec } from '../../codec';
33
import type { Serializable } from '../../common/types';
44
import { serializable } from '../../common/types';
5-
import { BigIntPr } from '../../primitives';
5+
import { BigIntPr, Bytes } from '../../primitives';
66
import { TypeSymbols } from '../../constants';
7-
import { emptyNodeId } from '../../../constants/zeroValue';
7+
import { ProofOfPossession } from '../../pvm';
88
import { NodeId } from '../common';
9-
import { concatBytes } from '@noble/hashes/utils';
10-
import type { SignerEmpty } from '../../pvm';
11-
import type { Signer } from '../../pvm';
12-
import type { OutputOwners } from '../secp256k1';
9+
import { PChainOwner } from './pChainOwner';
1310

1411
/**
1512
* @see https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/txs/convert_subnet_tx.go#86
@@ -19,36 +16,36 @@ export class ConvertSubnetValidator {
1916
_type = TypeSymbols.ConvertSubnetValidator;
2017

2118
constructor(
22-
public readonly nodeId: NodeId,
19+
public readonly nodeId: Bytes,
2320
public readonly weight: BigIntPr,
2421
public readonly balance: BigIntPr,
25-
public readonly signer: Signer | SignerEmpty,
22+
public readonly signer: ProofOfPossession,
2623
public readonly remainingBalanceOwner: Serializable,
2724
public readonly deactivationOwner: Serializable,
2825
) {}
2926

3027
getBalance() {
31-
return this.balance.value();
28+
return this.balance;
3229
}
3330

3431
getRemainingBalanceOwner() {
35-
return this.remainingBalanceOwner as OutputOwners;
32+
return this.remainingBalanceOwner as PChainOwner;
3633
}
3734

3835
getDeactivationOwner() {
39-
return this.deactivationOwner as OutputOwners;
36+
return this.deactivationOwner as PChainOwner;
4037
}
4138

4239
static fromNative(
4340
nodeId: string,
4441
weight: bigint,
4542
balance: bigint,
46-
signer: Signer | SignerEmpty,
47-
remainingBalanceOwner: OutputOwners,
48-
deactivationOwner: OutputOwners,
43+
signer: ProofOfPossession,
44+
remainingBalanceOwner: PChainOwner,
45+
deactivationOwner: PChainOwner,
4946
) {
5047
return new ConvertSubnetValidator(
51-
NodeId.fromString(nodeId),
48+
new Bytes(NodeId.fromString(nodeId).toBytes()),
5249
new BigIntPr(weight),
5350
new BigIntPr(balance),
5451
signer,
@@ -69,7 +66,11 @@ export class ConvertSubnetValidator {
6966
remainingBalanceOwner,
7067
deactivationOwner,
7168
rest,
72-
] = unpack(bytes, [NodeId, BigIntPr, BigIntPr, Codec, Codec, Codec], codec);
69+
] = unpack(
70+
bytes,
71+
[Bytes, BigIntPr, BigIntPr, ProofOfPossession, PChainOwner, PChainOwner],
72+
codec,
73+
);
7374

7475
return [
7576
new ConvertSubnetValidator(
@@ -85,11 +86,16 @@ export class ConvertSubnetValidator {
8586
}
8687

8788
toBytes(codec: Codec) {
88-
return concatBytes(
89-
pack([this.nodeId, this.weight, this.balance], codec),
90-
codec.PackPrefix(this.signer),
91-
codec.PackPrefix(this.remainingBalanceOwner),
92-
codec.PackPrefix(this.deactivationOwner),
89+
return pack(
90+
[
91+
this.nodeId,
92+
this.weight,
93+
this.balance,
94+
this.signer,
95+
this.remainingBalanceOwner,
96+
this.deactivationOwner,
97+
],
98+
codec,
9399
);
94100
}
95101

@@ -98,9 +104,12 @@ export class ConvertSubnetValidator {
98104
throw new Error('Weight must be greater than 0');
99105
}
100106

101-
if (this.nodeId === emptyNodeId) {
102-
throw new Error('Node ID must be non-empty');
103-
}
107+
// const nodeId = new NodeId(this.nodeId.toBytesWithoutLength());
108+
109+
// TODO: Properly add this logic back with new types.
110+
// if (this.nodeId === emptyNodeId) {
111+
// throw new Error('Node ID must be non-empty');
112+
// }
104113
return true;
105114
}
106115
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { pChainOwner, pChainOwnerBytes } from '../../../fixtures/pvm';
2+
import { testSerialization } from '../../../fixtures/utils/serializable';
3+
import { PChainOwner } from './pChainOwner';
4+
5+
testSerialization('PChainOwner', PChainOwner, pChainOwner, pChainOwnerBytes);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { concatBytes } from '@noble/hashes/utils';
2+
import { toListStruct } from '../../../utils/serializeList';
3+
import { pack, unpack } from '../../../utils/struct';
4+
import { serializable } from '../../common/types';
5+
import { Int } from '../../primitives';
6+
import { Address } from '../common/address';
7+
import { TypeSymbols } from '../../constants';
8+
import type { Codec } from '../../codec';
9+
10+
/**
11+
* @see https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/warp/message/register_subnet_validator.go
12+
*/
13+
@serializable()
14+
export class PChainOwner {
15+
_type = TypeSymbols.PChainOwner;
16+
17+
constructor(
18+
public readonly threshold: Int,
19+
public readonly addresses: Address[],
20+
) {}
21+
22+
getAddresses() {
23+
return this.addresses;
24+
}
25+
26+
static fromBytes(bytes: Uint8Array, codec: Codec): [PChainOwner, Uint8Array] {
27+
const [threshold, addresses, remaining] = unpack(
28+
bytes,
29+
[Int, toListStruct(Address)],
30+
codec,
31+
);
32+
return [new PChainOwner(threshold, addresses), remaining];
33+
}
34+
35+
toBytes(codec: Codec) {
36+
return concatBytes(pack([this.threshold, this.addresses], codec));
37+
}
38+
39+
static fromNative(addresses: readonly Uint8Array[], threshold = 1) {
40+
return new PChainOwner(
41+
new Int(threshold),
42+
addresses.map((addr) => new Address(addr)),
43+
);
44+
}
45+
}

src/serializable/pvm/convertSubnetTx.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import { Codec } from '../codec/codec';
66
import type { Serializable } from '../common/types';
77
import { serializable } from '../common/types';
88
import { TypeSymbols } from '../constants';
9-
import { Address, Id } from '../fxs/common';
9+
import { Id } from '../fxs/common';
1010
import { ConvertSubnetValidator } from '../fxs/pvm/convertSubnetValidator';
11+
import { Bytes } from '../primitives';
1112
import { AbstractSubnetTx } from './abstractSubnetTx';
1213

1314
@serializable()
@@ -18,7 +19,7 @@ export class ConvertSubnetTx extends AbstractSubnetTx {
1819
public readonly baseTx: BaseTx,
1920
public readonly subnetID: Id,
2021
public readonly chainID: Id,
21-
public readonly address: Address,
22+
public readonly address: Bytes,
2223
public readonly validators: ConvertSubnetValidator[],
2324
public readonly subnetAuth: Serializable,
2425
) {
@@ -36,7 +37,7 @@ export class ConvertSubnetTx extends AbstractSubnetTx {
3637
const [baseTx, subnetID, chainID, address, validators, subnetAuth, rest] =
3738
unpack(
3839
bytes,
39-
[BaseTx, Id, Id, Address, toListStruct(ConvertSubnetValidator), Codec],
40+
[BaseTx, Id, Id, Bytes, toListStruct(ConvertSubnetValidator), Codec],
4041
codec,
4142
);
4243
return [

src/vms/pvm/etna-builder/builder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from '../../../constants/networkIDs';
1212
import type { TransferOutput } from '../../../serializable';
1313
import {
14-
Address,
1514
Input,
1615
NodeId,
1716
OutputOwners,
@@ -1387,7 +1386,7 @@ export const newConvertSubnetTx: TxBuilderFn<NewConvertSubnetTxProps> = (
13871386
for (const validator of sortedValidators) {
13881387
toBurn.set(
13891388
context.avaxAssetID,
1390-
(toBurn.get(context.avaxAssetID) ?? 0n) + validator.getBalance(),
1389+
(toBurn.get(context.avaxAssetID) ?? 0n) + validator.getBalance().value(),
13911390
);
13921391
}
13931392

@@ -1434,7 +1433,8 @@ export const newConvertSubnetTx: TxBuilderFn<NewConvertSubnetTxProps> = (
14341433
),
14351434
Id.fromString(subnetId),
14361435
Id.fromString(chainId),
1437-
new Address(address),
1436+
// new Address(address),
1437+
new Bytes(address),
14381438
sortedValidators,
14391439
Input.fromNative(subnetAuth),
14401440
),

0 commit comments

Comments
 (0)