weavedb / zkjson

Zero Knowledge Provable JSON
https://zkjson.weavedb.dev
39 stars 5 forks source link

Issue with Committing Updated Data: "wrong merkle root" Error #113

Open w-toguchi83 opened 6 months ago

w-toguchi83 commented 6 months ago

Hello,

I encountered an issue while working with the provided tutorial code for updating data in the zkDB using zkRollup. After successfully committing initial data, attempting to update a record (specifically changing "Bob's" age from 10 to 15) results in a "wrong merkle root" error during the commit phase.

Steps to Reproduce:

  1. Initialize and commit initial data to the DB.
  2. Update the age of "Bob" from 10 to 15.
  3. Attempt to commit the updated data.

Expected Result: The updated data is committed without errors, and querying "Bob's" age should return the updated value (15).

Actual Result: The commit fails with an error: "VM Exception while processing transaction: reverted with reason string 'wrong merkle root'".

I followed the documentation closely and ensured the setup for SMT levels and configurations were as recommended. Is there a specific procedure for updating data that I might have missed, or could this be a bug in the commit logic?

Thank you for looking into this issue.

    db = new DB({
      level: 100,
      size_path: 5,
      size_val: 5,
      size_json: 256,
      size_txs:10,
      level_col: 8,
      wasmRU: resolve(__dirname, "../../zkjson/circom/build/circuits/rollup/index_js/index.wasm"),
      zkeyRU: resolve(__dirname, "../../zkjson/circom/build/circuits/rollup/index_0001.zkey"),
      wasm: resolve(__dirname, "../../zkjson/circom/build/circuits/db/index_js/index.wasm"),
      zkey: resolve(__dirname, "../../zkjson/circom/build/circuits/db/index_0001.zkey"),
    });
    await db.init();

    col_id = await db.addCollection();

    const people = [
      { name: "Bob", age: 10 },
      { name: "Alice", age: 20 },
      { name: "Mike", age: 30 },
      { name: "Beth", age:40 },
    ]
    let txs = people.map(v => { return [col_id, v.name, v] })

    // batch commit write queries
    const zkp = await db.genRollupProof(txs);
    await myru.commit(zkp);

    // query Bob's age
    const zkp2 = await db.genProof({ json: people[0], col_id, path: "age", id: "Bob" });
    expect((await myru.qInt([col_id, toIndex("Bob"), ...path("age")], zkp2))).to.eql(10n)

     // How to update ?
    const people2 = [
      { name: "Bob", age: 15 }, // change age
      { name: "Alice", age: 20 },
      { name: "Mike", age: 30 },
      { name: "Beth", age:40 },
    ]
    txs = people2.map(v => { return [col_id, v.name, v] })
    const zkp3 = await db.genRollupProof(txs);
    await myru.commit(zkp3);
    // commit is faild.
    // Error: VM Exception while processing transaction: reverted with reason string 'wrong merkle root'
    // at MyRollup.commit (zkjson/contracts/ZKRollup.sol:29)

    const zkp4 = await db.genProof({ json: people2[0], col_id, path: "age", id: "Bob" });
    expect((await myru.qInt([col_id, toIndex("Bob"), ...path("age")], zkp4))).to.eql(15n)
w-toguchi83 commented 6 months ago

I am investigating an issue where commits for data updates in zkRollup are failing. Upon checking the data with console.log, I found that the values of publicSignals are not as expected. It's possible that there might be an issue with the implementation of the circuit.

Test code

const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers")
const { toIndex, path, DB } = require("zkjson")
const { resolve } = require("path")
const { expect } = require("chai")
const { ethers } = require("hardhat")

async function deploy() {
  const [committer] = await ethers.getSigners()
  const committerAddress = await committer.getAddress()

  const VerifierRU = await ethers.getContractFactory("Groth16VerifierRU")
  const verifierRU = await VerifierRU.deploy()
  const ruAddress = await verifierRU.getAddress()

  const VerifierDB = await ethers.getContractFactory("Groth16VerifierDB")
  const verifierDB = await VerifierDB.deploy()
  const dbAddress = await verifierDB.getAddress()

  const MyRU = await ethers.getContractFactory("MyRollup")
  const myru = await MyRU.deploy(ruAddress, dbAddress, committerAddress)
  return { myru, committer }
}

