Skip to content

Commit

Permalink
Merge pull request #1914 from aeternity/faeture/ceres
Browse files Browse the repository at this point in the history
Basic Ceres compatibility
  • Loading branch information
davidyuk authored Dec 6, 2023
2 parents 73c423d + 4cb0a8a commit c5376db
Show file tree
Hide file tree
Showing 15 changed files with 131 additions and 59 deletions.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ services:
- ./docker/accounts_test.json:/home/aeternity/node/data/aecore/.genesis/accounts_test.json

compiler:
image: aeternity/aesophia_http:v7.4.0
image: aeternity/aesophia_http:v7.6.0
hostname: compiler
ports: ["3080:3080"]
2 changes: 1 addition & 1 deletion docker/aeternity_node_mean16.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ chain:
persist: false
hard_forks:
"1": 0
"5": 1
"6": 1

mining:
autostart: true
Expand Down
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
},
"sideEffects": false,
"scripts": {
"build:assets": "node tooling/fetch-aesophia-cli.mjs",
"build:assets": "node tooling/fetch-aesophia-cli.mjs && node tooling/fetch-aesophia-cli-8.mjs",
"build:types": "tsc && node tooling/downlevel/run.mjs",
"build:es": "babel src --config-file ./babel.esm.config.js --out-dir es --extensions .js,.ts --out-file-extension .mjs --source-maps true",
"build:api:node": "autorest tooling/autorest/node.yaml",
Expand Down Expand Up @@ -75,7 +75,7 @@
"SDK"
],
"dependencies": {
"@aeternity/aepp-calldata": "^1.5.1",
"@aeternity/aepp-calldata": "github:aeternity/aepp-calldata-js#7cce0a6d23ec0ba5f23f46acf9d4254a9346c9c9",
"@aeternity/argon2": "^0.0.1",
"@aeternity/uuid": "^0.0.1",
"@azure/core-client": "1.6.0",
Expand Down
7 changes: 4 additions & 3 deletions src/contract/compiler/Cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CompilerError, InternalError, UnsupportedVersionError } from '../../uti
import semverSatisfies from '../../utils/semver-satisfies';
import { ensureError } from '../../utils/other';

