Skip to content

Commit

Permalink
Add RPC route to get note witness (#3666)
Browse files Browse the repository at this point in the history
  • Loading branch information
danield9tqh authored Mar 20, 2023
1 parent 6bbd5e2 commit 681c533
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 0 deletions.
10 changes: 10 additions & 0 deletions ironfish/src/rpc/clients/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import {
FollowChainStreamRequest,
FollowChainStreamResponse,
} from '../routes/chain/followChain'
import { GetNoteWitnessRequest, GetNoteWitnessResponse } from '../routes/chain/getNoteWitness'
import { UnsetConfigRequest, UnsetConfigResponse } from '../routes/config/unsetConfig'
import { OnGossipRequest, OnGossipResponse } from '../routes/events/onGossip'
import { GetMempoolTransactionResponse, GetMempoolTransactionsRequest } from '../routes/mempool'
Expand Down Expand Up @@ -503,6 +504,15 @@ export abstract class RpcClient {
).waitForEnd()
}

async getNoteWitness(
params: GetNoteWitnessRequest,
): Promise<RpcResponseEnded<GetNoteWitnessResponse>> {
return this.request<GetNoteWitnessResponse>(
`${ApiNamespace.chain}/getNoteWitness`,
params,
).waitForEnd()
}

async getNetworkHashPower(
params: GetNetworkHashPowerRequest,
): Promise<RpcResponseEnded<GetNetworkHashPowerResponse>> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"Route chain/getNoteWitness gets note witness for each note": [
{
"header": {
"sequence": 2,
"previousBlockHash": "AD35193FA159CFD7440A3DFDFBE7ACB720CB4A44A441AB933071E2B9EF5DE90B",
"noteCommitment": {
"type": "Buffer",
"data": "base64:hiVOrI6oJ1Ms1eX1IBms4Uoyggdk0QzrGb0XrR/brS0="
},
"transactionCommitment": {
"type": "Buffer",
"data": "base64:HTrozZcyI5ZylBf2rmmPO8LnbZYXUfzfFF8gUHwoR9I="
},
"target": "883423532389192164791648750371459257913741948437809479060803100646309888",
"randomness": "0",
"timestamp": 1679330947014,
"graffiti": "0000000000000000000000000000000000000000000000000000000000000000",
"noteSize": 4,
"work": "0"
},
"transactions": [
{
"type": "Buffer",
"data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAA91o8dTAh10QXCU6kqJWBhw2CfkCjNeAVNtAdzzRAhACjw2VcKhx3owxycbs+9d+DKi0JRx0Osj/my+2RB+GFjOLgxo2G1JJxNAmXgN3RVv6gPdRgjUeLKW/Eawn8ijjlvpXsAOUxyp5WVo2FfZH8C3E1BH50Sukd1itylRGRFpUEkEZEupW/uG1Mnugx3aP3yV375m6O37XhJm4pn/5bMRbfauk7wCtCvfVXIRdYFg2QFEPFfWebCVm3DGgsyVNned5u7U2Klff2w2hPm+Z8PnX5TMk+M60hbE1Zck3BfoFhl4as4VuBPfDMQgN5Sydr8dmRtgC3vTyNCAGTBxNsDwKviUclm8JB/nwKUbHD6WY6SU3/O+w7B9L+KiRjtK8UhrrNX47sRos5nWuMyhC8GtMRd3PUipbdkxU7lzZAY/DWLDYrla4cTG03kX4zd2NYXH6lqo3XqdeaffifgaMllNIgddS/hYyfPFy5WCJvR6f47+RRRDXUc/tpuVIaLvbBWkh2jtKvHNNDeZEEAt6LJehVNbPKC1QuW6le2HH/Dtik6qLNS9Icg7eyeZ9BT6QWxbnZaGomudJ94aTLb6exJnZX2+sNxPDAxwUeT3blQmxw7y1c80O+Bklyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIIXr9SfODshZ/C7zdN0Z1PAOTHikT/vQ3RUAYXLgtnN82G7HFdcA0S6PBBbwoHHJESxl71GBWqPgPBPNrnB8Cw=="
}
]
},
{
"header": {
"sequence": 3,
"previousBlockHash": "FE68FE030B5023C10C51B5DE411FF3B5661304D893B9EC395A07536BFFBF737E",
"noteCommitment": {
"type": "Buffer",
"data": "base64:Ev7qX+BqP17qwj01E+TWpEjgm44nkGnhxUXbDdaAEjI="
},
"transactionCommitment": {
"type": "Buffer",
"data": "base64:Qc1NhUUOfBL5eKX5bw6TrdtWLrKUBrD4astRw+apkp8="
},
"target": "880842937844725196442695540779332307793253899902937591585455087694081134",
"randomness": "0",
"timestamp": 1679330947305,
"graffiti": "0000000000000000000000000000000000000000000000000000000000000000",
"noteSize": 5,
"work": "0"
},
"transactions": [
{
"type": "Buffer",
"data": "base64:AQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGzKiP////8AAAAAMa3fPgpzeyJsSv1tBDmdH2lUW6Q8whSMyjnz3OlzchSS08/5mqDemfCbhBG9WJ7bZdPo+OX4DNrjUdmykc7O8d3pcvPqklE/F0kkpPQ4UMOhb9wvS8DplsqXv62tF/FbzUJPR99IBSAtslENM1gCTuVs7nNGEfN89ZbgLc6B18QIGJnUiVtlzBsdK3S42WvbG9w/S9pNTgFMh2JKzPpEPSqLJ1Vw5fsSZH2LlEyKjReHiAaveyuDlssX4dVv2TttoebKF9MNd+WbS6rxzKBZxyCW+/yhIjhFB2jdinRyhRAvg+iOtlrWgh99SzMImRZDeH8m4fdv8/Nme7AC5Q852/FAUpUElYV1k2cY6BKN3dPIVqiON4KDMS16z7rsHNoGg9hTbm35hMvn2GKUgpiC8+BJ01YtJxB3Rou3bixSbAfjZzyhxWiblX6uPU5NP+xXeQ2HgxG/5fe4BwBoFahHx/7oYpsm/ohXFHWa6AaeoPEaHQc5zTa5KbNd9KoPswVO4G2x7qDeoSEsirHxXbJkBIpa4ySgbW3McNRdXRztSVxsSAxMqJNScWp3MeG2CCX7sLc1kNSXV6+Lynl5qTmkslxvfR0vy3pdMRqRsd5JV0vRLOwjZkM8q0lyb24gRmlzaCBub3RlIGVuY3J5cHRpb24gbWluZXIga2V5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZHgBK/pPT44sDik7CCufnnmkpJWOPhcevzZjglMOy8rZ0or4x1/xve21G+jD10AiY7lSwg/xROI4vuKA1zmcAQ=="
}
]
}
]
}
44 changes: 44 additions & 0 deletions ironfish/src/rpc/routes/chain/getNoteWitness.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { Assert } from '../../../assert'
import { useMinerBlockFixture } from '../../../testUtilities'
import { createRouteTest } from '../../../testUtilities/routeTest'
import { GetNoteWitnessResponse } from './getNoteWitness'

