-
Notifications
You must be signed in to change notification settings - Fork 170
/
abi.ts
120 lines (108 loc) · 3.96 KB
/
abi.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { FUNCTION_TREE_HEIGHT } from '@aztec/circuits.js/constants';
import { ContractArtifact, DebugMetadata, FunctionArtifact, FunctionType } from '@aztec/foundation/abi';
import { deflate } from 'pako';
import { mockVerificationKey } from '../mocked_keys.js';
import {
NoirCompilationResult,
NoirContractCompilationArtifacts,
NoirFunctionEntry,
NoirProgramCompilationArtifacts,
ProgramArtifact,
isNoirContractCompilationArtifacts,
isNoirProgramCompilationArtifacts,
} from '../noir_artifact.js';
/**
* Generates a function build artifact. Replaces verification key with a mock value.
* @param fn - Noir function entry.
* @returns Function artifact.
*/
function generateFunctionArtifact(fn: NoirFunctionEntry): FunctionArtifact {
const functionType = fn.function_type.toLowerCase() as FunctionType;
const isInternal = fn.is_internal;
// If the function is not unconstrained, the first item is inputs or CallContext which we should omit
let parameters = fn.abi.parameters;
if (functionType !== FunctionType.UNCONSTRAINED) {
parameters = parameters.slice(1);
}
// If the function is secret, the return is the public inputs, which should be omitted
const returnTypes = functionType === FunctionType.SECRET ? [] : [fn.abi.return_type.abi_type];
return {
name: fn.name,
functionType,
isInternal,
parameters,
returnTypes,
bytecode: fn.bytecode,
verificationKey: mockVerificationKey,
};
}
/**
* Entrypoint for generating the .json artifact for compiled contract or program
* @param compileResult - Noir build output.
* @returns Aztec contract build artifact.
*/
export function generateArtifact(compileResult: NoirCompilationResult) {
if (isNoirContractCompilationArtifacts(compileResult)) {
return generateContractArtifact(compileResult);
} else if (isNoirProgramCompilationArtifacts(compileResult)) {
return generateProgramArtifact(compileResult);
} else {
throw Error('Unsupported artifact type');
}
}
/**
* Given a Nargo output generates an Aztec-compatible contract artifact.
* @param compiled - Noir build output.
* @returns Aztec contract build artifact.
*/
export function generateProgramArtifact(
{ program }: NoirProgramCompilationArtifacts,
// eslint-disable-next-line camelcase
noir_version?: string,
): ProgramArtifact {
return {
// eslint-disable-next-line camelcase
noir_version,
hash: program.hash,
abi: program.abi,
// TODO: should we parse and write the debug? it doesn't seem to be in the nargo output
// debug: someParsedDebug,
};
}
/**
* Given a Nargo output generates an Aztec-compatible contract artifact.
* @param compiled - Noir build output.
* @returns Aztec contract build artifact.
*/
export function generateContractArtifact(
{ contract, debug }: NoirContractCompilationArtifacts,
aztecNrVersion?: string,
): ContractArtifact {
const constructorArtifact = contract.functions.find(({ name }) => name === 'constructor');
if (constructorArtifact === undefined) {
throw new Error('Contract must have a constructor function');
}
if (contract.functions.length > 2 ** FUNCTION_TREE_HEIGHT) {
throw new Error(`Contract can only have a maximum of ${2 ** FUNCTION_TREE_HEIGHT} functions`);
}
const originalFunctions = contract.functions;
// TODO why sort? we should have idempotent compilation so this should not be needed.
const sortedFunctions = [...contract.functions].sort((fnA, fnB) => fnA.name.localeCompare(fnB.name));
let parsedDebug: DebugMetadata | undefined = undefined;
if (debug) {
parsedDebug = {
debugSymbols: sortedFunctions.map(fn => {
const originalIndex = originalFunctions.indexOf(fn);
return Buffer.from(deflate(JSON.stringify(debug.debug_symbols[originalIndex]))).toString('base64');
}),
fileMap: debug.file_map,
};
}
return {
name: contract.name,
functions: sortedFunctions.map(generateFunctionArtifact),
events: contract.events,
debug: parsedDebug,
aztecNrVersion,
};
}