Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Added calltable serialization for TransactionV1, Changing TransactionV1 structure #459

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions src/types/AddressableEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,21 +152,3 @@ export class NamedEntryPoint {
@jsonMember({ name: 'name', constructor: String })
name: string;
}

/**
* Returns the numeric tag associated with a given transaction runtime version.
* Useful for distinguishing between different virtual machine versions.
*
* @param runtime - The transaction runtime to retrieve the tag for.
* @returns A number representing the tag for the given runtime.
*/
export function getRuntimeTag(runtime: TransactionRuntime): number {
switch (runtime) {
case 'VmCasperV1':
return 0;
case 'VmCasperV2':
return 1;
default:
return 0;
}
}
73 changes: 34 additions & 39 deletions src/types/Args.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { concat } from '@ethersproject/bytes';

import {
CLTypeString,
CLValue,
CLValueParser,
CLValueString,
CLValueUInt32,
IResultWithBytes
} from './clvalue';
import { CLValue, CLValueParser } from './clvalue';
import { jsonMapMember, jsonObject } from 'typedjson';
import { toBytesString, toBytesU32 } from './ByteConverters';

Expand Down Expand Up @@ -35,21 +28,21 @@ export class NamedArg {
/**
* Creates a `NamedArg` instance from a byte array.
* @param bytes - The byte array to parse.
* @returns A new `NamedArg` instance.
* @throws Error if the value data is missing.
* @returns A `NamedArg` instance.
*/
public static fromBytes(bytes: Uint8Array): NamedArg {
const stringValue = CLValueString.fromBytes(bytes);
let offset = 0;

if (!stringValue.bytes) {
throw new Error('Missing data for value of named arg');
}
const nameLength = new DataView(bytes.buffer).getUint32(offset, true);
offset += 4;
const nameBytes = bytes.slice(offset, offset + nameLength);
offset += nameLength;
const name = new TextDecoder().decode(nameBytes);

const value = CLValueParser.fromBytesByType(
stringValue.bytes,
CLTypeString
);
return new NamedArg(value.result.toString(), value.result);
const valueBytes = bytes.slice(offset);
const value = CLValueParser.fromBytesWithType(valueBytes);

return new NamedArg(name, value.result);
}
}

