@lumina-dex/contracts
Version:
Contracts for Lumina DEX.
809 lines (726 loc) • 31.6 kB
text/typescript
import { FungibleToken, FungibleTokenAdmin } from "mina-fungible-token"
import {
AccountUpdate,
Bool,
Cache,
Field,
MerkleMap,
Mina,
Poseidon,
PrivateKey,
Provable,
PublicKey,
Signature,
UInt32,
UInt64,
UInt8,
VerificationKey
} from "o1js"
import { beforeAll, beforeEach, describe, expect, it } from "vitest"
import {
Multisig,
MultisigInfo,
MultisigSigner,
Pool,
PoolFactory,
PoolTokenHolder,
SignatureInfo,
SignatureRight,
UpdateAccountInfo,
UpdateFactoryInfo,
UpdateSignerData,
UpgradeInfo
} from "../dist"
const proofsEnabled = false
const vkUpgradeTest = new VerificationKey({
data:
"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",
hash: Field.from(1094855669395027188090902596744887124365128625005606285591537108109825582697n)
})
describe("Pool data", () => {
let deployerAccount: Mina.TestPublicKey,
deployerKey: PrivateKey,
senderAccount: Mina.TestPublicKey,
senderKey: PrivateKey,
senderPublic: PublicKey,
bobAccount: Mina.TestPublicKey,
bobPublic: PublicKey,
bobKey: PrivateKey,
deployer2: Mina.TestPublicKey,
deployer3: Mina.TestPublicKey,
aliceAccount: Mina.TestPublicKey,
alicePublic: PublicKey,
dylanAccount: Mina.TestPublicKey,
dylanPublic: PublicKey,
deployerPublic: PublicKey,
deployer2Public: PublicKey,
deployer3Public: PublicKey,
aliceKey: PrivateKey,
allRight: SignatureRight,
signerRight: SignatureRight,
deployRight: SignatureRight,
updatePoolRight: SignatureRight,
updateDelegatorRight: SignatureRight,
updateSignerRight: SignatureRight,
updateProtocolRight: SignatureRight,
updateFactoryRight: SignatureRight,
deployerRight: SignatureRight,
merkle: MerkleMap,
compileKey: VerificationKey,
zkAppAddress: PublicKey,
zkAppPrivateKey: PrivateKey,
zkApp: PoolFactory,
zkPoolAddress: PublicKey,
zkPoolPrivateKey: PrivateKey,
zkPool: Pool,
zkTokenAdminAddress: PublicKey,
zkTokenAdminPrivateKey: PrivateKey,
zkTokenAdmin: FungibleTokenAdmin,
zkTokenAddress: PublicKey,
zkTokenPrivateKey: PrivateKey,
zkToken: FungibleToken,
tokenHolder: PoolTokenHolder
beforeAll(async () => {
compileKey = vkUpgradeTest
const cache = Cache.FileSystem("./cache")
// const compileResult = await PoolUpgradeTest.compile({ cache, });
// console.log("poolUpgradeTest", compileResult.verificationKey.data);
// console.log("poolUpgradeTest hash", compileResult.verificationKey.hash.toBigInt());
if (proofsEnabled) {
console.time("compile PoolData")
await FungibleTokenAdmin.compile({ cache })
await FungibleToken.compile({ cache })
await PoolFactory.compile({ cache })
await Pool.compile({ cache })
await PoolTokenHolder.compile({ cache })
console.timeEnd("compile PoolData")
}
allRight = new SignatureRight(Bool(true), Bool(true), Bool(true), Bool(true), Bool(true), Bool(true))
deployerRight = new SignatureRight(Bool(true), Bool(false), Bool(true), Bool(false), Bool(false), Bool(false))
updatePoolRight = SignatureRight.canUpdatePool()
updateDelegatorRight = SignatureRight.canUpdateDelegator()
updateSignerRight = SignatureRight.canUpdateSigner()
updateProtocolRight = SignatureRight.canUpdateProtocol()
updateFactoryRight = SignatureRight.canUpdateFactory()
signerRight = SignatureRight.canUpdateSigner()
deployRight = SignatureRight.canDeployPool()
})
beforeEach(async () => {
const Local = await Mina.LocalBlockchain({ proofsEnabled })
Mina.setActiveInstance(Local)
;[deployerAccount, senderAccount, bobAccount, aliceAccount, dylanAccount, deployer2, deployer3] = Local.testAccounts
deployerKey = deployerAccount.key
senderKey = senderAccount.key
senderPublic = senderKey.toPublicKey()
dylanPublic = dylanAccount.key.toPublicKey()
bobKey = bobAccount.key
bobPublic = bobKey.toPublicKey()
aliceKey = aliceAccount.key
alicePublic = aliceKey.toPublicKey()
deployerPublic = deployerKey.toPublicKey()
deployer2Public = deployer2.key.toPublicKey()
deployer3Public = deployer3.key.toPublicKey()
merkle = new MerkleMap()
merkle.set(Poseidon.hash(deployerPublic.toFields()), allRight.hash())
merkle.set(Poseidon.hash(deployer2Public.toFields()), updateSignerRight.hash())
merkle.set(Poseidon.hash(deployer3Public.toFields()), updateSignerRight.hash())
zkAppPrivateKey = PrivateKey.random()
zkAppAddress = zkAppPrivateKey.toPublicKey()
zkApp = new PoolFactory(zkAppAddress)
zkPoolPrivateKey = PrivateKey.random()
zkPoolAddress = zkPoolPrivateKey.toPublicKey()
zkPool = new Pool(zkPoolAddress)
zkTokenAdminPrivateKey = PrivateKey.random()
zkTokenAdminAddress = zkTokenAdminPrivateKey.toPublicKey()
zkTokenAdmin = new FungibleTokenAdmin(zkTokenAdminAddress)
zkTokenPrivateKey = PrivateKey.random()
zkTokenAddress = zkTokenPrivateKey.toPublicKey()
zkToken = new FungibleToken(zkTokenAddress)
const txn = await Mina.transaction(deployerAccount, async () => {
AccountUpdate.fundNewAccount(deployerAccount, 3)
await zkTokenAdmin.deploy({
adminPublicKey: deployerAccount
})
await zkToken.deploy({
symbol: "LTA",
src: "https://github.com/MinaFoundation/mina-fungible-token/blob/main/FungibleToken.ts",
allowUpdates: false
})
await zkToken.initialize(
zkTokenAdminAddress,
UInt8.from(9),
Bool(false)
)
})
await txn.prove()
// this tx needs .sign(), because `deploy()` adds an account update that requires signature authorization
await txn.sign([deployerKey, zkAppPrivateKey, zkTokenAdminPrivateKey, zkTokenPrivateKey]).send()
})
async function deployPool() {
const root = merkle.getRoot()
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpdateSignerData({ oldRoot: Field.empty(), newRoot: root, deadlineSlot: UInt32.from(time) })
const sign1 = Signature.create(deployerKey, info.toFields())
const sign2 = Signature.create(deployer2.key, info.toFields())
const sign3 = Signature.create(deployer3.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: root,
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const info1 = new SignatureInfo({
user: deployerPublic,
witness: merkle.getWitness(Poseidon.hash(deployerPublic.toFields())),
signature: sign1,
right: allRight
})
const info2 = new SignatureInfo({
user: deployer2Public,
witness: merkle.getWitness(Poseidon.hash(deployer2Public.toFields())),
signature: sign2,
right: updateSignerRight
})
const info3 = new SignatureInfo({
user: deployer3Public,
witness: merkle.getWitness(Poseidon.hash(deployer3Public.toFields())),
signature: sign3,
right: updateSignerRight
})
const signatures = [info1, info2, info3]
const txn = await Mina.transaction(deployerAccount, async () => {
AccountUpdate.fundNewAccount(deployerAccount, 1)
await zkApp.deploy({
symbol: "FAC",
src: "https://luminadex.com/",
protocol: aliceAccount,
delegator: dylanAccount,
approvedSigner: root,
signatures: signatures,
multisigInfo: multi
})
})
await txn.prove()
// this tx needs .sign(), because `deploy()` adds an account update that requires signature authorization
await txn.sign([deployerKey, zkAppPrivateKey, zkTokenAdminPrivateKey, zkTokenPrivateKey]).send()
const signature = Signature.create(deployerKey, zkPoolAddress.toFields())
const witness = merkle.getWitness(Poseidon.hash(deployerPublic.toFields()))
const txn3 = await Mina.transaction(deployerAccount, async () => {
AccountUpdate.fundNewAccount(deployerAccount, 4)
await zkApp.createPool(zkPoolAddress, zkTokenAddress, deployerAccount, signature, witness, allRight)
})
// console.log("Pool creation au", txn3.transaction.accountUpdates.length);
await txn3.prove()
// this tx needs .sign(), because `deploy()` adds an account update that requires signature authorization
await txn3.sign([deployerKey, zkPoolPrivateKey]).send()
}
it("update pool proof", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updatePoolRight.hash())
await deployPool()
const contractAddress = zkPoolAddress
const tokenId = zkPool.tokenId
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: vkUpgradeTest.hash,
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updatePoolRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right: updatePoolRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
const txn = await Mina.transaction(deployerAccount, async () => {
await zkPool.updateVerificationKey(proof, compileKey)
})
await txn.prove()
await txn.sign([deployerKey]).send()
})
it("incorrect signer pool proof", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updateDelegatorRight.hash())
await deployPool()
const contractAddress = zkPoolAddress
const tokenId = zkPool.tokenId
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: vkUpgradeTest.hash,
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updatePoolRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right: updatePoolRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
await expect(Mina.transaction(deployerAccount, async () => {
await zkPool.updateVerificationKey(proof, compileKey)
})).rejects.toThrow("Invalid signer")
})
it("incorrect right pool proof", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updateDelegatorRight.hash())
await deployPool()
const contractAddress = zkPoolAddress
const tokenId = zkPool.tokenId
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: vkUpgradeTest.hash,
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updatePoolRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right: updateDelegatorRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
await expect(Mina.transaction(deployerAccount, async () => {
await zkPool.updateVerificationKey(proof, compileKey)
})).rejects.toThrow("User doesn't have the right for this operation")
})
it("incorrect message pool proof", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updatePoolRight.hash())
await deployPool()
const contractAddress = zkPoolAddress
const tokenId = zkPool.tokenId
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: vkUpgradeTest.hash,
deadlineSlot: UInt32.from(time)
})
const infoProof = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: Field(5000),
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
// we sign for the incorrect info
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: infoProof.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updatePoolRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right: updatePoolRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
await expect(Mina.transaction(deployerAccount, async () => {
await zkPool.updateVerificationKey(proof, compileKey)
})).rejects.toThrow("Message didn't match parameters")
})
it("incorrect signature pool proof", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updatePoolRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updatePoolRight.hash())
await deployPool()
const contractAddress = zkPoolAddress
const tokenId = zkPool.tokenId
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpgradeInfo({
contractAddress,
tokenId,
newVkHash: vkUpgradeTest.hash,
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updatePoolRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
// we pass alice signature to throy the error
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signAlice,
right: updatePoolRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
await expect(Mina.transaction(deployerAccount, async () => {
await zkPool.updateVerificationKey(proof, compileKey)
})).rejects.toThrow("Invalid signature")
})
it("update delegator", async () => {
merkle.set(Poseidon.hash(bobPublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), updateDelegatorRight.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), updateDelegatorRight.hash())
await deployPool()
const pk = PrivateKey.random()
const oldAccount = await zkApp.delegator.fetch()
const pkNew = PrivateKey.random()
const newAccount = pkNew.toPublicKey()
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpdateAccountInfo({ oldUser: oldAccount!, newUser: newAccount, deadlineSlot: UInt32.from(time) })
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right: updateDelegatorRight
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right: updateDelegatorRight
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right: updateDelegatorRight
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
const txn = await Mina.transaction(deployerAccount, async () => {
await zkApp.setNewDelegator(proof, newAccount)
})
await txn.prove()
await txn.sign([deployerKey]).send()
})
it("update protocol", async () => {
const right = updateProtocolRight
merkle.set(Poseidon.hash(bobPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), right.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), right.hash())
await deployPool()
const pk = PrivateKey.random()
const oldAccount = await zkApp.protocol.fetch()
const pkNew = PrivateKey.random()
const newAccount = pkNew.toPublicKey()
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpdateAccountInfo({ oldUser: oldAccount!, newUser: newAccount, deadlineSlot: UInt32.from(time) })
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
const txn = await Mina.transaction(deployerAccount, async () => {
await zkApp.setNewProtocol(proof, newAccount)
})
await txn.prove()
await txn.sign([deployerKey]).send()
})
it("update factory", async () => {
const right = updateFactoryRight
merkle.set(Poseidon.hash(bobPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), right.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), right.hash())
await deployPool()
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpdateFactoryInfo({ newVkHash: vkUpgradeTest.hash, deadlineSlot: UInt32.from(time) })
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right
})
const array = [infoBob, infoAlice, infoDylan]
const proof = new Multisig({ info: multi, signatures: array })
const txn = await Mina.transaction(deployerAccount, async () => {
await zkApp.updateVerificationKey(proof, vkUpgradeTest)
})
await txn.prove()
await txn.sign([deployerKey]).send()
})
it("update signer", async () => {
const right = updateSignerRight
merkle.set(Poseidon.hash(bobPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(alicePublic.toFields()), right.hash())
merkle.set(Poseidon.hash(dylanPublic.toFields()), right.hash())
merkle.set(Poseidon.hash(senderPublic.toFields()), right.hash())
await deployPool()
const newMerkle = new MerkleMap()
newMerkle.set(Poseidon.hash(bobPublic.toFields()), right.hash())
newMerkle.set(Poseidon.hash(alicePublic.toFields()), right.hash())
newMerkle.set(Poseidon.hash(deployerAccount.toFields()), right.hash())
const today = new Date()
today.setDate(today.getDate() + 1)
const tomorrow = today.getTime()
const time = getSlotFromTimestamp(tomorrow)
const info = new UpdateSignerData({
oldRoot: merkle.getRoot(),
newRoot: newMerkle.getRoot(),
deadlineSlot: UInt32.from(time)
})
Provable.log("info validate", info.toFields())
Provable.log("bob", bobPublic)
const signBob = Signature.create(bobKey, info.toFields())
const signAlice = Signature.create(aliceKey, info.toFields())
const signDylan = Signature.create(dylanAccount.key, info.toFields())
const deployerPublic = deployerAccount.key.toPublicKey()
const newsignBob = Signature.create(bobKey, info.toFields())
const newsignAlice = Signature.create(aliceKey, info.toFields())
const newsignDeployer = Signature.create(deployerAccount.key, info.toFields())
const multi = new MultisigInfo({
approvedUpgrader: merkle.getRoot(),
messageHash: info.hash(),
deadlineSlot: UInt32.from(time)
})
const infoBob = new SignatureInfo({
user: bobPublic,
witness: merkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: signBob,
right
})
const infoAlice = new SignatureInfo({
user: alicePublic,
witness: merkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: signAlice,
right
})
const infoDylan = new SignatureInfo({
user: dylanPublic,
witness: merkle.getWitness(Poseidon.hash(dylanPublic.toFields())),
signature: signDylan,
right
})
const array = [infoBob, infoAlice, infoDylan]
const newinfoBob = new SignatureInfo({
user: bobPublic,
witness: newMerkle.getWitness(Poseidon.hash(bobPublic.toFields())),
signature: newsignBob,
right
})
const newinfoAlice = new SignatureInfo({
user: alicePublic,
witness: newMerkle.getWitness(Poseidon.hash(alicePublic.toFields())),
signature: newsignAlice,
right
})
const newinfoDeployer = new SignatureInfo({
user: deployerPublic,
witness: newMerkle.getWitness(Poseidon.hash(deployerPublic.toFields())),
signature: newsignDeployer,
right
})
const newarray = [newinfoBob, newinfoAlice, newinfoDeployer]
const proof = new MultisigSigner({ info: multi, signatures: array, newSignatures: newarray })
const txn = await Mina.transaction(deployerAccount, async () => {
await zkApp.updateApprovedSigner(proof, newMerkle.getRoot())
})
await txn.prove()
await txn.sign([deployerKey]).send()
})
function getSlotFromTimestamp(date: number) {
const { genesisTimestamp, slotTime } = Mina.activeInstance.getNetworkConstants()
let slotCalculated = UInt64.from(date)
slotCalculated = (slotCalculated.sub(genesisTimestamp)).div(slotTime)
Provable.log("slotCalculated64", slotCalculated)
return slotCalculated.toUInt32()
}
})