const getPackagePath = (): string => {
export const getPackagePath = (): string => {
const path = dirname(fileURLToPath(import.meta.url));
if (basename(path) === 'dist') return resolve(path, '..');
if (basename(path) === 'compiler') return resolve(path, '../../..');
Expand All @@ -19,6 +19,7 @@ const getPackagePath = (): string => {
/**
* A wrapper around aesophia_cli, available only in Node.js.
* Requires Erlang installed, assumes that `escript` is available in PATH.
* @category contract
*/
export default class CompilerCli extends CompilerBase {
#path: string;
Expand All @@ -38,7 +39,7 @@ export default class CompilerCli extends CompilerBase {
this.#path = compilerPath;
if (ignoreVersion !== true) {
this.#ensureCompatibleVersion = this.version().then((version) => {
const versions = [version, '7.2.1', '8.0.0'] as const;
const versions = [version, '7.2.1', '9.0.0'] as const;
if (!semverSatisfies(...versions)) throw new UnsupportedVersionError('compiler', ...versions);
});
}
Expand Down Expand Up @@ -79,7 +80,7 @@ export default class CompilerCli extends CompilerBase {
await this.#ensureCompatibleVersion;
try {
const [bytecode, aci] = await Promise.all([
this.#run(path),
this.#run(path, '--no_warning', 'all'),
this.#run('--create_json_aci', path).then((res) => JSON.parse(res)),
]);
return {
Expand Down
17 changes: 17 additions & 0 deletions src/contract/compiler/Cli8.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { resolve } from 'path';
import CompilerCli, { getPackagePath } from './Cli';

/**
* @category contract
*/
export default class CompilerCli8 extends CompilerCli {
/**
* @param options - Options
* @param options.ignoreVersion - Don't ensure that the compiler is supported
*/
constructor(
{ ignoreVersion }: { ignoreVersion?: boolean } = {},
) {
super(resolve(getPackagePath(), './bin/aesophia_cli_8'), { ignoreVersion });
}
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './index-browser';

export { default as CompilerCli } from './contract/compiler/Cli';
export { default as CompilerCli8 } from './contract/compiler/Cli8';
export { default as getFileSystem } from './contract/compiler/getFileSystem';
export { default as CompilerHttpNode } from './contract/compiler/HttpNode';
6 changes: 3 additions & 3 deletions test/integration/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function testCompiler(compiler: CompilerBase): void {
const inclSourceCodePath = './test/integration/contracts/Includes.aes';
let inclSourceCode: string;
let inclFileSystem: Record<string, string>;
const inclBytecode = 'cb_+QEGRgOg7BH1sCv+p2IrS0Pn3/i6AfE8lOGUuC71lLPn6mbUm9PAuNm4cv4AWolkAjcCBwcHFBQAAgD+RNZEHwA3ADcAGg6CPwEDP/5Nt4A5AjcCBwcHDAECDAEABAMRAFqJZP6SiyA2ADcBBwcMAwgMAQAEAxFNt4A5/pSgnxIANwF3BwwBAAQDEarAwob+qsDChgI3AXcHPgQAALhgLwYRAFqJZD0uU3VibGlicmFyeS5zdW0RRNZEHxFpbml0EU23gDkxLkxpYnJhcnkuc3VtEZKLIDYRdGVzdBGUoJ8SJWdldExlbmd0aBGqwMKGOS5TdHJpbmcubGVuZ3Rogi8AhTcuMi4xAFw7b7s=';
const inclBytecode = 'cb_+QEGRgOg7BH1sCv+p2IrS0Pn3/i6AfE8lOGUuC71lLPn6mbUm9PAuNm4cv4AWolkAjcCBwcHFBQAAgD+RNZEHwA3ADcAGg6CPwEDP/5Nt4A5AjcCBwcHDAECDAEABAMRAFqJZP6SiyA2ADcBBwcMAwgMAQAEAxFNt4A5/pSgnxIANwF3BwwBAAQDEarAwob+qsDChgI3AXcHPgQAALhgLwYRAFqJZD0uU3VibGlicmFyeS5zdW0RRNZEHxFpbml0EU23gDkxLkxpYnJhcnkuc3VtEZKLIDYRdGVzdBGUoJ8SJWdldExlbmd0aBGqwMKGOS5TdHJpbmcubGVuZ3Rogi8AhTcuNC4wAGqg1h8=';
const testBytecode = 'cb_+GhGA6BgYgXqYB9ctBcQ8mJ0+we5OXhb9PpsSQWP2DhPx9obn8C4O57+RNZEHwA3ADcAGg6CPwEDP/6AeCCSADcBd3cBAQCYLwIRRNZEHxFpbml0EYB4IJIZZ2V0QXJngi8AhTcuMC4xAMXqWXc=';

const interfaceSourceCodePath = './test/integration/contracts/Interface.aes';
Expand Down Expand Up @@ -61,7 +61,7 @@ function testCompiler(compiler: CompilerBase): void {
});

it('returns version', async () => {
expect(await compiler.version()).to.be.equal('7.2.1');
expect(await compiler.version()).to.be.equal('7.4.0');
});

it('compiles and generates aci by path', async () => {
Expand All @@ -85,7 +85,7 @@ function testCompiler(compiler: CompilerBase): void {
)).to.be.rejectedWith(
CompilerError,
compiler instanceof CompilerCli
? /Command failed: escript .+[\\/]bin[\\/]aesophia_cli( --create_json_aci)? .+\.aes\nType error( in '.+\.aes')? at line 3, col 3:\nDuplicate definitions of `getArg` at\n {2}- line 2, column 3\n {2}- line 3, column 3\n\n/m
? /Command failed: escript .+[\\/]bin[\\/]aesophia_cli( --create_json_aci)? .+\.aes( --no_warning all)?\nType error( in '.+\.aes')? at line 3, col 3:\nDuplicate definitions of `getArg` at\n {2}- line 2, column 3\n {2}- line 3, column 3\n\n/m
: 'compile error:\n'
+ 'type_error:3:3: Duplicate definitions of `getArg` at\n'
+ ' - line 2, column 3\n'
Expand Down
19 changes: 9 additions & 10 deletions test/integration/contract-aci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ include "testLib"
contract StateContract =
type number = int
record state = { value: string, key: number, testOption: option(string) }
record yesEr = { t: number}
datatype dateUnit = Year | Month | Day
datatype one_or_both('a, 'b) = Left('a) | Right('b) | Both('a, 'b)
Expand All @@ -56,10 +55,10 @@ contract StateContract =
entrypoint retrieve() : string*int = (state.value, state.key)
stateful entrypoint setKey(key: number) = put(state{key = key})
entrypoint remoteContract(a: RemoteI) : int = 1
entrypoint remoteArgs(a: RemoteI.test_record) : RemoteI.test_type = 1
entrypoint remoteContract(_: RemoteI) : int = 1
entrypoint remoteArgs(_: RemoteI.test_record) : RemoteI.test_type = 1
entrypoint unitFn(a: unit) = a
entrypoint intFn(a: int) : int = a
entrypoint intFn(a: int) : int = TestLib.sum(a, 0)
payable entrypoint stringFn(a: string) : string = a
entrypoint boolFn(a: bool) : bool = a
entrypoint addressFn(a: address) : address = a
Expand All @@ -81,7 +80,7 @@ contract StateContract =
entrypoint listOption(s: option(list(int*string))) : option(list(int*string)) = s
entrypoint testFn(a: list(int), b: bool) : list(int)*bool = (a, b)
entrypoint approve(tx_id: int, remote_contract: RemoteI) : int = tx_id
entrypoint approve(remote_contract: RemoteI) : RemoteI = remote_contract
entrypoint hashFn(s: hash): hash = s
entrypoint signatureFn(s: signature): signature = s
Expand All @@ -94,9 +93,9 @@ contract StateContract =
entrypoint datTypeFn(s: dateUnit): dateUnit = s
entrypoint datTypeGFn(x : one_or_both(int, string)) : int =
switch(x)
Left(x) => x
Left(p) => p
Right(_) => abort("asdasd")
Both(x, _) => x
Both(p, _) => p
entrypoint chainTtlFn(t: Chain.ttl): Chain.ttl = t
Expand Down Expand Up @@ -148,7 +147,7 @@ interface TestContractApi extends ContractMethodsBase {
listOption: (s?: Array<[InputNumber, string]>) => Array<[bigint, string]> | undefined;

testFn: (a: InputNumber[], b: boolean) => [bigint[], boolean];
approve: (tx_id: InputNumber, remote_contract: Encoded.ContractAddress) => bigint;
approve: (remote_contract: Encoded.ContractAddress) => Encoded.ContractAddress;

hashFn: (s: Uint8Array | string) => Uint8Array;
signatureFn: (s: Uint8Array | string) => Uint8Array;
Expand Down Expand Up @@ -1069,8 +1068,8 @@ describe('Contract instance', () => {
});

it('Call contract with contract type argument', async () => {
const result = await testContract.approve(0, 'ct_AUUhhVZ9de4SbeRk8ekos4vZJwMJohwW5X8KQjBMUVduUmoUh');
expect(result.decodedResult).to.be.equal(0n);
const result = await testContract.approve('ct_AUUhhVZ9de4SbeRk8ekos4vZJwMJohwW5X8KQjBMUVduUmoUh');
expect(result.decodedResult).to.be.equal('ct_AUUhhVZ9de4SbeRk8ekos4vZJwMJohwW5X8KQjBMUVduUmoUh');
});
});
});
62 changes: 36 additions & 26 deletions test/integration/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
genSalt,
UnexpectedTsError,
AeSdk,
Contract, ContractMethodsBase,
Contract, ContractMethodsBase, ConsensusProtocolVersion,
} from '../../src';

const identitySourceCode = `
Expand Down Expand Up @@ -79,7 +79,6 @@ describe('Contract', () => {
}>({
sourceCode:
'include "String.aes"'
+ '\ninclude "Option.aes"'
+ '\n'
+ '\ncontract Sign ='
+ '\n entrypoint int_to_binary (i: int): string ='
Expand All @@ -90,7 +89,7 @@ describe('Contract', () => {
+ '\n entrypoint includes (str: string, pat: string): bool ='
+ '\n switch(String.contains(str, pat))'
+ '\n None => false'
+ '\n Some(c) => true'
+ '\n Some(_) => true'
+ '\n'
+ '\n entrypoint message_to_hash (message: string): hash ='
+ '\n let prefix = "aeternity Signed Message:\\n"'
Expand Down Expand Up @@ -296,6 +295,7 @@ describe('Contract', () => {
let contract: Contract<{
getName: (name: string) => {
'AENS.Name': [Encoded.AccountAddress, ChainTtl, Map<string, string>];
'AENSv2.Name': [Encoded.AccountAddress, ChainTtl, Map<string, string>];
};
signedPreclaim: (addr: Encoded.AccountAddress, chash: Uint8Array, sign: Uint8Array) => void;
signedClaim: (
Expand All @@ -316,34 +316,44 @@ describe('Contract', () => {
owner: Encoded.AccountAddress,
name: string,
key: string,
pt: { 'AENS.OraclePt': readonly [Encoded.Any] },
pt: {
'AENS.OraclePt'?: readonly [Encoded.Any];
'AENSv2.OraclePt'?: readonly [Encoded.Any];
},
sign: Uint8Array
) => void;
}>;
let contractAddress: Encoded.ContractAddress;
let aens: string;

before(async () => {
const isIris = (await aeSdk.api.getNodeInfo())
.consensusProtocolVersion === ConsensusProtocolVersion.Iris;
aens = isIris ? 'AENS' : 'AENSv2';
contract = await aeSdk.initializeContract({
sourceCode:
'contract DelegateTest =\n'
+ ' entrypoint getName(name: string): option(AENS.name) =\n'
+ ' AENS.lookup(name)\n'
+ ' stateful payable entrypoint signedPreclaim(addr: address, chash: hash, sign: signature): unit =\n'
+ ' AENS.preclaim(addr, chash, signature = sign)\n'
+ ' stateful entrypoint signedClaim(\n'
+ ' addr: address, name: string, salt: int, name_fee: int, sign: signature): unit =\n'
+ ' AENS.claim(addr, name, salt, name_fee, signature = sign)\n'
+ ' stateful entrypoint signedTransfer(\n'
+ ' owner: address, new_owner: address, name: string, sign: signature): unit =\n'
+ ' AENS.transfer(owner, new_owner, name, signature = sign)\n'
+ ' stateful entrypoint signedRevoke(owner: address, name: string, sign: signature): unit =\n'
+ ' AENS.revoke(owner, name, signature = sign)\n'
+ ' stateful entrypoint signedUpdate(\n'
+ ' owner: address, name: string, key: string, pt: AENS.pointee, sig: signature) =\n'
+ ' switch(AENS.lookup(name))\n'
+ ' None => ()\n'
+ ' Some(AENS.Name(_, _, ptrs)) =>\n'
+ ' AENS.update(owner, name, None, None, Some(ptrs{[key] = pt}), signature = sig)',
sourceCode: `
@compiler ${isIris ? '>= 7' : '>= 8'}
@compiler ${isIris ? '< 8' : '< 9'}
contract DelegateTest =
entrypoint getName(name: string): option(${aens}.name) =
${aens}.lookup(name)
stateful payable entrypoint signedPreclaim(addr: address, chash: hash, sign: signature): unit =
${aens}.preclaim(addr, chash, signature = sign)
stateful entrypoint signedClaim(
addr: address, name: string, salt: int, name_fee: int, sign: signature): unit =
${aens}.claim(addr, name, salt, name_fee, signature = sign)
stateful entrypoint signedTransfer(
owner: address, new_owner: address, name: string, sign: signature): unit =
${aens}.transfer(owner, new_owner, name, signature = sign)
stateful entrypoint signedRevoke(owner: address, name: string, sign: signature): unit =
${aens}.revoke(owner, name, signature = sign)
stateful entrypoint signedUpdate(
owner: address, name: string, key: string, pt: ${aens}.pointee, sig: signature) =
switch(${aens}.lookup(name))
None => ()
Some(${aens}.Name(_, _, ptrs)) =>
${aens}.update(owner, name, None, None, Some(ptrs{[key] = pt}), signature = sig)`,
});
await contract.$deploy([]);
assertNotNull(contract.$options.address);
Expand Down Expand Up @@ -373,14 +383,14 @@ describe('Contract', () => {
});

it('gets', async () => {
const nameEntry = (await contract.getName(name)).decodedResult['AENS.Name'];
const nameEntry = (await contract.getName(name)).decodedResult[`${aens}.Name`];
expect(nameEntry[0]).to.be.equal(owner);
expect(nameEntry[1].FixedTTL[0]).to.be.a('bigint');
expect(nameEntry[2]).to.be.eql(new Map());
});

it('updates', async () => {
const pointee = { 'AENS.OraclePt': [newOwner] as const };
const pointee = { [`${aens}.OraclePt`]: [newOwner] as const };
const { result } = await contract
.signedUpdate(owner, name, 'oracle', pointee, delegationSignature);
assertNotNull(result);
Expand Down
6 changes: 5 additions & 1 deletion test/integration/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
AeSdk, CompilerHttpNode, MemoryAccount, Node, Encoded,
AeSdk, CompilerHttpNode, CompilerCli8, MemoryAccount, Node, Encoded, ConsensusProtocolVersion,
} from '../../src';
import '..';

Expand Down Expand Up @@ -36,6 +36,10 @@ export async function getSdk(accountCount = 1): Promise<AeSdk> {
_expectedMineRate: 1000,
_microBlockCycle: 300,
});
// TODO: remove after release aesophia_http@8
if ((await sdk.api.getNodeInfo()).consensusProtocolVersion === ConsensusProtocolVersion.Ceres) {
sdk._options.onCompiler = new CompilerCli8();
}
for (let i = 0; i < accounts.length; i += 1) {
await sdk.spend(1e32, accounts[i].address, { onAccount: genesisAccount });
}
Expand Down
10 changes: 7 additions & 3 deletions test/integration/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ describe('Node client', () => {

it('throws exception if unsupported protocol', async () => {
const sandbox = createSandbox();
sandbox.stub(ConsensusProtocolVersion, 'Iris').value(undefined);
sandbox.stub(ConsensusProtocolVersion, '5' as 'Iris').value(undefined);
const [name, version, message] = {
5: ['Iris', '5', '5. Supported: >= 6 < 7'],
6: ['Ceres', '6', '6. Supported: >= 5 < 6'],
}[(await node.getNodeInfo()).consensusProtocolVersion];
sandbox.stub(ConsensusProtocolVersion, name as any).value(undefined);
sandbox.stub(ConsensusProtocolVersion, version as any).value(undefined);
await expect(node.getNodeInfo()).to.be
.rejectedWith('Unsupported consensus protocol version 5. Supported: >= 6 < 7');
.rejectedWith(`Unsupported consensus protocol version ${message}`);
sandbox.restore();
});

Expand Down
Loading

0 comments on commit c5376db

Please sign in to comment.