Expand Down Expand Up @@ -156,28 +149,30 @@ export class Args {

/**
* Creates an `Args` instance from a byte array.
* Parses the byte array to extract each argument.
* @param bytes - The byte array to parse.
* @returns An object containing a new `Args` instance and any remaining bytes.
* @throws Error if there is an issue parsing the bytes.
* @returns An `Args` instance.
*/
public static fromBytes(bytes: Uint8Array): IResultWithBytes<Args> {
const uint32 = CLValueUInt32.fromBytes(bytes);
const size = uint32.result.getValue().toNumber();

let remainBytes: Uint8Array | undefined = uint32.bytes;
const res: NamedArg[] = [];
for (let i = 0; i < size; i++) {
if (!remainBytes) {
throw new Error('Error while parsing bytes');
}
const namedArg = NamedArg.fromBytes(remainBytes);
res.push(namedArg);
remainBytes = undefined;
public static fromBytes(bytes: Uint8Array): Args {
let offset = 0;

const numArgs = new DataView(bytes.buffer).getUint32(offset, true);
offset += 4;

const args = new Map<string, CLValue>();

for (let i = 0; i < numArgs; i++) {
const namedArgBytes = bytes.slice(offset);
const namedArg = NamedArg.fromBytes(namedArgBytes);

const nameLength = new DataView(namedArgBytes.buffer).getUint32(0, true);
const valueBytes = CLValueParser.toBytesWithType(namedArg.value);
const consumedBytes = 4 + nameLength + valueBytes.length;

offset += consumedBytes;

args.set(namedArg.name, namedArg.value);
}
return {
result: Args.fromNamedArgs(res),
bytes: remainBytes || Uint8Array.from([])
};

return new Args(args);
}
}
44 changes: 44 additions & 0 deletions src/types/Bid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ export class ValidatorBid {
@jsonMember({ name: 'maximum_delegation_amount', constructor: Number })
maximumDelegationAmount: number;

/**
* Number of slots reserved for specific delegators
*/
@jsonMember({ name: 'reserved_slots', constructor: Number })
reservedSlots: number;

/**
* The vesting schedule for this validator’s stake.
*/
Expand Down Expand Up @@ -301,3 +307,41 @@ export class Bridge {
})
newValidatorPublicKey: PublicKey;
}

@jsonObject
/**
* Represents a reservation in the blockchain system, including delegation details and associated public keys.
*/
export class Reservation {
/**
* The delegation rate, representing the percentage of rewards allocated to the delegator.
*/
@jsonMember({ name: 'delegation_rate', constructor: Number })
delegationRate: number;

/**
* The public key of the validator associated with this reservation.
*
* This key is used to identify the validator in the blockchain system.
*/
@jsonMember({
name: 'validator_public_key',
constructor: PublicKey,
deserializer: json => PublicKey.fromJSON(json),
serializer: value => value.toJSON()
})
validatorPublicKey: PublicKey;

/**
* The public key of the delegator associated with this reservation.
*
* This key is used to identify the delegator who initiated the reservation.
*/
@jsonMember({
name: 'delegator_public_key',
constructor: PublicKey,
deserializer: json => PublicKey.fromJSON(json),
serializer: value => value.toJSON()
})
delegatorPublicKey: PublicKey;
}
15 changes: 14 additions & 1 deletion src/types/BidKind.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { jsonObject, jsonMember } from 'typedjson';
import { Bid, Bridge, Credit, Delegator, ValidatorBid } from './Bid';
import {
Bid,
Bridge,
Credit,
Delegator,
Reservation,
ValidatorBid
} from './Bid';

/**
* Represents a polymorphic bid kind, allowing for different types of bid-related entities.
Expand Down Expand Up @@ -37,4 +44,10 @@ export class BidKind {
*/
@jsonMember({ name: 'Credit', constructor: Credit })
credit?: Credit;

/**
* Represents a validator reserving a slot for specific delegator
*/
@jsonMember({ name: 'Reservation', constructor: Reservation })
reservation?: Reservation;
}
46 changes: 46 additions & 0 deletions src/types/ByteConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export const toBytesNumber = (bitSize: number, signed: boolean) => (
*/
export const toBytesU8 = toBytesNumber(8, false);

/**
* Converts an 16-bit unsigned integer (`u16`) to little-endian byte format.
*/
export const toBytesU16 = toBytesNumber(16, false);

/**
* Converts a 32-bit signed integer (`i32`) to little-endian byte format.
*/
Expand Down Expand Up @@ -127,3 +132,44 @@ export function toBytesArrayU8(arr: Uint8Array): Uint8Array {
export function byteHash(x: Uint8Array): Uint8Array {
return blake2b(x, { dkLen: 32 });
}

/**
* Parses a 16-bit unsigned integer (`u16`) from a little-endian byte array.
* @param bytes - The byte array containing the `u16` value.
* @returns The parsed 16-bit unsigned integer.
*/
export function parseU16(bytes: Uint8Array): number {
if (bytes.length < 2) {
throw new Error('Invalid byte array for u16 parsing');
}
return bytes[0] | (bytes[1] << 8);
}

/**
* Parses a 32-bit unsigned integer (`u32`) from a little-endian byte array.
* @param bytes - The byte array containing the `u32` value.
* @returns The parsed 32-bit unsigned integer.
*/
export function parseU32(bytes: Uint8Array): number {
if (bytes.length < 4) {
throw new Error('Invalid byte array for u32 parsing');
}

return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}

/**
* Parses a 64-bit unsigned integer (`u64`) from a little-endian byte array.
* @param bytes - A `Uint8Array` containing the serialized 64-bit unsigned integer.
* @returns A `BigNumber` representing the parsed value.
*/
export const fromBytesU64 = (bytes: Uint8Array): BigNumber => {
if (bytes.length !== 8) {
throw new Error(
`Invalid input length for u64: expected 8 bytes, got ${bytes.length}`
);
}

// Convert the little-endian bytes into a BigNumber
return BigNumber.from(bytes.reverse());
};
Loading
Loading