Repository: ecadlabs/taquito (ts)

Issue:
[Oxford2] Update local forger to include 'whitelist' property for smart rollup originate
Oxford2 introduced changes to Smart Rollups where you can now make use of private rollups.

The whitelist property is introduced as an optional property now in `smart_rollup_originate`

Investigate and implement the changes in local forger to reflect the changes.

> The smart_rollup_originate operation now also takes an optional whitelist of public key hashes. This whitelist cannot be used yet (the sc_rollup.private_enable flag has to be set to true). (MR [!9401](https://gitlab.com/tezos/tezos/-/merge_requests/9401))

Relevant docs:
- https://tezos.gitlab.io/protocols/018_oxford.html#smart-rollups



Pull request description:
2776 smart rollup origination with whitelist
supporting whitelist property and new PVMkind riscv of smartRollupOrigination in localForging 
closes #2776 

Thank you for your contribution to Taquito.

Before submitting this PR, please make sure:

- [x] Your code builds cleanly without any errors or warnings
- [x] You have run the linter against the changes
- [x] You have added unit tests (if relevant/appropriate)
- [x] You have added integration tests (if relevant/appropriate)
- [ ] All public methods or types have TypeDoc coverage with a complete description, and ideally an @example
- [ ] You have added or updated corresponding documentation
- [x] If relevant, you have written a first draft summary describing the change for inclusion in Release Notes. 

In this PR, please also make sure: 

- [x] You have linked this PR to the issue by putting `closes #TICKETNUMBER` in the description box (when applicable)
- [x] You have added a concise description on your changes
## Release Note Draft Snippet

__If relevant, please write a summary of your change that will be suitable for
inclusion in the Release Notes for the next Taquito release.__


Patch:
diff --git a/cspell.json b/cspell.json
index 01fecb89b..5d5b5bbd6 100644
--- a/cspell.json
+++ b/cspell.json
@@ -77,6 +77,7 @@
     "ProxfordY",
     "PtNairobi",
     "refetched",
+    "riscv",
     "rollups",
     "Roxane",
     "SAPLINGCONTRACT",
diff --git a/packages/taquito-local-forging/src/codec.ts b/packages/taquito-local-forging/src/codec.ts
index 48324ea58..7fba0d570 100644
--- a/packages/taquito-local-forging/src/codec.ts
+++ b/packages/taquito-local-forging/src/codec.ts
@@ -45,7 +45,7 @@ export const prefixDecoder = (pre: Prefix) => (str: Uint8ArrayConsumer) => {
 
 export const tz1Decoder = prefixDecoder(Prefix.TZ1);
 export const branchDecoder = prefixDecoder(Prefix.B);
-export const pkhDecoder = (val: Uint8ArrayConsumer) => {
+export const publicKeyHashDecoder = (val: Uint8ArrayConsumer) => {
   const prefix = val.consume(1);
 
   if (prefix[0] === 0x00) {
@@ -57,6 +57,18 @@ export const pkhDecoder = (val: Uint8ArrayConsumer) => {
   }
 };
 
+export const publicKeyHashesDecoder = (val: Uint8ArrayConsumer) => {
+  if (!boolDecoder(val)) {
+    return undefined;
+  }
+  const publicKeyHashes = [];
+  val.consume(4);
+  while (val.length() > 0) {
+    publicKeyHashes.push(publicKeyHashDecoder(val));
+  }
+  return publicKeyHashes;
+};
+
 export const branchEncoder = prefixEncoder(Prefix.B);
 export const tz1Encoder = prefixEncoder(Prefix.TZ1);
 
@@ -116,6 +128,8 @@ export const pvmKindEncoder = (pvm: string): string => {
       return '00';
     case 'wasm_2_0_0':
       return '01';
+    case 'riscv':
+      return '02';
     default:
       throw new UnsupportedPvmKindError(pvm);
   }
@@ -128,6 +142,8 @@ export const pvmKindDecoder = (pvm: Uint8ArrayConsumer): string => {
       return 'arith';
     case 0x01:
       return 'wasm_2_0_0';
+    case 0x02:
+      return 'riscv';
     default:
       throw new DecodePvmKindError(value[0].toString());
   }
@@ -135,7 +151,7 @@ export const pvmKindDecoder = (pvm: Uint8ArrayConsumer): string => {
 
 export const delegateEncoder = (val: string) => {
   if (val) {
-    return boolEncoder(true) + pkhEncoder(val);
+    return boolEncoder(true) + publicKeyHashEncoder(val);
   } else {
     return boolEncoder(false);
   }
@@ -189,11 +205,11 @@ export const boolDecoder = (val: Uint8ArrayConsumer): boolean => {
 export const delegateDecoder = (val: Uint8ArrayConsumer) => {
   const hasDelegate = boolDecoder(val);
   if (hasDelegate) {
-    return pkhDecoder(val);
+    return publicKeyHashDecoder(val);
   }
 };
 
-export const pkhEncoder = (val: string) => {
+export const publicKeyHashEncoder = (val: string) => {
   const pubkeyPrefix = val.substring(0, 3);
   switch (pubkeyPrefix) {
     case Prefix.TZ1:
@@ -213,6 +229,19 @@ export const pkhEncoder = (val: string) => {
   }
 };
 
+export const publicKeyHashesEncoder = (val?: string[]) => {
+  if (!val) {
+    return boolEncoder(false);
+  }
+  if (val.length === 0) {
+    return boolEncoder(true) + pad(0);
+  }
+  const publicKeyHashes = val.reduce((prev, curr) => {
+    return prev + publicKeyHashEncoder(curr);
+  }, '');
+  return boolEncoder(true) + pad(publicKeyHashes.length / 2) + publicKeyHashes;
+};
+
 export const publicKeyEncoder = (val: string) => {
   const pubkeyPrefix = val.substring(0, 4);
   switch (pubkeyPrefix) {
@@ -238,7 +267,7 @@ export const addressEncoder = (val: string): string => {
     case Prefix.TZ2:
     case Prefix.TZ3:
     case Prefix.TZ4:
-      return '00' + pkhEncoder(val);
+      return '00' + publicKeyHashEncoder(val);
     case Prefix.KT1:
       return '01' + prefixEncoder(Prefix.KT1)(val) + '00';
     default:
@@ -304,7 +333,7 @@ export const addressDecoder = (val: Uint8ArrayConsumer) => {
   const preamble = val.consume(1);
   switch (preamble[0]) {
     case 0x00:
-      return pkhDecoder(val);
+      return publicKeyHashDecoder(val);
     case 0x01: {
       const address = prefixDecoder(Prefix.KT1)(val);
       val.consume(1);
diff --git a/packages/taquito-local-forging/src/constants.ts b/packages/taquito-local-forging/src/constants.ts
index 4c1a5f81d..8def4779e 100644
--- a/packages/taquito-local-forging/src/constants.ts
+++ b/packages/taquito-local-forging/src/constants.ts
@@ -16,6 +16,7 @@ export enum CODEC {
   ZARITH = 'zarith',
   PUBLIC_KEY = 'public_key',
   PKH = 'pkh',
+  PKH_ARR = 'pkhArr',
   DELEGATE = 'delegate',
   SCRIPT = 'script',
   BALLOT_STATEMENT = 'ballotStmt',
diff --git a/packages/taquito-local-forging/src/decoder.ts b/packages/taquito-local-forging/src/decoder.ts
index 1e68113b8..68b1c1378 100644
--- a/packages/taquito-local-forging/src/decoder.ts
+++ b/packages/taquito-local-forging/src/decoder.ts
@@ -10,7 +10,8 @@ import {
   int32Decoder,
   paddedBytesDecoder,
   parametersDecoder,
-  pkhDecoder,
+  publicKeyHashDecoder,
+  publicKeyHashesDecoder,
   smartRollupMessageDecoder,
   proposalDecoder,
   proposalsDecoder,
@@ -62,7 +63,8 @@ export const decoders: { [key: string]: Decoder } = {
   [CODEC.BRANCH]: branchDecoder,
   [CODEC.ZARITH]: zarithDecoder,
   [CODEC.PUBLIC_KEY]: publicKeyDecoder,
-  [CODEC.PKH]: pkhDecoder,
+  [CODEC.PKH]: publicKeyHashDecoder,
+  [CODEC.PKH_ARR]: publicKeyHashesDecoder,
   [CODEC.DELEGATE]: delegateDecoder,
   [CODEC.INT32]: int32Decoder,
   [CODEC.SCRIPT]: scriptDecoder,
diff --git a/packages/taquito-local-forging/src/encoder.ts b/packages/taquito-local-forging/src/encoder.ts
index bd68c587d..028ffcb50 100644
--- a/packages/taquito-local-forging/src/encoder.ts
+++ b/packages/taquito-local-forging/src/encoder.ts
@@ -10,7 +10,8 @@ import {
   int32Encoder,
   paddedBytesEncoder,
   parametersEncoder,
-  pkhEncoder,
+  publicKeyHashEncoder,
+  publicKeyHashesEncoder,
   smartRollupMessageEncoder,
   proposalEncoder,
   proposalsEncoder,
@@ -60,7 +61,8 @@ export const encoders: { [key: string]: Encoder<any> } = {
   [CODEC.BRANCH]: branchEncoder,
   [CODEC.ZARITH]: zarithEncoder,
   [CODEC.PUBLIC_KEY]: publicKeyEncoder,
-  [CODEC.PKH]: pkhEncoder,
+  [CODEC.PKH]: publicKeyHashEncoder,
+  [CODEC.PKH_ARR]: publicKeyHashesEncoder,
   [CODEC.DELEGATE]: delegateEncoder,
   [CODEC.SCRIPT]: scriptEncoder,
   [CODEC.BALLOT_STATEMENT]: ballotEncoder,
diff --git a/packages/taquito-local-forging/src/schema/operation.ts b/packages/taquito-local-forging/src/schema/operation.ts
index 6afa83292..73be533c7 100644
--- a/packages/taquito-local-forging/src/schema/operation.ts
+++ b/packages/taquito-local-forging/src/schema/operation.ts
@@ -149,6 +149,7 @@ export const SmartRollupOriginateSchema = {
   pvm_kind: CODEC.PVM_KIND,
   kernel: CODEC.PADDED_BYTES,
   parameters_ty: CODEC.VALUE,
+  whitelist: CODEC.PKH_ARR,
 };
 
 export const SmartRollupAddMessagesSchema = {
diff --git a/packages/taquito-local-forging/src/taquito-local-forging.ts b/packages/taquito-local-forging/src/taquito-local-forging.ts
index 2a4642e28..b819c7515 100644
--- a/packages/taquito-local-forging/src/taquito-local-forging.ts
+++ b/packages/taquito-local-forging/src/taquito-local-forging.ts
@@ -22,7 +22,7 @@ export * from './interface';
 export { VERSION } from './version';
 export { ProtocolsHash } from './protocols';
 
-const PROTOCOL_CURRENT = ProtocolsHash.PtMumbai2;
+const PROTOCOL_CURRENT = ProtocolsHash.ProxfordY;
 
 export function getCodec(codec: CODEC, _proto: ProtocolsHash) {
   return {
@@ -60,6 +60,8 @@ export class LocalForger implements Forger {
           continue;
         } else if (content.kind === 'set_deposits_limit' && diff[0] === 'limit') {
           continue;
+        } else if (content.kind === 'smart_rollup_originate' && diff[0] === 'whitelist') {
+          continue;
         } else {
           throw new InvalidOperationSchemaError(content, `missing properties "${diff.join(', ')}"`);
         }
diff --git a/packages/taquito-rpc/src/types.ts b/packages/taquito-rpc/src/types.ts
index c8df5bf3a..0764e875b 100644
--- a/packages/taquito-rpc/src/types.ts
+++ b/packages/taquito-rpc/src/types.ts
@@ -19,19 +19,19 @@ interface INodeExtender {
 
 type OtherEltsInner =
   | {
-      value: any;
-    }
+    value: any;
+  }
   | {
-      inode_extender: INodeExtender;
-    };
+    inode_extender: INodeExtender;
+  };
 
 export type OtherElts =
   | {
-      node: [string, { value: string } | { node: string }][];
-    }
+    node: [string, { value: string } | { node: string }][];
+  }
   | {
-      other_elts: OtherEltsInner;
-    };
+    other_elts: OtherEltsInner;
+  };
 
 export interface Inode {
   length: string;
@@ -334,6 +334,7 @@ export interface OperationContentsSmartRollupOriginate {
   pvm_kind: PvmKind;
   kernel: string;
   parameters_ty: MichelsonV1Expression;
+  whitelist?: string[];
 }
 
 export interface OperationContentsSmartRollupAddMessages {
@@ -761,6 +762,7 @@ export interface OperationContentsAndResultSmartRollupOriginate {
   pvm_kind: PvmKind;
   kernel: string;
   parameters_ty: MichelsonV1Expression;
+  whitelist?: string[];
   metadata: OperationContentsAndResultMetadataSmartRollupOriginate;
 }
 
@@ -1104,13 +1106,13 @@ export interface ScriptedContracts {
 
 export type BondId =
   | {
-      smart_rollup?: never;
-      tx_rollup: string;
-    }
+    smart_rollup?: never;
+    tx_rollup: string;
+  }
   | {
-      smart_rollup: string;
-      tx_rollup?: never;
-    };
+    smart_rollup: string;
+    tx_rollup?: never;
+  };
 
 export interface OperationBalanceUpdatesItem {
   kind: BalanceUpdateKindEnum;
@@ -1207,7 +1209,7 @@ export interface OperationResultSmartRollupOriginate {
   address?: string;
   genesis_commitment_hash?: string;
   consumed_milligas?: string;
-  size: string;
+  size?: string;
   errors?: TezosGenericOperationError[];
 }
 
@@ -1818,10 +1820,10 @@ export interface ConstantsResponseProto010 extends ConstantsResponseProto009 {
 }
 
 // eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface ConstantsResponseProto009 extends ConstantsResponseProto008 {}
+export interface ConstantsResponseProto009 extends ConstantsResponseProto008 { }
 
 // eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface ConstantsResponseProto008 extends ConstantsResponseProto007 {}
+export interface ConstantsResponseProto008 extends ConstantsResponseProto007 { }
 
 export interface ConstantsResponseProto007
   extends Omit<ConstantsResponseProto006, 'max_revelations_per_block'> {
@@ -2029,12 +2031,12 @@ export type ProtocolsResponse = {
 
 export type Next =
   | {
-      next: number;
-    }
+    next: number;
+  }
   | {
-      newest: number;
-      oldest: number;
-    };
+    newest: number;
+    oldest: number;
+  };
 
 export type LastRemovedCommitmentHashes = {
   last_message_hash: string;
@@ -2080,6 +2082,7 @@ export interface PendingOperationsV2 {
 export enum PvmKind {
   WASM2 = 'wasm_2_0_0',
   ARITH = 'arith',
+  RISCV = 'riscv',
 }
 
 export interface SmartRollupPublishCommitment {


Test patch:
diff --git a/integration-tests/contract-estimation-tests.spec.ts b/integration-tests/contract-estimation-tests.spec.ts
index 9ed760714..748243dda 100644
--- a/integration-tests/contract-estimation-tests.spec.ts
+++ b/integration-tests/contract-estimation-tests.spec.ts
@@ -101,7 +101,7 @@ CONFIGS().forEach(({ lib, setup, knownBaker, createAddress, rpc }) => {
       expect(estimate.minimalFeeMutez).toEqual(472);
       expect(estimate.totalCost).toEqual(472);
       expect(estimate.usingBaseFeeMutez).toEqual(472);
-      expect(estimate.consumedMilligas).toEqual(1356142);
+      expect(estimate.consumedMilligas).toEqual(1356228);
     });
 
     it('Verify .estimate.transfer for multiple internal transfers to unallocated account', async () => {
@@ -118,7 +118,7 @@ CONFIGS().forEach(({ lib, setup, knownBaker, createAddress, rpc }) => {
       expect(estimate.minimalFeeMutez).toEqual(543);
       expect(estimate.totalCost).toEqual(129043);
       expect(estimate.usingBaseFeeMutez).toEqual(543);
-      expect(estimate.consumedMilligas).toEqual(1470671);
+      expect(estimate.consumedMilligas).toEqual(1470757);
     });
 
     it('Verify .estimate.transfer for internal origination', async () => {
@@ -131,20 +131,20 @@ CONFIGS().forEach(({ lib, setup, knownBaker, createAddress, rpc }) => {
       expect(estimate.minimalFeeMutez).toEqual(519);
       expect(estimate.totalCost).toEqual(79769);
       expect(estimate.usingBaseFeeMutez).toEqual(519);
-      expect(estimate.consumedMilligas).toEqual(1766766);
+      expect(estimate.consumedMilligas).toEqual(1766852);
     });
 
     it('Verify .estimate.transfer for multiple internal originations', async () => {
       const tx = contract.methods.do(originate2()).toTransferParams();
       const estimate = await LowAmountTez.estimate.transfer(tx);
-      expect(estimate.gasLimit).toEqual(2392);
+      expect(estimate.gasLimit).toEqual(2393);
       expect(estimate.storageLimit).toEqual(634);
       expect(estimate.suggestedFeeMutez).toEqual(737);
       expect(estimate.burnFeeMutez).toEqual(158500);
       expect(estimate.minimalFeeMutez).toEqual(637);
       expect(estimate.totalCost).toEqual(159137);
       expect(estimate.usingBaseFeeMutez).toEqual(637);
-      expect(estimate.consumedMilligas).toEqual(2291919);
+      expect(estimate.consumedMilligas).toEqual(2292005);
       // Do the actual operation
       const op2 = await contract.methods.do(originate2()).send();
       await op2.confirmation();
diff --git a/packages/taquito-local-forging/test/codec.spec.ts b/packages/taquito-local-forging/test/codec.spec.ts
index 8694565d5..2721f7e2a 100644
--- a/packages/taquito-local-forging/test/codec.spec.ts
+++ b/packages/taquito-local-forging/test/codec.spec.ts
@@ -9,7 +9,13 @@ import {
   paddedBytesDecoder,
 } from '../src/codec';
 import { Uint8ArrayConsumer } from '../src/uint8array-consumer';
-import { pkhEncoder, publicKeyDecoder, publicKeyEncoder } from '../src/codec';
+import {
+  publicKeyHashEncoder,
+  publicKeyHashesEncoder,
+  publicKeyHashesDecoder,
+  publicKeyDecoder,
+  publicKeyEncoder,
+} from '../src/codec';
 import {
   DecodeBallotValueError,
   DecodePvmKindError,
@@ -59,23 +65,68 @@ describe('Tests for Entrypoint functions and for encode and decoder error messag
     );
   });
 
-  test(`Verify pkhEncoder`, async () => {
-    const tz1 = pkhEncoder('tz1e42w8ZaGAbM3gucbBy8iRypdbnqUj7oWY');
+  test(`Verify publicKeyHashEncoder`, async () => {
+    const tz1 = publicKeyHashEncoder('tz1e42w8ZaGAbM3gucbBy8iRypdbnqUj7oWY');
     expect(tz1).toEqual('00c9fc72e8491bd2973e196f04ec6918ad5bcee22d');
-    const tz2 = pkhEncoder('tz2Ch1abG7FNiibmV26Uzgdsnfni9XGrk5wD');
+    const tz2 = publicKeyHashEncoder('tz2Ch1abG7FNiibmV26Uzgdsnfni9XGrk5wD');
     expect(tz2).toEqual('012ffebbf1560632ca767bc960ccdb84669d284c2c');
-    const tz3 = pkhEncoder('tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5');
+    const tz3 = publicKeyHashEncoder('tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5');
     expect(tz3).toEqual('026fde46af0356a0476dae4e4600172dc9309b3aa4');
-    const tz4 = pkhEncoder('tz4HQ8VeXAyrZMhES1qLMJAc9uAVXjbMpS8u');
+    const tz4 = publicKeyHashEncoder('tz4HQ8VeXAyrZMhES1qLMJAc9uAVXjbMpS8u');
     expect(tz4).toEqual('035c14a7a05c10fc8b402fbcdd48dc8136236bf3c1');
-    expect(() => pkhEncoder('tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5')).toThrow(InvalidKeyHashError);
+    expect(() => publicKeyHashEncoder('tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5')).toThrow(
+      InvalidKeyHashError
+    );
     try {
-      pkhEncoder('tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5');
+      publicKeyHashEncoder('tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5');
     } catch (e) {
       expect(e.message).toContain(`Invalid public key hash "tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5"`);
     }
   });
 
+  test(`Verify publicKeyHashesEncoder`, async () => {
+    const none = publicKeyHashesEncoder();
+    expect(none).toEqual('00');
+    const empty = publicKeyHashesEncoder([]);
+    expect(empty).toEqual('ff00000000');
+    const tz = publicKeyHashesEncoder([
+      'tz1e42w8ZaGAbM3gucbBy8iRypdbnqUj7oWY',
+      'tz2Ch1abG7FNiibmV26Uzgdsnfni9XGrk5wD',
+      'tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5',
+      'tz4HQ8VeXAyrZMhES1qLMJAc9uAVXjbMpS8u',
+    ]);
+    expect(tz).toEqual(
+      'ff0000005400c9fc72e8491bd2973e196f04ec6918ad5bcee22d012ffebbf1560632ca767bc960ccdb84669d284c2c026fde46af0356a0476dae4e4600172dc9309b3aa4035c14a7a05c10fc8b402fbcdd48dc8136236bf3c1'
+    );
+
+    expect(() => publicKeyHashesEncoder(['tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5'])).toThrow(
+      InvalidKeyHashError
+    );
+    try {
+      publicKeyHashesEncoder(['tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5']);
+    } catch (e) {
+      expect(e.message).toContain(`Invalid public key hash "tz5WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5"`);
+    }
+  });
+
+  test(`Verify publicKeyHashesDecoder`, async () => {
+    const none = publicKeyHashesDecoder(Uint8ArrayConsumer.fromHexString('00'));
+    expect(none).toEqual(undefined);
+    const empty = publicKeyHashesDecoder(Uint8ArrayConsumer.fromHexString('ff00000000'));
+    expect(empty).toEqual([]);
+    const tz = publicKeyHashesDecoder(
+      Uint8ArrayConsumer.fromHexString(
+        'ff0000005400c9fc72e8491bd2973e196f04ec6918ad5bcee22d012ffebbf1560632ca767bc960ccdb84669d284c2c026fde46af0356a0476dae4e4600172dc9309b3aa4'
+      )
+    );
+    expect(tz).toEqual([
+      'tz1e42w8ZaGAbM3gucbBy8iRypdbnqUj7oWY',
+      'tz2Ch1abG7FNiibmV26Uzgdsnfni9XGrk5wD',
+      'tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5',
+    ]);
+    //
+  });
+
   test(`Verify publicKeyEncoder`, async () => {
     const edpk = publicKeyEncoder('edpkuLxx9PQD8fZ45eUzrK3BhfDZJHhBuK4Zi49DcEGANwd2rpX82t');
     expect(edpk).toEqual('005c8244b8de7d57795962c1bfc855d0813f8c61eddf3795f804ccdea3e4c82ae9');
@@ -240,13 +291,15 @@ describe('Tests for Entrypoint functions and for encode and decoder error messag
   test('Verify that pvmKindEncoder functions correctly and returns UnsupportedPvmKindError on unknown case', () => {
     expect(pvmKindEncoder('arith')).toEqual('00');
     expect(pvmKindEncoder('wasm_2_0_0')).toEqual('01');
+    expect(pvmKindEncoder('riscv')).toEqual('02');
     expect(() => pvmKindEncoder('foobar')).toThrowError(UnsupportedPvmKindError);
   });
 
   test('Verify that pvmKindDecoder functions correctly and returns DecodePvmKindError on unknown case', () => {
     expect(pvmKindDecoder(Uint8ArrayConsumer.fromHexString('00'))).toEqual('arith');
     expect(pvmKindDecoder(Uint8ArrayConsumer.fromHexString('01'))).toEqual('wasm_2_0_0');
-    expect(() => pvmKindDecoder(Uint8ArrayConsumer.fromHexString('02'))).toThrowError(
+    expect(pvmKindDecoder(Uint8ArrayConsumer.fromHexString('02'))).toEqual('riscv');
+    expect(() => pvmKindDecoder(Uint8ArrayConsumer.fromHexString('03'))).toThrowError(
       DecodePvmKindError
     );
   });