Skip to content

Commit

Permalink
feat: suport deploying contracts with public keys in txe (#11882)
Browse files Browse the repository at this point in the history
Resolves #11881
  • Loading branch information
sklppy88 authored Feb 10, 2025
1 parent 9239b4f commit 94bdc85
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 17 deletions.
6 changes: 3 additions & 3 deletions noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ pub unconstrained fn deploy<let N: u32, let M: u32, let P: u32>(
name: str<M>,
initializer: str<P>,
args: [Field],
public_keys_hash: Field,
secret: Field,
) -> ContractInstance {
let instance_fields = oracle_deploy(path, name, initializer, args, public_keys_hash);
let instance_fields = oracle_deploy(path, name, initializer, args, secret);
ContractInstance::deserialize(instance_fields)
}

Expand Down Expand Up @@ -110,7 +110,7 @@ unconstrained fn oracle_deploy<let N: u32, let M: u32, let P: u32>(
name: str<M>,
initializer: str<P>,
args: [Field],
public_keys_hash: Field,
secret: Field,
) -> [Field; CONTRACT_INSTANCE_LENGTH] {}

#[oracle(directStorageWrite)]
Expand Down
22 changes: 20 additions & 2 deletions noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,29 @@ impl TestEnvironment {
path: str<N>,
name: str<M>,
) -> Deployer<N, M> {
Deployer { path, name, public_keys_hash: 0 }
Deployer { path, name, secret: 0 }
}

pub unconstrained fn deploy_self<let M: u32>(_self: Self, name: str<M>) -> Deployer<0, M> {
Deployer { path: "", name, public_keys_hash: 0 }
Deployer { path: "", name, secret: 0 }
}

// Deploying with public keys assumes secret != 0
pub unconstrained fn deploy_with_public_keys<let N: u32, let M: u32>(
_self: Self,
path: str<N>,
name: str<M>,
secret: Field,
) -> Deployer<N, M> {
Deployer { path, name, secret }
}

pub unconstrained fn deploy_self_with_public_keys<let M: u32>(
_self: Self,
name: str<M>,
secret: Field,
) -> Deployer<0, M> {
Deployer { path: "", name, secret }
}

pub unconstrained fn assert_public_call_fails<C, let M: u32>(_self: Self, call_interface: C)
Expand Down
10 changes: 5 additions & 5 deletions noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::oracle::execution_cache;
pub struct Deployer<let N: u32, let M: u32> {
pub path: str<N>,
pub name: str<M>,
pub public_keys_hash: Field,
pub secret: Field,
}

impl<let N: u32, let M: u32> Deployer<N, M> {
Expand All @@ -38,7 +38,7 @@ impl<let N: u32, let M: u32> Deployer<N, M> {
self.name,
call_interface.get_name(),
call_interface.get_args(),
self.public_keys_hash,
self.secret,
);
cheatcodes::advance_blocks_by(1);
let inputs = cheatcodes::get_private_context_inputs(get_block_number() - 1);
Expand Down Expand Up @@ -68,7 +68,7 @@ impl<let N: u32, let M: u32> Deployer<N, M> {
self.name,
call_interface.get_name(),
call_interface.get_args(),
self.public_keys_hash,
self.secret,
);
cheatcodes::advance_blocks_by(1);

Expand Down Expand Up @@ -98,7 +98,7 @@ impl<let N: u32, let M: u32> Deployer<N, M> {
self.name,
call_interface.get_name(),
call_interface.get_args(),
self.public_keys_hash,
self.secret,
);
cheatcodes::advance_blocks_by(1);

Expand All @@ -115,7 +115,7 @@ impl<let N: u32, let M: u32> Deployer<N, M> {
}

pub unconstrained fn without_initializer(self) -> ContractInstance {
cheatcodes::deploy(self.path, self.name, "", &[], self.public_keys_hash)
cheatcodes::deploy(self.path, self.name, "", &[], self.secret)
}
}

Expand Down
16 changes: 10 additions & 6 deletions yarn-project/txe/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
fromArray,
fromSingle,
toForeignCallResult,
toSingle,
} from './util/encoding.js';

const TXESessions = new Map<number, TXEService>();
Expand Down Expand Up @@ -68,11 +69,13 @@ class TXEDispatcher {
);

const decodedArgs = fromArray(inputs[4] as ForeignCallArray);
const publicKeysHashFr = fromSingle(inputs[5] as ForeignCallSingle);
const secret = fromSingle(inputs[5] as ForeignCallSingle);
const publicKeys = secret.equals(Fr.ZERO) ? PublicKeys.default() : (await deriveKeys(secret)).publicKeys;
const publicKeysHash = await publicKeys.hash();

const cacheKey = `${pathStr}-${contractName}-${initializer}-${decodedArgs
.map(arg => arg.toString())
.join('-')}-${publicKeysHashFr}`;
.join('-')}-${publicKeysHash.toString()}`;

let artifact;
let instance;
Expand Down Expand Up @@ -105,21 +108,22 @@ class TXEDispatcher {
this.logger.debug(`Loading compiled artifact ${artifactPath}`);
artifact = loadContractArtifact(JSON.parse(await readFile(artifactPath, 'utf-8')));
this.logger.debug(
`Deploy ${artifact.name} with initializer ${initializer}(${decodedArgs}) and public keys hash ${publicKeysHashFr}`,
`Deploy ${
artifact.name
} with initializer ${initializer}(${decodedArgs}) and public keys hash ${publicKeysHash.toString()}`,
);
instance = await getContractInstanceFromDeployParams(artifact, {
constructorArgs: decodedArgs,
skipArgsDecoding: true,
salt: Fr.ONE,
// TODO: Modify this to allow for passing public keys.
publicKeys: PublicKeys.default(),
publicKeys,
constructorArtifact: initializer ? initializer : undefined,
deployer: AztecAddress.ZERO,
});
TXEArtifactsCache.set(cacheKey, { artifact, instance });
}

inputs.splice(0, 2, artifact, instance);
inputs.splice(0, 2, artifact, instance, toSingle(secret));
}

async #processAddAccountInputs({ inputs }: TXEForeignCallInput) {
Expand Down
6 changes: 5 additions & 1 deletion yarn-project/txe/src/txe_service/txe_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,16 @@ export class TXEService {
return toForeignCallResult(keys.publicKeys.toFields().map(toSingle));
}

async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress) {
async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: ForeignCallSingle) {
// Emit deployment nullifier
(this.typedOracle as TXE).addSiloedNullifiersFromPublic([
await siloNullifier(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), instance.address.toField()),
]);

if (!fromSingle(secret).equals(Fr.ZERO)) {
await this.createAccount(secret);
}

this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
await (this.typedOracle as TXE).addContractInstance(instance);
await (this.typedOracle as TXE).addContractArtifact(instance.contractClassId, artifact);
Expand Down

0 comments on commit 94bdc85

Please sign in to comment.