Skip to content

Commit

Permalink
2776 smart rollup origination with whitelist (#2781)
Browse files Browse the repository at this point in the history
* removed references to originationProof

* trigger checks

* trigger checks

* test commit

* adjusted more tests

* removed remaining origination proof artifacts

* updated smart rollup docs

* adjusted estimates

* feat: supported smartRollupOriginate with new pvmKind and property whitelist in localForger

re #2776

* refactor: addressed comments of naming for clarity

* test: updated contract-estimation-tests-spec.ts assertions

---------

Co-authored-by: Davis Sawali <[email protected]>
  • Loading branch information
hui-an-yang and dsawali authored Jan 5, 2024
1 parent a39f699 commit cd1f805
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 47 deletions.
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"ProxfordY",
"PtNairobi",
"refetched",
"riscv",
"rollups",
"Roxane",
"SAPLINGCONTRACT",
Expand Down
10 changes: 5 additions & 5 deletions integration-tests/contract-estimation-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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();
Expand Down
41 changes: 35 additions & 6 deletions packages/taquito-local-forging/src/codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);

Expand Down Expand Up @@ -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);
}
Expand All @@ -128,14 +142,16 @@ 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());
}
};

export const delegateEncoder = (val: string) => {
if (val) {
return boolEncoder(true) + pkhEncoder(val);
return boolEncoder(true) + publicKeyHashEncoder(val);
} else {
return boolEncoder(false);
}
Expand Down Expand Up @@ -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:
Expand All @@ -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) {
Expand All @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions packages/taquito-local-forging/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
6 changes: 4 additions & 2 deletions packages/taquito-local-forging/src/decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
int32Decoder,
paddedBytesDecoder,
parametersDecoder,
pkhDecoder,
publicKeyHashDecoder,
publicKeyHashesDecoder,
smartRollupMessageDecoder,
proposalDecoder,
proposalsDecoder,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions packages/taquito-local-forging/src/encoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
int32Encoder,
paddedBytesEncoder,
parametersEncoder,
pkhEncoder,
publicKeyHashEncoder,
publicKeyHashesEncoder,
smartRollupMessageEncoder,
proposalEncoder,
proposalsEncoder,
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packages/taquito-local-forging/src/schema/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
4 changes: 3 additions & 1 deletion packages/taquito-local-forging/src/taquito-local-forging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(', ')}"`);
}
Expand Down
71 changes: 62 additions & 9 deletions packages/taquito-local-forging/test/codec.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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
);
});
Expand Down
Loading

0 comments on commit cd1f805

Please sign in to comment.