Skip to content

Commit

Permalink
add validator, add validatorTX, subnetValidator (#88)
Browse files Browse the repository at this point in the history
* wip

* xchain

* rename to avm

* nits

* wip

* wip

* add test
  • Loading branch information
hiimoliverwang authored Jun 30, 2022
1 parent 1bc2617 commit 8710224
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 43 deletions.
34 changes: 33 additions & 1 deletion .vscode/testing.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,41 @@
"scope": "typescript",
"prefix": "testser",
"body": [
"testSerialization('${TM_FILENAME/(.)(.+?)\\.(.+)/${1:/upcase}$2/}', ${TM_FILENAME/(.)(.+?)\\.(.+)/${1:/upcase}$2/}, ${TM_FILENAME/\\.(.+)//g}, ${TM_FILENAME/\\.(.+)//g}Bytes);",
"testSerialization('${TM_FILENAME/(.)(.+?)\\.(.+)/${1:/upcase}$2/}', ${TM_FILENAME/(.)(.+?)\\.(.+)/${1:/upcase}$2/}, ${TM_FILENAME/\\.(.+)//g}, ${TM_FILENAME/\\.(.+)//g}Bytes, testPVMCodec);",
"$2"
],
"description": "Log output to console"
},
"newtx": {
"scope": "typescript",
"prefix": "newtx",
"body": [
"import type { Codec } from '../../codec/codec';",
"import { serializable } from '../../common/types';",
"import { concatBytes } from '../../utils/buffer';",
"import { unpack } from '../../utils/struct';",
"",
"const _symbol = Symbol('pvm.${1:TxName}');",
"",
"/**",
" * @see ",
" */",
"@serializable()",
"export class $1 {",
" _type = _symbol;",
"",
" constructor(public readonly ) {}",
"",
" static fromBytes(bytes: Uint8Array, codec: Codec): [$1, Uint8Array] {",
" const [$2, rest] = unpack(bytes, [], codec);",
" return [new $1($2), rest];",
" }",
"",
" toBytes(codec: Codec) {",
" return concatBytes();",
" }",
"}"
],
"description": "new tx type"
}
}
3 changes: 3 additions & 0 deletions src/fixtures/codec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Short } from '../primitives';
import { getManager } from '../vms/avm/codec';
import { codec } from '../vms/pvm/codec';

// Check for circular imports in the fx type
// registries if tests are throwing errors

export const testManager = getManager;

export const testCodec = () => testManager().getCodecForVersion(new Short(0));

export const testPVMCodec = () => codec;
42 changes: 42 additions & 0 deletions src/fixtures/pvm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { concatBytes } from '@noble/hashes/utils';
import { SubnetValidator } from '../vms/pvm/subnetValidator';
import { AddValidatorTx } from '../vms/pvm/addValidatorTx';
import { Validator } from '../vms/pvm/validator';
import {
baseTx,
baseTxbytes,
transferableOutput,
transferableOutputBytes,
} from './avax';
import { id, idBytes } from './common';
import { bigIntPr, bigIntPrBytes, int, intBytes } from './primitives';
import { outputOwner, outputOwnerBytes } from './secp256k1';
import { makeList, makeListBytes } from './utils/makeList';

export const validator = () =>
new Validator(id(), bigIntPr(), bigIntPr(), bigIntPr());

export const validatorBytes = () =>
concatBytes(idBytes(), bigIntPrBytes(), bigIntPrBytes(), bigIntPrBytes());

export const addValidatorTx = () =>
new AddValidatorTx(
baseTx(),
validator(),
makeList(transferableOutput)(),
outputOwner(),
int(),
);
export const addValidatorTxBytes = () =>
concatBytes(
baseTxbytes(),
validatorBytes(),
makeListBytes(transferableOutputBytes)(),
outputOwnerBytes(),
intBytes(),
);

export const subnetValidator = () => new SubnetValidator(validator(), id());

export const subnetValidatorBytes = () =>
concatBytes(validatorBytes(), idBytes());
13 changes: 4 additions & 9 deletions src/fixtures/utils/serializable.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Codec } from '../../codec';
import type { Serializable, SerializableStatic } from '../../common/types';
import { testCodec } from '../codec';