describe("MyRollup", function () {
  let myru, committer, db, col_id, ru
  this.timeout(0)

  beforeEach(async () => {
    const dep = await loadFixture(deploy)
    myru = dep.myru
    committer = dep.committer
  })

  it("should verify rollup transactions", async function () {
    db = new DB({
      level: 100,
      size_path: 5,
      size_val: 5,
      size_json: 256,
      size_txs: 10,
      level_col: 8,
      wasmRU: resolve(  __dirname, "../../zkjson/circom/build/circuits/rollup/index_js/index.wasm" ),
      zkeyRU: resolve(  __dirname, "../../zkjson/circom/build/circuits/rollup/index_0001.zkey" ),
      wasm: resolve(  __dirname, "../../zkjson/circom/build/circuits/db/index_js/index.wasm" ),
      zkey: resolve( __dirname, "../../zkjson/circom/build/circuits/db/index_0001.zkey" ),
    })
    await db.init()
    console.log('start frist commit')
    col_id = await db.addCollection()
    const people = [
      { name: "Bob", age: 10 },
      // { name: "Alice", age: 20 },
      // { name: "Mike", age: 30 },
      // { name: "Beth", age: 40 },
    ]
    let txs = people.map(v => { return [col_id, v.name, v] })

    // batch commit write queries
    const zkp = await db.genRollupProof(txs)
    console.log('zkp[8]', zkp[8])
    console.log('zkp[9]', zkp[9])
    await myru.commit(zkp)

    const root = await myru.root();
    console.log('root (in contract)', root)

    // query Bob's age
    const zkp2 = await db.genProof({ json: people[0], col_id, path: "age", id: "Bob" })
    expect((await myru.qInt([col_id, toIndex("Bob"), ...path("age")], zkp2))).to.eql(10n)

    console.log('start second commit')
    const people2 = [
      { name: "Bob", age: 15 },
    ]
    let txs2 = people2.map(v => { return [col_id, v.name, v] })

    const zkp3 = await db.genRollupProof(txs2)
    console.log('zkp3[8]', zkp3[8])
    console.log('zkp3[9]', zkp3[9])
    await myru.commit(zkp)

    const zkp4 = await db.genProof({ json: people2[0], col_id, path: "age", id: "Bob" })
    expect((await myru.qInt([col_id, toIndex("Bob"), ...path("age")], zkp4))).to.eql(15n)

    // // query Beth's name
    // const zkp3 = await db.genProof({ json: people[3], col_id, path: "name", id: "Beth" })
    // expect(await myru.qString([col_id, toIndex("Beth"), ...path("name")], zkp3)).to.eql("Beth")
  })
})

Output


  MyRollup
