Skip to content

Commit c4d7e93

Browse files
committed
create proofs with post state
1 parent dbd9bfc commit c4d7e93

6 files changed

+349
-86
lines changed

proof_ipa.go

+157-48
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@ type Proof struct {
5858
Cs []*Point // commitments, sorted by their path in the tree
5959
PoaStems [][]byte // stems proving another stem is absent
6060
Keys [][]byte
61-
Values [][]byte
61+
PreValues [][]byte
62+
PostValues [][]byte
6263
}
6364

6465
type SuffixStateDiff struct {
6566
Suffix byte `json:"suffix"`
6667
CurrentValue *[32]byte `json:"currentValue"`
68+
NewValue *[32]byte `json:"newValue"`
6769
}
6870

6971
type SuffixStateDiffs []SuffixStateDiff
@@ -80,38 +82,78 @@ func GetCommitmentsForMultiproof(root VerkleNode, keys [][]byte, resolver NodeRe
8082
return root.GetProofItems(keylist(keys), resolver)
8183
}
8284

83-
func MakeVerkleMultiProof(root VerkleNode, keys [][]byte, resolver NodeResolverFn) (*Proof, []*Point, []byte, []*Fr, error) {
85+
// getProofElementsFromTree factors the logic that is used both in the proving and verification methods. It takes a pre-state
86+
// tree and an optional post-state tree, extracts the proof data from them and returns all the items required to build/verify
87+
// a proof.
88+
func getProofElementsFromTree(preroot, postroot VerkleNode, keys [][]byte, resolver NodeResolverFn) (*ProofElements, []byte, [][]byte, [][]byte, []*Point, [][]Fr, []*Fr, []byte, error) {
8489
// go-ipa won't accept no key as an input, catch this corner case
8590
// and return an empty result.
8691
if len(keys) == 0 {
87-
return nil, nil, nil, nil, errors.New("no key provided for proof")
92+
return nil, nil, nil, nil, nil, nil, nil, nil, errors.New("no key provided for proof")
8893
}
8994

90-
tr := common.NewTranscript("vt")
91-
root.Commit()
95+
pe, es, poas, err := GetCommitmentsForMultiproof(preroot, keys, resolver)
96+
if err != nil {
97+
return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("error getting pre-state proof data: %w", err)
98+
}
99+
100+
// List of points and vectors and indices used to generate the IPA proof
101+
// If only a pre-state root is available, it's a simple copy, but if both
102+
// pre- and post-state root are present, it's merging the two lists.
103+
var (
104+
proof_cis []*Point
105+
proof_fs [][]Fr
106+
proof_zs []uint8
107+
proof_ys []*Fr
108+
postvals = make([][]byte, len(keys))
109+
)
110+
for i := range pe.Cis {
111+
proof_cis = append(proof_cis, pe.Cis[i])
112+
proof_fs = append(proof_fs, pe.Fis[i])
113+
proof_ys = append(proof_ys, pe.Yis[i])
114+
proof_zs = append(proof_zs, pe.Zis[i])
115+
}
92116

93-
pe, es, poas, err := GetCommitmentsForMultiproof(root, keys, resolver)
117+
// if a post-state tree is present, merge its proof elements with
118+
// those of the pre-state tree, so that they can be proved together.
119+
if postroot != nil {
120+
pe_post, _, _, err := GetCommitmentsForMultiproof(postroot, keys, resolver)
121+
if err != nil {
122+
return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("error getting post-state proof data: %w", err)
123+
}
124+
125+
for i := range pe_post.Cis {
126+
proof_cis = append(proof_cis, pe_post.Cis[i])
127+
proof_fs = append(proof_fs, pe_post.Fis[i])
128+
proof_ys = append(proof_ys, pe_post.Yis[i])
129+
proof_zs = append(proof_zs, pe_post.Zis[i])
130+
}
131+
132+
// Set the post values, if they are untouched, leave them `nil`
133+
for i, v := range pe.Vals {
134+
if !bytes.Equal(v, pe_post.Vals[i]) {
135+
postvals[i] = pe_post.Vals[i]
136+
}
137+
}
138+
}
139+
140+
// [0:3]: proof elements of the pre-state trie for serialization,
141+
// 3: values to be inserted in the post-state trie for serialization
142+
// [4:8]: aggregated pre+post elements for proving
143+
return pe, es, poas, postvals, proof_cis, proof_fs, proof_ys, proof_zs, nil
144+
}
145+
146+
func MakeVerkleMultiProof(preroot, postroot VerkleNode, keys [][]byte, resolver NodeResolverFn) (*Proof, []*Point, []byte, []*Fr, error) {
147+
pe, es, poas, postvals, proof_cis, proof_fs, _, proof_zs, err := getProofElementsFromTree(preroot, postroot, keys, resolver)
94148
if err != nil {
95149
return nil, nil, nil, nil, fmt.Errorf("get commitments for multiproof: %s", err)
96150
}
97151

98-
// NOTE this is leftover code from the time the proof was
99-
// made against the POST state. Since proofs are expected
100-
// to prove PRE and POST state in the future, I'm leaving
101-
// this for reference - eventhough it's unlikely that the
102-
// final version will look like this, but you never know.
103-
// var vals [][]byte
104-
// for _, k := range keys {
105-
// // TODO at the moment, do not include the post-data
106-
// // val, _ := root.Get(k, nil)
107-
// // vals = append(vals, val)
108-
// vals = append(vals, keyvals[string(k)])
109-
// }
110-
111152
cfg := GetConfig()
112-
mpArg, err := ipa.CreateMultiProof(tr, cfg.conf, pe.Cis, pe.Fis, pe.Zis)
153+
tr := common.NewTranscript("vt")
154+
mpArg, err := ipa.CreateMultiProof(tr, cfg.conf, proof_cis, proof_fs, proof_zs)
113155
if err != nil {
114-
return nil, nil, nil, nil, fmt.Errorf("creating multiproof: %s", err)
156+
return nil, nil, nil, nil, fmt.Errorf("creating multiproof: %w", err)
115157
}
116158

117159
// It's wheel-reinvention time again 🎉: reimplement a basic
@@ -130,17 +172,34 @@ func MakeVerkleMultiProof(root VerkleNode, keys [][]byte, resolver NodeResolverF
130172
for i, path := range paths {
131173
cis[i] = pe.ByPath[path]
132174
}
175+
133176
proof := &Proof{
134177
Multipoint: mpArg,
135178
Cs: cis,
136179
ExtStatus: es,
137180
PoaStems: poas,
138181
Keys: keys,
139-
Values: pe.Vals,
182+
PreValues: pe.Vals,
183+
PostValues: postvals,
140184
}
141185
return proof, pe.Cis, pe.Zis, pe.Yis, nil
142186
}
143187

188+
// VerifyVerkleProofWithPreAndPostTrie takes a pre-state trie, a post-state trie and a list of keys, and verifies that
189+
// the provided proof verifies. If the post-state trie is `nil`, the behavior is the same as `VerifyVerkleProof`.
190+
func VerifyVerkleProofWithPreAndPostTrie(proof *Proof, preroot, postroot VerkleNode) error {
191+
_, _, _, _, proof_cis, _, proof_ys, proof_zs, err := getProofElementsFromTree(preroot, postroot, proof.Keys, nil)
192+
if err != nil {
193+
return fmt.Errorf("error getting proof elements: %w", err)
194+
}
195+
196+
if ok, err := VerifyVerkleProof(proof, proof_cis, proof_zs, proof_ys, GetConfig()); !ok || err != nil {
197+
return fmt.Errorf("error verifying proof: verifies=%v, error=%w", ok, err)
198+
}
199+
200+
return nil
201+
}
202+
144203
func VerifyVerkleProof(proof *Proof, Cs []*Point, indices []uint8, ys []*Fr, tc *Config) (bool, error) {
145204
tr := common.NewTranscript("vt")
146205
return ipa.CheckMultiProof(tr, tc.conf, proof.Multipoint, Cs, ys, indices)
@@ -181,26 +240,35 @@ func SerializeProof(proof *Proof) (*VerkleProof, StateDiff, error) {
181240
stemdiff = &statediff[len(statediff)-1]
182241
copy(stemdiff.Stem[:], key[:31])
183242
}
184-
var valueLen = len(proof.Values[i])
243+
stemdiff.SuffixDiffs = append(stemdiff.SuffixDiffs, SuffixStateDiff{Suffix: key[31]})
244+
newsd := &stemdiff.SuffixDiffs[len(stemdiff.SuffixDiffs)-1]
245+
246+
var valueLen = len(proof.PreValues[i])
247+
switch valueLen {
248+
case 0:
249+
// null value
250+
case 32:
251+
newsd.CurrentValue = (*[32]byte)(proof.PreValues[i])
252+
default:
253+
var aligned [32]byte
254+
copy(aligned[:valueLen], proof.PreValues[i])
255+
newsd.CurrentValue = (*[32]byte)(unsafe.Pointer(&aligned[0]))
256+
}
257+
258+
valueLen = len(proof.PostValues[i])
185259
switch valueLen {
186260
case 0:
187-
stemdiff.SuffixDiffs = append(stemdiff.SuffixDiffs, SuffixStateDiff{
188-
Suffix: key[31],
189-
})
261+
// null value
190262
case 32:
191-
stemdiff.SuffixDiffs = append(stemdiff.SuffixDiffs, SuffixStateDiff{
192-
Suffix: key[31],
193-
CurrentValue: (*[32]byte)(proof.Values[i]),
194-
})
263+
newsd.NewValue = (*[32]byte)(proof.PostValues[i])
195264
default:
265+
// TODO remove usage of unsafe
196266
var aligned [32]byte
197-
copy(aligned[:valueLen], proof.Values[i])
198-
stemdiff.SuffixDiffs = append(stemdiff.SuffixDiffs, SuffixStateDiff{
199-
Suffix: key[31],
200-
CurrentValue: (*[32]byte)(unsafe.Pointer(&aligned[0])),
201-
})
267+
copy(aligned[:valueLen], proof.PostValues[i])
268+
newsd.NewValue = (*[32]byte)(unsafe.Pointer(&aligned[0]))
202269
}
203270
}
271+
204272
return &VerkleProof{
205273
OtherStems: otherstems,
206274
DepthExtensionPresent: proof.ExtStatus,
@@ -218,10 +286,11 @@ func SerializeProof(proof *Proof) (*VerkleProof, StateDiff, error) {
218286
// can be used to rebuild a stateless version of the tree.
219287
func DeserializeProof(vp *VerkleProof, statediff StateDiff) (*Proof, error) {
220288
var (
221-
poaStems, keys, values [][]byte
222-
extStatus []byte
223-
commitments []*Point
224-
multipoint ipa.MultiProof
289+
poaStems, keys [][]byte
290+
prevalues, postvalues [][]byte
291+
extStatus []byte
292+
commitments []*Point
293+
multipoint ipa.MultiProof
225294
)
226295

227296
poaStems = make([][]byte, len(vp.OtherStems))
@@ -259,9 +328,15 @@ func DeserializeProof(vp *VerkleProof, statediff StateDiff) (*Proof, error) {
259328
k[31] = suffixdiff.Suffix
260329
keys = append(keys, k[:])
261330
if suffixdiff.CurrentValue != nil {
262-
values = append(values, suffixdiff.CurrentValue[:])
331+
prevalues = append(prevalues, suffixdiff.CurrentValue[:])
263332
} else {
264-
values = append(values, nil)
333+
prevalues = append(prevalues, nil)
334+
}
335+
336+
if suffixdiff.NewValue != nil {
337+
postvalues = append(postvalues, suffixdiff.NewValue[:])
338+
} else {
339+
postvalues = append(postvalues, nil)
265340
}
266341
}
267342
}
@@ -272,7 +347,8 @@ func DeserializeProof(vp *VerkleProof, statediff StateDiff) (*Proof, error) {
272347
commitments,
273348
poaStems,
274349
keys,
275-
values,
350+
prevalues,
351+
postvalues,
276352
}
277353
return &proof, nil
278354
}
@@ -285,8 +361,8 @@ type stemInfo struct {
285361
stem []byte
286362
}
287363

288-
// TreeFromProof builds a stateless tree from the proof
289-
func TreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // skipcq: GO-R1005
364+
// PreStateTreeFromProof builds a stateless prestate tree from the proof.
365+
func PreStateTreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // skipcq: GO-R1005
290366
stems := make([][]byte, 0, len(proof.Keys))
291367
for _, k := range proof.Keys {
292368
if len(stems) == 0 || !bytes.Equal(stems[len(stems)-1], k[:31]) {
@@ -322,8 +398,8 @@ func TreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // skipcq:
322398
stemPath := stems[stemIndex][:len(path)]
323399
si.values = map[byte][]byte{}
324400
for i, k := range proof.Keys {
325-
if bytes.Equal(k[:len(path)], stemPath) && proof.Values[i] != nil {
326-
si.values[k[31]] = proof.Values[i]
401+
if bytes.Equal(k[:len(path)], stemPath) && proof.PreValues[i] != nil {
402+
si.values[k[31]] = proof.PreValues[i]
327403
si.has_c1 = si.has_c1 || (k[31] < 128)
328404
si.has_c2 = si.has_c2 || (k[31] >= 128)
329405
// This key has values, its stem is the one that
@@ -356,14 +432,14 @@ func TreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // skipcq:
356432
// but not for block validation.
357433
values := make([][]byte, NodeWidth)
358434
for i, k := range proof.Keys {
359-
if len(proof.Values[i]) == 0 {
435+
if len(proof.PreValues[i]) == 0 {
360436
// Skip the nil keys, they are here to prove
361437
// an absence.
362438
continue
363439
}
364440

365441
if bytes.Equal(k[:31], info[string(p)].stem) {
366-
values[k[31]] = proof.Values[i]
442+
values[k[31]] = proof.PreValues[i]
367443
}
368444
}
369445
comms, err = root.CreatePath(p, info[string(p)], comms, values)
@@ -374,3 +450,36 @@ func TreeFromProof(proof *Proof, rootC *Point) (VerkleNode, error) { // skipcq:
374450

375451
return root, nil
376452
}
453+
454+
// PostStateTreeFromProof uses the pre-state trie and the list of updated values
455+
// to produce the stateless post-state trie.
456+
func PostStateTreeFromProof(preroot VerkleNode, statediff StateDiff) (VerkleNode, error) {
457+
postroot := preroot.Copy()
458+
459+
for _, stemstatediff := range statediff {
460+
var (
461+
values = make([][]byte, NodeWidth)
462+
overwrites bool
463+
)
464+
465+
for _, suffixdiff := range stemstatediff.SuffixDiffs {
466+
if /* len(suffixdiff.NewValue) > 0 - this only works for a slice */ suffixdiff.NewValue != nil {
467+
// if this value is non-nil, it means InsertStem should be
468+
// called, otherwise, skip updating the tree.
469+
overwrites = true
470+
values[suffixdiff.Suffix] = suffixdiff.NewValue[:]
471+
}
472+
}
473+
474+
if overwrites {
475+
var stem [31]byte
476+
copy(stem[:31], stemstatediff.Stem[:])
477+
if err := postroot.(*InternalNode).InsertStem(stem[:], values, nil); err != nil {
478+
return nil, fmt.Errorf("error overwriting value in post state: %w", err)
479+
}
480+
}
481+
}
482+
postroot.Commit()
483+
484+
return postroot, nil
485+
}

proof_json.go

+20-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func (vp *VerkleProof) UnmarshalJSON(data []byte) error {
147147
var aux verkleProofMarshaller
148148
err := json.Unmarshal(data, &aux)
149149
if err != nil {
150-
return err
150+
return fmt.Errorf("verkle proof unmarshal error: %w", err)
151151
}
152152

153153
vp.DepthExtensionPresent, err = PrefixedHexStringToBytes(aux.DepthExtensionPresent)
@@ -198,7 +198,7 @@ func (ssd StemStateDiff) MarshalJSON() ([]byte, error) {
198198
func (ssd *StemStateDiff) UnmarshalJSON(data []byte) error {
199199
var aux stemStateDiffMarshaller
200200
if err := json.Unmarshal(data, &aux); err != nil {
201-
return err
201+
return fmt.Errorf("stemdiff unmarshal error: %w", err)
202202
}
203203

204204
stem, err := PrefixedHexStringToBytes(aux.Stem)
@@ -215,25 +215,31 @@ func (ssd *StemStateDiff) UnmarshalJSON(data []byte) error {
215215
type suffixStateDiffMarshaller struct {
216216
Suffix byte `json:"suffix"`
217217
CurrentValue *string `json:"currentValue"`
218+
NewValue *string `json:"newValue"`
218219
}
219220

220221
func (ssd SuffixStateDiff) MarshalJSON() ([]byte, error) {
221-
var cvstr *string
222+
var cvstr, nvstr *string
222223
if ssd.CurrentValue != nil {
223224
tempstr := HexToPrefixedString(ssd.CurrentValue[:])
224225
cvstr = &tempstr
225226
}
227+
if ssd.NewValue != nil {
228+
tempstr := HexToPrefixedString(ssd.NewValue[:])
229+
nvstr = &tempstr
230+
}
226231
return json.Marshal(&suffixStateDiffMarshaller{
227232
Suffix: ssd.Suffix,
228233
CurrentValue: cvstr,
234+
NewValue: nvstr,
229235
})
230236
}
231237

232238
func (ssd *SuffixStateDiff) UnmarshalJSON(data []byte) error {
233239
aux := &suffixStateDiffMarshaller{}
234240

235241
if err := json.Unmarshal(data, &aux); err != nil {
236-
return err
242+
return fmt.Errorf("suffix diff unmarshal error: %w", err)
237243
}
238244

239245
if aux.CurrentValue != nil && len(*aux.CurrentValue) != 64 && len(*aux.CurrentValue) != 0 && len(*aux.CurrentValue) != 66 {
@@ -254,5 +260,15 @@ func (ssd *SuffixStateDiff) UnmarshalJSON(data []byte) error {
254260
copy(ssd.CurrentValue[:], currentValueBytes)
255261
}
256262

263+
if aux.NewValue != nil && len(*aux.NewValue) != 0 {
264+
newValueBytes, err := PrefixedHexStringToBytes(*aux.NewValue)
265+
if err != nil {
266+
return fmt.Errorf("error decoding hex string for current value: %v", err)
267+
}
268+
269+
ssd.NewValue = &[32]byte{}
270+
copy(ssd.NewValue[:], newValueBytes)
271+
}
272+
257273
return nil
258274
}

0 commit comments

Comments
 (0)