Expand All @@ -6,25 +7,19 @@ export const testSerialization = (
entity: SerializableStatic,
entityFixture: () => Serializable,
bytesFixture: () => Uint8Array,
options?: {
skipToBytes: boolean;
},
codec: () => Codec = testCodec,
) => {
describe(name, () => {
it('deserializes correctly', () => {
const [output, remainder] = entity.fromBytes(bytesFixture(), testCodec());
const [output, remainder] = entity.fromBytes(bytesFixture(), codec());
expect(output).toStrictEqual(entityFixture());
expect(remainder).toStrictEqual(new Uint8Array());
});
});

if (options?.skipToBytes) return;

describe(name, () => {
it('serializes correctly', () => {
expect(entityFixture().toBytes(testCodec())).toStrictEqual(
bytesFixture(),
);
expect(entityFixture().toBytes(codec())).toStrictEqual(bytesFixture());
});
});
};
12 changes: 12 additions & 0 deletions src/vms/pvm/addValidatorTx.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { testPVMCodec } from '../../fixtures/codec';
import { addValidatorTx, addValidatorTxBytes } from '../../fixtures/pvm';
import { testSerialization } from '../../fixtures/utils/serializable';
import { AddValidatorTx } from './addValidatorTx';

testSerialization(
'AddValidatorTx',
AddValidatorTx,
addValidatorTx,
addValidatorTxBytes,
testPVMCodec,
);
56 changes: 56 additions & 0 deletions src/vms/pvm/addValidatorTx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { Codec } from '../../codec/codec';
import { serializable } from '../../common/types';
import { BaseTx, TransferableOutput } from '../../components/avax';
import { OutputOwners } from '../../fxs/secp256k1';
import { Int } from '../../primitives';
import { concatBytes } from '../../utils/buffer';
import { convertListStruct, packList } from '../../utils/serializeList';
import { packSimpleWithCodec, unpack } from '../../utils/struct';
import { Validator } from './validator';

const _symbol = Symbol('pvm.AddValidatorTx');

/**
* @see
*/
@serializable()
export class AddValidatorTx {
_type = _symbol;

constructor(
public readonly baseTx: BaseTx,
public readonly validator: Validator,
public readonly stake: TransferableOutput[],
public readonly rewardsOwner: OutputOwners,
public readonly shares: Int,
) {}

static fromBytes(
bytes: Uint8Array,
codec: Codec,
): [AddValidatorTx, Uint8Array] {
const [baseTx, validator, stake, rewardsOwner, shares, rest] = unpack(
bytes,
[
BaseTx,
Validator,
convertListStruct(TransferableOutput),
OutputOwners,
Int,
],
codec,
);
return [
new AddValidatorTx(baseTx, validator, stake, rewardsOwner, shares),
rest,
];
}

toBytes(codec: Codec) {
return concatBytes(
packSimpleWithCodec([this.baseTx, this.validator], codec),
packList(this.stake, codec),
packSimpleWithCodec([this.rewardsOwner, this.shares], codec),
);
}
}
65 changes: 32 additions & 33 deletions src/vms/pvm/codec.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import { Codec, Manager } from '../../codec';
import { BaseTx } from '../../components/avax';
import * as Secp256k1Fx from '../../fxs/secp256k1';
import { AddValidatorTx } from './addValidatorTx';

// https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/codec.go
const manager = new Manager();
manager.RegisterCodec(
0,
new Codec([
undefined, // TODO: ProposalBlock
undefined, // TODO: AbortBlock
undefined, // TODO: CommitBlock
undefined, // TODO: StandardBlock
undefined, // TODO: AtomicBlock

...Secp256k1Fx.TypeRegistry,
Secp256k1Fx.Input,
Secp256k1Fx.OutputOwners,

undefined, // TODO: UnsignedAddValidatorTx
undefined, // TODO: UnsignedAddSubnetValidatorTx
undefined, // TODO: UnsignedAddDelegatorTx

undefined, // TODO: UnsignedCreateChainTx
undefined, // TODO: UnsignedCreateSubnetTx

undefined, // TODO: UnsignedImportTx
undefined, // TODO: UnsignedExportTx

undefined, // TODO: UnsignedAdvanceTimeTx
undefined, // TODO: UnsignedRewardValidatorTx

undefined, // TODO: stakeable.LockIn
undefined, // TODO: stakeable.LockOut
]),
);

