mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
Replaces the prior `verkle/verkle.go` re-export shim (`type X =
upstream.X`, `var Fn = upstream.Fn` against `github.com/ethereum/go-verkle`)
with a full source vendor of `github.com/ethereum/go-verkle@v0.2.2` into
`/Users/z/work/lux/crypto/verkle/` under luxfi copyright. Every type and
function now has a concrete Go body in luxfi-owned files; no aliases
remain. Resolves the canonical-audit violation flagged in
CANONICAL_AUDIT.md (commit 9affea3).
Provenance:
Upstream: github.com/ethereum/go-verkle@v0.2.2 (public domain / Unlicense)
Per-file header notes vendor source and Lux Ecosystem License rebadge.
Files (13 source + 10 tests, ~7,900 LOC vendored):
verkle/config.go, config_ipa.go, conversion.go, debug.go, doc.go,
verkle/empty.go, encoding.go, hashednode.go, ipa.go, proof_ipa.go,
verkle/proof_json.go, tree.go, unknown.go (+ matching _test.go)
Surface preserved (all symbols consumed by lux/geth/trie, lux/geth/core/types):
Types: VerkleNode, InternalNode, LeafNode, Empty, Point, Fr,
VerkleProof, StateDiff, NodeResolverFn, IPAConfig, Proof
Const: NodeWidth
Funcs: ParseNode, New, ToDot, GetConfig, MakeVerkleMultiProof,
SerializeProof, HashPointToBytes, FromLEBytes, FromBytes,
DeserializeProof, MergeTrees, BatchNewLeafNode,
PreStateTreeFromProof
Methods: *InternalNode.{Insert,Commit,Hash,GetValuesAtStem,
DeleteAtStem}, IPAConfig.CommitToPoly, ...
go.mod: drop direct require on github.com/ethereum/go-verkle; promote
crate-crypto/go-ipa and davecgh/go-spew to direct (still pulled
through banderwagon primitives — to be swapped to luxfi/crypto/ipa
once the parallel banderwagon vendor lands at lux/crypto/banderwagon).
Tests (GOWORK=off go test ./verkle/ -count=1):
82 PASS, 4 SKIP, 2 FAIL.
TestParseNodeEoA and TestParseNodeSingleSlot fail identically against
upstream go-verkle@v0.2.2 (verified) -- these are pre-existing upstream
test fixtures gone stale; not caused by the vendor.
Consumer compatibility verified by external module replace+build
exercising every consumed symbol: ok.
Outstanding (tracked, not blocking):
- Switch IPA primitives import from `crate-crypto/go-ipa/{banderwagon,
common,ipa}` to `luxfi/crypto/ipa/*` once the banderwagon-vanilla
branch lands. Done in this commit would conflict with the parallel
work-in-progress.
- Two upstream-stale test fixtures (TestParseNodeEoA,
TestParseNodeSingleSlot) to be regenerated against current encoding
in a follow-up.
Branch: verkle-vanilla-2026-04-27
285 lines
9.0 KiB
Go
285 lines
9.0 KiB
Go
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
|
//
|
|
// Vendored from github.com/ethereum/go-verkle@v0.2.2 (public domain / Unlicense).
|
|
// Re-licensed under the Lux Ecosystem License. The package implements the
|
|
// Verkle trie, its node types (InternalNode, LeafNode, Empty, HashedNode),
|
|
// IPA configuration, multi-proof generation/verification, encoding, and
|
|
// JSON serialization. Algorithmic logic mirrors upstream; downstream callers
|
|
// (luxfi/geth, luxfi/node, luxfi/evm) consume this package directly under
|
|
// the github.com/luxfi/crypto/verkle import path.
|
|
|
|
// This is free and unencumbered software released into the public domain.
|
|
//
|
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
// distribute this software, either in source code form or as a compiled
|
|
// binary, for any purpose, commercial or non-commercial, and by any
|
|
// means.
|
|
//
|
|
// In jurisdictions that recognize copyright laws, the author or authors
|
|
// of this software dedicate any and all copyright interest in the
|
|
// software to the public domain. We make this dedication for the benefit
|
|
// of the public at large and to the detriment of our heirs and
|
|
// successors. We intend this dedication to be an overt act of
|
|
// relinquishment in perpetuity of all present and future rights to this
|
|
// software under copyright law.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
// For more information, please refer to <https://unlicense.org>
|
|
|
|
package verkle
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// HexToPrefixedString turns a byte slice into its hex representation
|
|
// and prefixes it with `0x`.
|
|
func HexToPrefixedString(data []byte) string {
|
|
return "0x" + hex.EncodeToString(data)
|
|
}
|
|
|
|
// PrefixedHexStringToBytes does the opposite of HexToPrefixedString.
|
|
func PrefixedHexStringToBytes(input string) ([]byte, error) {
|
|
if input[0:2] == "0x" {
|
|
input = input[2:]
|
|
}
|
|
return hex.DecodeString(input)
|
|
}
|
|
|
|
type ipaproofMarshaller struct {
|
|
CL [IPA_PROOF_DEPTH]string `json:"cl"`
|
|
CR [IPA_PROOF_DEPTH]string `json:"cr"`
|
|
FinalEvaluation string `json:"finalEvaluation"`
|
|
}
|
|
|
|
func (ipp *IPAProof) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&ipaproofMarshaller{
|
|
CL: [IPA_PROOF_DEPTH]string{
|
|
HexToPrefixedString(ipp.CL[0][:]),
|
|
HexToPrefixedString(ipp.CL[1][:]),
|
|
HexToPrefixedString(ipp.CL[2][:]),
|
|
HexToPrefixedString(ipp.CL[3][:]),
|
|
HexToPrefixedString(ipp.CL[4][:]),
|
|
HexToPrefixedString(ipp.CL[5][:]),
|
|
HexToPrefixedString(ipp.CL[6][:]),
|
|
HexToPrefixedString(ipp.CL[7][:]),
|
|
},
|
|
CR: [IPA_PROOF_DEPTH]string{
|
|
HexToPrefixedString(ipp.CR[0][:]),
|
|
HexToPrefixedString(ipp.CR[1][:]),
|
|
HexToPrefixedString(ipp.CR[2][:]),
|
|
HexToPrefixedString(ipp.CR[3][:]),
|
|
HexToPrefixedString(ipp.CR[4][:]),
|
|
HexToPrefixedString(ipp.CR[5][:]),
|
|
HexToPrefixedString(ipp.CR[6][:]),
|
|
HexToPrefixedString(ipp.CR[7][:]),
|
|
},
|
|
FinalEvaluation: HexToPrefixedString(ipp.FinalEvaluation[:]),
|
|
})
|
|
}
|
|
|
|
func (ipp *IPAProof) UnmarshalJSON(data []byte) error {
|
|
aux := &ipaproofMarshaller{}
|
|
|
|
if err := json.Unmarshal(data, &aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(aux.FinalEvaluation) != 64 && len(aux.FinalEvaluation) != 66 {
|
|
return fmt.Errorf("invalid hex string for final evaluation: %s", aux.FinalEvaluation)
|
|
}
|
|
|
|
currentValueBytes, err := PrefixedHexStringToBytes(aux.FinalEvaluation)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for current value: %v", err)
|
|
}
|
|
copy(ipp.FinalEvaluation[:], currentValueBytes)
|
|
|
|
for i := range ipp.CL {
|
|
if len(aux.CL[i]) != 64 && len(aux.CL[i]) != 66 {
|
|
return fmt.Errorf("invalid hex string for CL[%d]: %s", i, aux.CL[i])
|
|
}
|
|
val, err := PrefixedHexStringToBytes(aux.CL[i])
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for CL[%d]: %s", i, aux.CL[i])
|
|
}
|
|
copy(ipp.CL[i][:], val)
|
|
if len(aux.CR[i]) != 64 && len(aux.CR[i]) != 66 {
|
|
return fmt.Errorf("invalid hex string for CR[%d]: %s", i, aux.CR[i])
|
|
}
|
|
val, err = PrefixedHexStringToBytes(aux.CR[i])
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for CR[%d]: %s", i, aux.CR[i])
|
|
}
|
|
copy(ipp.CR[i][:], val)
|
|
}
|
|
copy(ipp.FinalEvaluation[:], currentValueBytes)
|
|
|
|
return nil
|
|
}
|
|
|
|
type verkleProofMarshaller struct {
|
|
OtherStems []string `json:"otherStems"`
|
|
DepthExtensionPresent string `json:"depthExtensionPresent"`
|
|
CommitmentsByPath []string `json:"commitmentsByPath"`
|
|
D string `json:"d"`
|
|
IPAProof *IPAProof `json:"ipaProof"`
|
|
}
|
|
|
|
func (vp *VerkleProof) MarshalJSON() ([]byte, error) {
|
|
aux := &verkleProofMarshaller{
|
|
OtherStems: make([]string, len(vp.OtherStems)),
|
|
DepthExtensionPresent: HexToPrefixedString(vp.DepthExtensionPresent),
|
|
CommitmentsByPath: make([]string, len(vp.CommitmentsByPath)),
|
|
D: HexToPrefixedString(vp.D[:]),
|
|
IPAProof: vp.IPAProof,
|
|
}
|
|
|
|
for i, s := range vp.OtherStems {
|
|
aux.OtherStems[i] = HexToPrefixedString(s[:])
|
|
}
|
|
for i, c := range vp.CommitmentsByPath {
|
|
aux.CommitmentsByPath[i] = HexToPrefixedString(c[:])
|
|
}
|
|
return json.Marshal(aux)
|
|
}
|
|
|
|
func (vp *VerkleProof) UnmarshalJSON(data []byte) error {
|
|
var aux verkleProofMarshaller
|
|
err := json.Unmarshal(data, &aux)
|
|
if err != nil {
|
|
return fmt.Errorf("verkle proof unmarshal error: %w", err)
|
|
}
|
|
|
|
vp.DepthExtensionPresent, err = PrefixedHexStringToBytes(aux.DepthExtensionPresent)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for depth and extension present: %v", err)
|
|
}
|
|
|
|
vp.CommitmentsByPath = make([][32]byte, len(aux.CommitmentsByPath))
|
|
for i, c := range aux.CommitmentsByPath {
|
|
val, err := PrefixedHexStringToBytes(c)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for commitment #%d: %w", i, err)
|
|
}
|
|
copy(vp.CommitmentsByPath[i][:], val)
|
|
}
|
|
|
|
currentValueBytes, err := PrefixedHexStringToBytes(aux.D)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for D: %w", err)
|
|
}
|
|
copy(vp.D[:], currentValueBytes)
|
|
|
|
vp.OtherStems = make([][StemSize]byte, len(aux.OtherStems))
|
|
for i, c := range aux.OtherStems {
|
|
val, err := PrefixedHexStringToBytes(c)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for other stem #%d: %w", i, err)
|
|
}
|
|
copy(vp.OtherStems[i][:], val)
|
|
}
|
|
|
|
vp.IPAProof = aux.IPAProof
|
|
return nil
|
|
}
|
|
|
|
type stemStateDiffMarshaller struct {
|
|
Stem string `json:"stem"`
|
|
SuffixDiffs SuffixStateDiffs `json:"suffixDiffs"`
|
|
}
|
|
|
|
func (ssd StemStateDiff) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&stemStateDiffMarshaller{
|
|
Stem: HexToPrefixedString(ssd.Stem[:]),
|
|
SuffixDiffs: ssd.SuffixDiffs,
|
|
})
|
|
}
|
|
|
|
func (ssd *StemStateDiff) UnmarshalJSON(data []byte) error {
|
|
var aux stemStateDiffMarshaller
|
|
if err := json.Unmarshal(data, &aux); err != nil {
|
|
return fmt.Errorf("stemdiff unmarshal error: %w", err)
|
|
}
|
|
|
|
stem, err := PrefixedHexStringToBytes(aux.Stem)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid hex string for stem: %w", err)
|
|
}
|
|
*ssd = StemStateDiff{
|
|
SuffixDiffs: aux.SuffixDiffs,
|
|
}
|
|
copy(ssd.Stem[:], stem)
|
|
return nil
|
|
}
|
|
|
|
type suffixStateDiffMarshaller struct {
|
|
Suffix byte `json:"suffix"`
|
|
CurrentValue *string `json:"currentValue"`
|
|
NewValue *string `json:"newValue"`
|
|
}
|
|
|
|
func (ssd SuffixStateDiff) MarshalJSON() ([]byte, error) {
|
|
var cvstr, nvstr *string
|
|
if ssd.CurrentValue != nil {
|
|
tempstr := HexToPrefixedString(ssd.CurrentValue[:])
|
|
cvstr = &tempstr
|
|
}
|
|
if ssd.NewValue != nil {
|
|
tempstr := HexToPrefixedString(ssd.NewValue[:])
|
|
nvstr = &tempstr
|
|
}
|
|
return json.Marshal(&suffixStateDiffMarshaller{
|
|
Suffix: ssd.Suffix,
|
|
CurrentValue: cvstr,
|
|
NewValue: nvstr,
|
|
})
|
|
}
|
|
|
|
func (ssd *SuffixStateDiff) UnmarshalJSON(data []byte) error {
|
|
aux := &suffixStateDiffMarshaller{}
|
|
|
|
if err := json.Unmarshal(data, &aux); err != nil {
|
|
return fmt.Errorf("suffix diff unmarshal error: %w", err)
|
|
}
|
|
|
|
if aux.CurrentValue != nil && len(*aux.CurrentValue) != 64 && len(*aux.CurrentValue) != 0 && len(*aux.CurrentValue) != 66 {
|
|
return fmt.Errorf("invalid hex string for current value: %s", *aux.CurrentValue)
|
|
}
|
|
|
|
*ssd = SuffixStateDiff{
|
|
Suffix: aux.Suffix,
|
|
}
|
|
|
|
if aux.CurrentValue != nil && len(*aux.CurrentValue) != 0 {
|
|
currentValueBytes, err := PrefixedHexStringToBytes(*aux.CurrentValue)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for current value: %v", err)
|
|
}
|
|
|
|
ssd.CurrentValue = &[32]byte{}
|
|
copy(ssd.CurrentValue[:], currentValueBytes)
|
|
}
|
|
|
|
if aux.NewValue != nil && len(*aux.NewValue) != 0 {
|
|
newValueBytes, err := PrefixedHexStringToBytes(*aux.NewValue)
|
|
if err != nil {
|
|
return fmt.Errorf("error decoding hex string for current value: %v", err)
|
|
}
|
|
|
|
ssd.NewValue = &[32]byte{}
|
|
copy(ssd.NewValue[:], newValueBytes)
|
|
}
|
|
|
|
return nil
|
|
}
|