wrap storage proof inputs into an object

This commit is contained in:
Mark Spanbroek 2024-12-17 13:10:22 +01:00
parent 54d5c89122
commit 0fff583d58
7 changed files with 135 additions and 148 deletions

View File

@ -21,6 +21,18 @@ func fromBytes(
): ?!StorageRequestId =
success StorageRequestId(? array[32, byte].fromBytes(bytes))
func init*(
_: type StorageProofInput,
message: StorageProofInputMessage
): ?!StorageProofInput =
success StorageProofInput.init(
? StorageRequestId.fromBytes(message.requestId),
message.slotIndex,
Period(message.period),
? array[32, byte].fromBytes(message.merkleRoot),
? array[32, byte].fromBytes(message.challenge)
)
func init(_: type Groth16Proof, message: Groth16ProofMessage): Groth16Proof =
Groth16Proof.init(
G1Point.init(
@ -46,29 +58,13 @@ func init(_: type Groth16Proof, message: Groth16ProofMessage): Groth16Proof =
func init(_: type Transaction, message: TransactionMessage): ?!Transaction =
if message.version != TransactionVersion.version0.uint32:
return failure "unsupported transaction version: " & $message.version
let requestId = ? StorageRequestId.fromBytes(message.requestId)
let slotIndex = message.slotIndex
let period = Period(message.period)
let merkleRoot = ? array[32, byte].fromBytes(message.merkleRoot)
let challenge = ? array[32, byte].fromBytes(message.challenge)
let proofInput = ? StorageProofInput.init(message.proofInput)
case message.kind
of TransactionKind.storageProof.uint32:
success Transaction.storageProof(
requestId,
slotIndex,
period,
merkleRoot,
challenge,
Groth16Proof.init(message.proof)
)
let proof = Groth16Proof.init(message.proof)
success Transaction.storageProof(proofInput, proof)
of TransactionKind.missingProof.uint32:
success Transaction.missingProof(
requestId,
message.slotIndex,
period,
merkleRoot,
challenge,
)
success Transaction.missingProof(proofInput)
else:
failure "invalid transaction kind: " & $message.kind

View File

@ -0,0 +1,42 @@
import ./storagerequest
import ./period
type
StorageProofInput* = object
requestId: StorageRequestId
slotIndex: uint32
period: Period
merkleRoot: array[32, byte]
challenge: array[32, byte]
func init*(
_: type StorageProofInput,
requestId: StorageRequestId,
slotIndex: uint32,
period: Period,
merkleRoot: array[32, byte],
challenge: array[32, byte]
): StorageProofInput =
StorageProofInput(
requestId: requestId,
slotIndex: slotIndex,
period: period,
merkleRoot: merkleRoot,
challenge: challenge
)
func requestId*(input: StorageProofInput): StorageRequestId =
input.requestId
func slotIndex*(input: StorageProofInput): uint32 =
input.slotIndex
func period*(input: StorageProofInput): Period =
input.period
func merkleRoot*(input: StorageProofInput): array[32, byte] =
input.merkleRoot
func challenge*(input: StorageProofInput): array[32, byte] =
input.challenge

View File

@ -9,12 +9,14 @@ type
TransactionMessage* {.proto3.} = object
version* {.fieldNumber: 1, pint.}: uint32
kind* {.fieldNumber: 2, pint.}: uint32
requestId* {.fieldNumber: 3.}: seq[byte]
slotIndex* {.fieldNumber: 4, pint.}: uint32
period* {.fieldNumber: 5, pint.}: uint64
merkleRoot* {.fieldNumber: 6.}: seq[byte]
challenge* {.fieldNumber: 7.}: seq[byte]
proof* {.fieldNumber: 8.}: Groth16ProofMessage
proofInput* {.fieldNumber: 3.}: StorageProofInputMessage
proof* {.fieldNumber: 4.}: Groth16ProofMessage
StorageProofInputMessage* {.proto3.} = object
requestId* {.fieldNumber: 1.}: seq[byte]
slotIndex* {.fieldNumber: 2, pint.}: uint32
period* {.fieldNumber: 3, pint.}: uint64
merkleRoot* {.fieldNumber: 4.}: seq[byte]
challenge* {.fieldNumber: 5.}: seq[byte]
Groth16ProofMessage* {.proto3.} = object
a* {.fieldNumber: 1.}: G1PointMessage
b* {.fieldNumber: 2.}: G2PointMessage
@ -29,15 +31,23 @@ type
real* {.fieldNumber: 1.}: seq[byte]
imag* {.fieldNumber: 2.}: seq[byte]
func init(
_: type StorageProofInputMessage,
input: StorageProofInput
): StorageProofInputMessage =
StorageProofInputMessage(
requestId: @(array[32, byte](input.requestId)),
slotIndex: input.slotIndex,
period: input.period.uint64,
merkleRoot: @(input.merkleRoot),
challenge: @(input.challenge)
)
func init*(_: type TransactionMessage, transaction: Transaction): TransactionMessage =
var message = TransactionMessage(
version: transaction.version.uint32,
kind: transaction.kind.uint32,
requestId: @(array[32, byte](transaction.requestId)),
slotIndex: transaction.slotIndex,
period: transaction.period.uint64,
merkleRoot: @(transaction.merkleRoot),
challenge: @(transaction.challenge)
proofInput: StorageProofInputMessage.init(transaction.proofInput)
)
if transaction.kind == TransactionKind.storageProof:
message.proof = Groth16ProofMessage(

View File

@ -2,10 +2,12 @@ import ../basics
import ../hashing
import ./storagerequest
import ./period
import ./proofinput
import ./groth16
export storagerequest
export period
export proofinput
export groth16
type
@ -15,11 +17,7 @@ type
storageProof
missingProof
Transaction* = ref object
requestId: StorageRequestId
slotIndex: uint32
period: Period
merkleRoot: array[32, byte]
challenge: array[32, byte]
proofInput: StorageProofInput
case kind: TransactionKind
of storageProof:
proof: Groth16Proof
@ -29,38 +27,22 @@ type
func storageProof*(
_: type Transaction,
requestId: StorageRequestId,
slotIndex: uint32,
period: Period,
merkleRoot: array[32, byte],
challenge: array[32, byte],
proofInput: StorageProofInput,
proof: Groth16Proof
): Transaction =
Transaction(
kind: TransactionKind.storageProof,
requestId: requestId,
period: period,
slotIndex: slotIndex,
merkleRoot: merkleRoot,
challenge: challenge,
proofInput: proofInput,
proof: proof
)
func missingProof*(
_: type Transaction,
requestId: StorageRequestId,
slotIndex: uint32,
period: Period,
merkleRoot: array[32, byte],
challenge: array[32, byte],
proofInput: StorageProofInput
): Transaction =
Transaction(
kind: TransactionKind.missingProof,
requestId: requestId,
slotIndex: slotIndex,
period: period,
merkleRoot: merkleRoot,
challenge: challenge
proofInput: proofInput
)
func version*(transaction: Transaction): TransactionVersion =
@ -69,20 +51,8 @@ func version*(transaction: Transaction): TransactionVersion =
func kind*(transaction: Transaction): TransactionKind =
transaction.kind
func requestId*(transaction: Transaction): StorageRequestId =
transaction.requestId
func slotIndex*(transaction: Transaction): uint32 =
transaction.slotIndex
func period*(transaction: Transaction): Period =
transaction.period
func merkleRoot*(transaction: Transaction): array[32, byte] =
transaction.merkleRoot
func challenge*(transaction: Transaction): array[32, byte] =
transaction.challenge
func proofInput*(transaction: Transaction): StorageProofInput =
transaction.proofInput
func proof*(transaction: Transaction): Groth16Proof =
transaction.proof
@ -96,15 +66,7 @@ func hash*(transaction: Transaction): ?Hash =
func `==`*(a, b: Transaction): bool =
if a.kind != b.kind:
return false
if a.requestId != b.requestId:
return false
if a.slotIndex != b.slotIndex:
return false
if a.period != b.period:
return false
if a.merkleRoot != b.merkleRoot:
return false
if a.challenge != b.challenge:
if a.proofInput != b.proofInput:
return false
case a.kind
of TransactionKind.storageProof:

View File

@ -44,32 +44,29 @@ proc example*(_: type Groth16Proof): Groth16Proof =
G1Point.example
)
proc example*(_: type Transaction): Transaction =
let kind = [TransactionKind.storageProof, TransactionKind.missingProof].sample
proc example*(_: type StorageProofInput): StorageProofInput =
let requestId = StorageRequestId.example
let slotIndex = uint32.example
let period = Period.example
let merkleRoot = array[32, byte].example
let challenge = array[32, byte].example
StorageProofInput.init(
requestId,
slotIndex,
period,
merkleRoot,
challenge
)
proc example*(_: type Transaction): Transaction =
let kind = [TransactionKind.storageProof, TransactionKind.missingProof].sample
let proofInput = StorageProofInput.example
case kind
of TransactionKind.missingProof:
Transaction.missingProof(
requestId,
slotIndex,
period,
merkleRoot,
challenge
)
Transaction.missingProof(proofInput)
of TransactionKind.storageProof:
let proof = Groth16Proof.example
Transaction.storageProof(
requestId,
slotIndex,
period,
merkleRoot,
challenge,
proof
)
Transaction.storageProof(proofInput, proof)
proc example*(_: type Identity): Identity =
Identity.random(result)

View File

@ -13,32 +13,32 @@ suite "Transaction serialization":
{.warning[Deprecated]: on.}
check protobuf.version == transaction.version.uint32
check protobuf.kind == transaction.kind.uint32
check protobuf.requestId == array[32, byte](transaction.requestId)
check protobuf.slotIndex == transaction.slotIndex
check protobuf.period == transaction.period.uint64
check protobuf.merkleRoot == array[32, byte](transaction.merkleRoot)
check protobuf.challenge == array[32, byte](transaction.challenge)
test "serializes a storage proof with protobuf":
let proof = Groth16Proof.example
let transaction = Transaction.storageProof(
StorageRequestId.example,
uint32.example,
Period.example,
array[32, byte].example,
array[32, byte].example,
proof
)
test "serializes storage proof input with protobuf":
let transaction = Transaction.example
let proofInput = transaction.proofInput
let serialized = transaction.toBytes()
let protobuf = ProtoBuf.decode(serialized, TransactionMessage)
check protobuf.proof.a.x == transaction.proof.a.x.toBytesBE()
check protobuf.proof.a.y == transaction.proof.a.y.toBytesBE()
check protobuf.proof.b.x.real == transaction.proof.b.x.real.toBytesBE()
check protobuf.proof.b.x.imag == transaction.proof.b.x.imag.toBytesBE()
check protobuf.proof.b.y.real == transaction.proof.b.y.real.toBytesBE()
check protobuf.proof.b.y.imag == transaction.proof.b.y.imag.toBytesBE()
check protobuf.proof.c.x == transaction.proof.c.x.toBytesBE()
check protobuf.proof.c.y == transaction.proof.c.y.toBytesBE()
check protobuf.proofInput.requestId == array[32, byte](proofInput.requestId)
check protobuf.proofInput.slotIndex == proofInput.slotIndex
check protobuf.proofInput.period == proofInput.period.uint64
check protobuf.proofInput.merkleRoot == array[32, byte](proofInput.merkleRoot)
check protobuf.proofInput.challenge == array[32, byte](proofInput.challenge)
test "serializes a storage proof with protobuf":
let proofInput = StorageProofInput.example
let proof = Groth16Proof.example
let transaction = Transaction.storageProof(proofInput, proof)
let serialized = transaction.toBytes()
let protobuf = ProtoBuf.decode(serialized, TransactionMessage)
check protobuf.proof.a.x == proof.a.x.toBytesBE()
check protobuf.proof.a.y == proof.a.y.toBytesBE()
check protobuf.proof.b.x.real == proof.b.x.real.toBytesBE()
check protobuf.proof.b.x.imag == proof.b.x.imag.toBytesBE()
check protobuf.proof.b.y.real == proof.b.y.real.toBytesBE()
check protobuf.proof.b.y.imag == proof.b.y.imag.toBytesBE()
check protobuf.proof.c.x == proof.c.x.toBytesBE()
check protobuf.proof.c.y == proof.c.y.toBytesBE()
test "serializes a signed transaction with protobuf":
let signed = Signed[Transaction].example
@ -99,7 +99,7 @@ suite "Transaction serialization":
test "deserialization fails when storage request id is invalid":
let signed = Signed[Transaction].example
var message = SignedTransactionMessage.init(signed)
message.transaction.requestid &= 42'u8
message.transaction.proofInput.requestid &= 42'u8
let invalid = Protobuf.encode(message)
let deserialized = Signed[Transaction].fromBytes(invalid)
check deserialized.isFailure
@ -108,7 +108,7 @@ suite "Transaction serialization":
test "deserialization fails when merkle root is invalid":
let signed = Signed[Transaction].example
var message = SignedTransactionMessage.init(signed)
message.transaction.merkleRoot &= 42'u8
message.transaction.proofInput.merkleRoot &= 42'u8
let invalid = Protobuf.encode(message)
let deserialized = Signed[Transaction].fromBytes(invalid)
check deserialized.isFailure
@ -117,7 +117,7 @@ suite "Transaction serialization":
test "deserialization fails when challenge is invalid":
let signed = Signed[Transaction].example
var message = SignedTransactionMessage.init(signed)
message.transaction.challenge &= 42'u8
message.transaction.proofInput.challenge &= 42'u8
let invalid = Protobuf.encode(message)
let deserialized = Signed[Transaction].fromBytes(invalid)
check deserialized.isFailure

View File

@ -4,36 +4,16 @@ import codexvalidator/transaction
suite "Transaction":
test "a transaction can contain a storage proof":
let requestId = StorageRequestId.example
let slotIndex = uint32.example
let period = Period.example
let merkleRoot = array[32, byte].example
let challenge = array[32, byte].example
let proofInput = StorageProofInput.example
let proof = Groth16Proof.example
let transaction = Transaction.storageProof(
requestId, slotIndex, period, merkleRoot, challenge, proof
)
check transaction.requestId == requestId
check transaction.slotIndex == slotIndex
check transaction.period == period
check transaction.merkleRoot == merkleRoot
check transaction.challenge == challenge
let transaction = Transaction.storageProof(proofInput, proof)
check transaction.proofInput == proofInput
check transaction.proof == proof
test "a transaction can indicate a missing storage proof":
let requestId = StorageRequestId.example
let slotIndex = uint32.example
let period = Period.example
let merkleRoot = array[32, byte].example
let challenge = array[32, byte].example
let transaction = Transaction.missingProof(
requestId, slotIndex, period, merkleRoot, challenge
)
check transaction.requestId == requestId
check transaction.slotIndex == slotIndex
check transaction.period == period
check transaction.merkleRoot == merkleRoot
check transaction.challenge == challenge
let proofInput = StorageProofInput.example
let transaction = Transaction.missingProof(proofInput)
check transaction.proofInput == proofInput
test "transactions have a fixed version":
let transaction = Transaction.example