describe('Route chain/getNoteWitness', () => {
const routeTest = createRouteTest()

it('gets note witness for each note', async () => {
const { chain } = routeTest
await chain.open()

const block1 = await useMinerBlockFixture(chain)
await expect(chain).toAddBlock(block1)
const block2 = await useMinerBlockFixture(chain)
await expect(chain).toAddBlock(block2)

const noteSize = await chain.notes.size()

for (const index of Array.from(Array(noteSize).keys())) {
const response = await routeTest.client
.request<GetNoteWitnessResponse>('chain/getNoteWitness', { index })
.waitForEnd()

const witness = await chain.notes.witness(index)
Assert.isNotNull(witness)

expect(response.content.rootHash).toEqual(witness.rootHash.toString('hex'))
expect(response.content.treeSize).toEqual(witness.treeSize())

const expectedAuthPath = witness.authenticationPath.map((step) => {
return {
side: step.side,
hashOfSibling: step.hashOfSibling.toString('hex'),
}
})

expect(response.content.authPath).toEqual(expectedAuthPath)
}
})
})
68 changes: 68 additions & 0 deletions ironfish/src/rpc/routes/chain/getNoteWitness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import * as yup from 'yup'
import { ValidationError } from '../../adapters'
import { ApiNamespace, router } from '../router'

export type GetNoteWitnessRequest = {
index: number
}

export type GetNoteWitnessResponse = {
treeSize: number
rootHash: string
authPath: {
side: 'Left' | 'Right'
hashOfSibling: string
}[]
}

export const GetNoteWitnessRequestSchema: yup.ObjectSchema<GetNoteWitnessRequest> = yup
.object({
index: yup.number().min(0).defined(),
})
.defined()

export const GetNoteWitnessResponseSchema: yup.ObjectSchema<GetNoteWitnessResponse> = yup
.object({
treeSize: yup.number().defined(),
rootHash: yup.string().defined(),
authPath: yup
.array(
yup
.object({
side: yup.string().oneOf(['Left', 'Right']).defined(),
hashOfSibling: yup.string().defined(),
})
.defined(),
)
.defined(),
})
.defined()

router.register<typeof GetNoteWitnessRequestSchema, GetNoteWitnessResponse>(
`${ApiNamespace.chain}/getNoteWitness`,
GetNoteWitnessRequestSchema,
async (request, node): Promise<void> => {
const { chain } = node
const witness = await chain.notes.witness(request.data.index)

if (witness === null) {
throw new ValidationError(`No notes exist with index ${request.data.index}`)
}

const authPath = witness.authenticationPath.map((step) => {
return {
side: step.side,
hashOfSibling: step.hashOfSibling.toString('hex'),
}
})

request.end({
treeSize: witness.treeSize(),
rootHash: witness.rootHash.toString('hex'),
authPath,
})
},
)
1 change: 1 addition & 0 deletions ironfish/src/rpc/routes/chain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './showChain'
export * from './getConsensusParameters'
export * from './getAsset'
export * from './getNetworkInfo'
export * from './getNoteWitness'

0 comments on commit 681c533

Please sign in to comment.