export { manager };
export const codec = new Codec([
BaseTx, // TODO: ProposalBlock
undefined, // TODO: AbortBlock
undefined, // TODO: CommitBlock
undefined, // TODO: StandardBlock
undefined, // TODO: AtomicBlock

...Secp256k1Fx.TypeRegistry,
Secp256k1Fx.Input,
Secp256k1Fx.OutputOwners,

AddValidatorTx, // TODO: UnsignedAddValidatorTx
undefined, // TODO: UnsignedAddSubnetValidatorTx
undefined, // TODO: UnsignedAddDelegatorTx

undefined, // TODO: UnsignedCreateChainTx
undefined, // TODO: UnsignedCreateSubnetTx

undefined, // TODO: UnsignedImportTx
undefined, // TODO: UnsignedExportTx

undefined, // TODO: UnsignedAdvanceTimeTx
undefined, // TODO: UnsignedRewardValidatorTx

undefined, // TODO: stakeable.LockIn
undefined, // TODO: stakeable.LockOut
]);

export const manager = new Manager();
manager.RegisterCodec(0, codec);
12 changes: 12 additions & 0 deletions src/vms/pvm/subnetValidator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { testPVMCodec } from '../../fixtures/codec';
import { subnetValidator, subnetValidatorBytes } from '../../fixtures/pvm';
import { testSerialization } from '../../fixtures/utils/serializable';
import { SubnetValidator } from './subnetValidator';

testSerialization(
'SubnetValidator',
SubnetValidator,
subnetValidator,
subnetValidatorBytes,
testPVMCodec,
);
32 changes: 32 additions & 0 deletions src/vms/pvm/subnetValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Codec } from '../../codec/codec';
import { serializable } from '../../common/types';
import { Id } from '../../fxs/common';
import { packSimpleWithCodec, unpack } from '../../utils/struct';
import { Validator } from './validator';

const _symbol = Symbol('pvm.SubnetValidator');

/**
* @see
*/
@serializable()
export class SubnetValidator {
_type = _symbol;

constructor(
public readonly validator: Validator,
public readonly subnetId: Id,
) {}

static fromBytes(
bytes: Uint8Array,
codec: Codec,
): [SubnetValidator, Uint8Array] {
const [validator, subnetId, rest] = unpack(bytes, [Validator, Id], codec);
return [new SubnetValidator(validator, subnetId), rest];
}

toBytes(codec: Codec) {
return packSimpleWithCodec([this.validator, this.subnetId], codec);
}
}
5 changes: 5 additions & 0 deletions src/vms/pvm/validator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { validator, validatorBytes } from '../../fixtures/pvm';
import { testSerialization } from '../../fixtures/utils/serializable';
import { Validator } from './validator';

testSerialization('Validator', Validator, validator, validatorBytes);
38 changes: 38 additions & 0 deletions src/vms/pvm/validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Codec } from '../../codec/codec';
import { serializable } from '../../common/types';
import { Id } from '../../fxs/common';
import { BigIntPr } from '../../primitives';
import { packSimpleWithCodec, unpack } from '../../utils/struct';

const _symbol = Symbol('pvm.Validator');

/**
* @see https://docs.avax.network/specs/platform-transaction-serialization#unsigned-add-validator-tx
*/
@serializable()
export class Validator {
_type = _symbol;

constructor(
public readonly nodeId: Id,
public readonly startTime: BigIntPr,
public readonly endTime: BigIntPr,
public readonly weight: BigIntPr,
) {}

static fromBytes(bytes: Uint8Array, codec: Codec): [Validator, Uint8Array] {
const [nodeId, startTime, endTime, weight, rest] = unpack(
bytes,
[Id, BigIntPr, BigIntPr, BigIntPr],
codec,
);
return [new Validator(nodeId, startTime, endTime, weight), rest];
}

toBytes(codec: Codec) {
return packSimpleWithCodec(
[this.nodeId, this.startTime, this.endTime, this.weight],
codec,
);
}
}

0 comments on commit 8710224

Please sign in to comment.