start frist commit
icol {
  isOld0: '1',
  oldRoot: '0',
  oldKey: '0',
  oldValue: '0',
  siblings: [
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0'
  ],
  newRoot: '7294141035545705951021349981065923740067743488283288208759245172731208263818'
}
idb {
  isOld0: '0',
  oldRoot: '12088914164006138162326115569229014787571257112438332540536664072415188902491',
  oldKey: '0',
  oldValue: '19014214495641488759237505126948346942972912379615652741039992445865937985820',
  siblings: [
    '0', '0', '0',
    '0', '0', '0',
    '0', '0'
  ],
  newRoot: '14817977917344487689182500492143689433810026144250121831574488334095972935844'
}
oldRoot [
  '0', '0', '0', '0',
  '0', '0', '0', '0',
  '0', '0'
]
newRoot [
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '14817977917344487689182500492143689433810026144250121831574488334095972935844'
]
oldKey [
  '0', '0', '0', '0',
  '0', '0', '0', '0',
  '0', '0'
]
oldValue [
  '0', '0', '0', '0',
  '0', '0', '0', '0',
  '0', '0'
]
newKey [
  '1014027', '0',
  '0',       '0',
  '0',       '0',
  '0',       '0',
  '0',       '0'
]
proof {
  pi_a: [
    '16940569109619169393292501172935261658295863154256494561904553675237463176108',
    '18056162424606792648200747215284504104500371945882959088492740998222145035756',
    '1'
  ],
  pi_b: [
    [
      '14392453683429184518193488388755028186637235009254042162203546630445274194485',
      '7858953337974093735124429358447653940558990577119667645903235572802382227180'
    ],
    [
      '12261006745511690370073048655998112827062415237162652393233978453176852729598',
      '17152872322933808167836777326241755917964977680299058230448022731820071703565'
    ],
    [ '1', '0' ]
  ],
  pi_c: [
    '5644409238292206350042146002276839219234655664137002174067463416432445164199',
    '1327414133046649020384032325875476092946622328739475670484572246454743621997',
    '1'
  ],
  protocol: 'groth16',
  curve: 'bn128'
}
publicSignals [
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]
zkp[8] 14817977917344487689182500492143689433810026144250121831574488334095972935844
zkp[9] 0
root (in contract) 14817977917344487689182500492143689433810026144250121831574488334095972935844n
start second commit
icol {
  isOld0: '0',
  oldRoot: '7294141035545705951021349981065923740067743488283288208759245172731208263818',
  oldKey: '1014027',
  oldValue: '2816973875829385198593578839875499027111884652455957982583883932530051577382',
  siblings: [
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '0'
  ],
  newRoot: '10587547760133226446982621596384213237037650681788053082384773290172256111078'
}
idb {
  isOld0: '0',
  oldRoot: '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  oldKey: '0',
  oldValue: '8987145217179376059810044258705348083818616085735800650834636649780348119701',
  siblings: [
    '0', '0', '0',
    '0', '0', '0',
    '0', '0'
  ],
  newRoot: '18081226326838532428602042645589552726958443303640225642050901459904108479695'
}
oldRoot [
  '7294141035545705951021349981065923740067743488283288208759245172731208263818',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]
newRoot [
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '18081226326838532428602042645589552726958443303640225642050901459904108479695'
]
oldKey [
  '1014027', '0',
  '0',       '0',
  '0',       '0',
  '0',       '0',
  '0',       '0'
]
oldValue [
  '2816973875829385198593578839875499027111884652455957982583883932530051577382',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]
newKey [
  '1014027', '0',
  '0',       '0',
  '0',       '0',
  '0',       '0',
  '0',       '0'
]
proof {
  pi_a: [
    '21103986421275259988248347367041929463638098325082231028650949452532051995210',
    '7698371110862525244392304470396468344669760766827928566994140636269112817363',
    '1'
  ],
  pi_b: [
    [
      '8757805145508427544714410704117565554420203810714038207112281467461772202808',
      '13351150380194779734663456911302884524973645020873329575784350061495617799052'
    ],
    [
      '15410989096368530348646244436214584045579102888116225298874255609235445521823',
      '6634978141458626887753779376435329275241943345415939243424928658129873720926'
    ],
    [ '1', '0' ]
  ],
  pi_c: [
    '6239743020067109487541046709274143664515235613576470864080191324968232244253',
    '6351832091170812451986866146647393331923115244979446193956517698546636815425',
    '1'
  ],
  protocol: 'groth16',
  curve: 'bn128'
}
publicSignals [
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '7294141035545705951021349981065923740067743488283288208759245172731208263818',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]
zkp3[8] 18081226326838532428602042645589552726958443303640225642050901459904108479695
zkp3[9] 7294141035545705951021349981065923740067743488283288208759245172731208263818
    1) should verify rollup transactions

  0 passing (1m)
  1 failing

  1) MyRollup
       should verify rollup transactions:
     Error: VM Exception while processing transaction: reverted with reason string 'wrong merkle root'
    at MyRollup.commit (zkjson/contracts/ZKRollup.sol:29)

Based on my observations, the publicSignals generated by the first proof are as follows:

publicSignals [
  '14817977917344487689182500492143689433810026144250121831574488334095972935844',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]

After updating the data, the publicSignals generated by the subsequent proof are:

publicSignals [
  '18081226326838532428602042645589552726958443303640225642050901459904108479695',
  '7294141035545705951021349981065923740067743488283288208759245172731208263818',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0',
  '0'
]

The value of publicSignals[1] changes to 7294141..., but according to the implementation of the zkRollup.sol contract, it should be 14871977... to avoid failure.

I suspect this might be a bug in the implementation of db.js in the SDK or in the circuit implementation. Can you help resolve this issue? I would greatly appreciate your assistance.