feat(wire): add asset proof tags 49, 50, 51 readers
Reads asset_operation_proof, asset_operation_ownership_proof, and asset_operation_ownership_proof_eth structures. All use CHAIN_TRANSITION_VER with version byte prefix. Stored as opaque bytes. Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
3e79f34a65
commit
d8e12a1539
2 changed files with 236 additions and 0 deletions
|
|
@ -539,6 +539,11 @@ const (
|
|||
// Asset descriptor operation (HF5).
|
||||
tagAssetDescriptorOperation = 40 // asset_descriptor_operation
|
||||
|
||||
// Asset operation proof tags (HF5).
|
||||
tagAssetOperationProof = 49 // asset_operation_proof
|
||||
tagAssetOperationOwnershipProof = 50 // asset_operation_ownership_proof
|
||||
tagAssetOperationOwnershipProofETH = 51 // asset_operation_ownership_proof_eth (Ethereum sig)
|
||||
|
||||
// Signature variant tags (signature_v).
|
||||
tagNLSAGSig = 42 // NLSAG_sig — vector<signature>
|
||||
tagZCSig = 43 // ZC_sig — 2 public_keys + CLSAG_GGX
|
||||
|
|
@ -611,6 +616,14 @@ func readVariantElementData(dec *Decoder, tag uint8) []byte {
|
|||
case tagAssetDescriptorOperation:
|
||||
return readAssetDescriptorOperation(dec)
|
||||
|
||||
// Asset operation proof variants (HF5)
|
||||
case tagAssetOperationProof:
|
||||
return readAssetOperationProof(dec)
|
||||
case tagAssetOperationOwnershipProof:
|
||||
return readAssetOperationOwnershipProof(dec)
|
||||
case tagAssetOperationOwnershipProofETH:
|
||||
return readAssetOperationOwnershipProofETH(dec)
|
||||
|
||||
// Signature variants
|
||||
case tagNLSAGSig: // vector<signature> (64 bytes each)
|
||||
return readVariantVectorFixed(dec, 64)
|
||||
|
|
@ -943,6 +956,109 @@ func readAssetDescriptorBase(dec *Decoder) []byte {
|
|||
return raw
|
||||
}
|
||||
|
||||
// readAssetOperationProof reads asset_operation_proof (tag 49).
|
||||
// Structure (CHAIN_TRANSITION_VER, version 1):
|
||||
//
|
||||
// ver (uint8) + gss (generic_schnorr_sig_s: 64 bytes)
|
||||
// + asset_id (32 bytes) + etc (vector<uint8>).
|
||||
func readAssetOperationProof(dec *Decoder) []byte {
|
||||
var raw []byte
|
||||
|
||||
// ver: uint8
|
||||
ver := dec.ReadUint8()
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, ver)
|
||||
|
||||
// gss: generic_schnorr_sig_s — 2 scalars (s, c) = 64 bytes
|
||||
b := dec.ReadBytes(64)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, b...)
|
||||
|
||||
// asset_id: 32-byte hash
|
||||
b = dec.ReadBytes(32)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, b...)
|
||||
|
||||
// etc: vector<uint8>
|
||||
v := readVariantVectorFixed(dec, 1)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, v...)
|
||||
|
||||
return raw
|
||||
}
|
||||
|
||||
// readAssetOperationOwnershipProof reads asset_operation_ownership_proof (tag 50).
|
||||
// Structure (CHAIN_TRANSITION_VER, version 1):
|
||||
//
|
||||
// ver (uint8) + gss (generic_schnorr_sig_s: 64 bytes)
|
||||
// + etc (vector<uint8>).
|
||||
func readAssetOperationOwnershipProof(dec *Decoder) []byte {
|
||||
var raw []byte
|
||||
|
||||
// ver: uint8
|
||||
ver := dec.ReadUint8()
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, ver)
|
||||
|
||||
// gss: generic_schnorr_sig_s — 2 scalars (s, c) = 64 bytes
|
||||
b := dec.ReadBytes(64)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, b...)
|
||||
|
||||
// etc: vector<uint8>
|
||||
v := readVariantVectorFixed(dec, 1)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, v...)
|
||||
|
||||
return raw
|
||||
}
|
||||
|
||||
// readAssetOperationOwnershipProofETH reads asset_operation_ownership_proof_eth (tag 51).
|
||||
// Structure (CHAIN_TRANSITION_VER, version 1):
|
||||
//
|
||||
// ver (uint8) + eth_sig (65 bytes: r(32) + s(32) + v(1))
|
||||
// + etc (vector<uint8>).
|
||||
func readAssetOperationOwnershipProofETH(dec *Decoder) []byte {
|
||||
var raw []byte
|
||||
|
||||
// ver: uint8
|
||||
ver := dec.ReadUint8()
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, ver)
|
||||
|
||||
// eth_sig: crypto::eth_signature — r(32) + s(32) + v(1) = 65 bytes
|
||||
b := dec.ReadBytes(65)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, b...)
|
||||
|
||||
// etc: vector<uint8>
|
||||
v := readVariantVectorFixed(dec, 1)
|
||||
if dec.err != nil {
|
||||
return nil
|
||||
}
|
||||
raw = append(raw, v...)
|
||||
|
||||
return raw
|
||||
}
|
||||
|
||||
// --- crypto blob readers ---
|
||||
// These read variable-length serialised crypto structures and return raw bytes.
|
||||
// All vectors are varint(count) + 32*count bytes (scalars or points).
|
||||
|
|
|
|||
|
|
@ -137,3 +137,123 @@ func TestVariantVectorWithTag40_Good(t *testing.T) {
|
|||
t.Fatalf("round-trip mismatch: got %d bytes, want %d bytes", len(got), len(raw))
|
||||
}
|
||||
}
|
||||
|
||||
func buildAssetOperationProofBlob() []byte {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
|
||||
// ver: uint8 = 1
|
||||
enc.WriteUint8(1)
|
||||
// gss: generic_schnorr_sig_s — 2 scalars (s, c) = 64 bytes
|
||||
enc.WriteBytes(make([]byte, 64))
|
||||
// asset_id: 32-byte hash
|
||||
enc.WriteBytes(bytes.Repeat([]byte{0xCD}, 32))
|
||||
// etc: vector<uint8> (empty)
|
||||
enc.WriteVarint(0)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func TestReadAssetOperationProof_Good(t *testing.T) {
|
||||
blob := buildAssetOperationProofBlob()
|
||||
dec := NewDecoder(bytes.NewReader(blob))
|
||||
got := readAssetOperationProof(dec)
|
||||
if dec.Err() != nil {
|
||||
t.Fatalf("readAssetOperationProof failed: %v", dec.Err())
|
||||
}
|
||||
if !bytes.Equal(got, blob) {
|
||||
t.Fatalf("round-trip mismatch: got %d bytes, want %d bytes", len(got), len(blob))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAssetOperationProof_Bad(t *testing.T) {
|
||||
dec := NewDecoder(bytes.NewReader([]byte{1}))
|
||||
_ = readAssetOperationProof(dec)
|
||||
if dec.Err() == nil {
|
||||
t.Fatal("expected error for truncated asset operation proof")
|
||||
}
|
||||
}
|
||||
|
||||
func buildAssetOperationOwnershipProofBlob() []byte {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
|
||||
// ver: uint8 = 1
|
||||
enc.WriteUint8(1)
|
||||
// gss: generic_schnorr_sig_s — 2 scalars = 64 bytes
|
||||
enc.WriteBytes(make([]byte, 64))
|
||||
// etc: vector<uint8> (empty)
|
||||
enc.WriteVarint(0)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func TestReadAssetOperationOwnershipProof_Good(t *testing.T) {
|
||||
blob := buildAssetOperationOwnershipProofBlob()
|
||||
dec := NewDecoder(bytes.NewReader(blob))
|
||||
got := readAssetOperationOwnershipProof(dec)
|
||||
if dec.Err() != nil {
|
||||
t.Fatalf("readAssetOperationOwnershipProof failed: %v", dec.Err())
|
||||
}
|
||||
if !bytes.Equal(got, blob) {
|
||||
t.Fatalf("round-trip mismatch: got %d bytes, want %d bytes", len(got), len(blob))
|
||||
}
|
||||
}
|
||||
|
||||
func buildAssetOperationOwnershipProofETHBlob() []byte {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
|
||||
// ver: uint8 = 1
|
||||
enc.WriteUint8(1)
|
||||
// eth_sig: 65 bytes (r=32 + s=32 + v=1)
|
||||
enc.WriteBytes(make([]byte, 65))
|
||||
// etc: vector<uint8> (empty)
|
||||
enc.WriteVarint(0)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func TestReadAssetOperationOwnershipProofETH_Good(t *testing.T) {
|
||||
blob := buildAssetOperationOwnershipProofETHBlob()
|
||||
dec := NewDecoder(bytes.NewReader(blob))
|
||||
got := readAssetOperationOwnershipProofETH(dec)
|
||||
if dec.Err() != nil {
|
||||
t.Fatalf("readAssetOperationOwnershipProofETH failed: %v", dec.Err())
|
||||
}
|
||||
if !bytes.Equal(got, blob) {
|
||||
t.Fatalf("round-trip mismatch: got %d bytes, want %d bytes", len(got), len(blob))
|
||||
}
|
||||
}
|
||||
|
||||
func TestVariantVectorWithProofTags_Good(t *testing.T) {
|
||||
// Build a variant vector with 3 elements: tags 49, 50, 51.
|
||||
proofBlob := buildAssetOperationProofBlob()
|
||||
ownershipBlob := buildAssetOperationOwnershipProofBlob()
|
||||
ethBlob := buildAssetOperationOwnershipProofETHBlob()
|
||||
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
// count = 3
|
||||
enc.WriteVarint(3)
|
||||
// tag 49
|
||||
enc.WriteUint8(tagAssetOperationProof)
|
||||
enc.WriteBytes(proofBlob)
|
||||
// tag 50
|
||||
enc.WriteUint8(tagAssetOperationOwnershipProof)
|
||||
enc.WriteBytes(ownershipBlob)
|
||||
// tag 51
|
||||
enc.WriteUint8(tagAssetOperationOwnershipProofETH)
|
||||
enc.WriteBytes(ethBlob)
|
||||
|
||||
raw := buf.Bytes()
|
||||
|
||||
dec := NewDecoder(bytes.NewReader(raw))
|
||||
got := decodeRawVariantVector(dec)
|
||||
if dec.Err() != nil {
|
||||
t.Fatalf("decodeRawVariantVector with proof tags failed: %v", dec.Err())
|
||||
}
|
||||
if !bytes.Equal(got, raw) {
|
||||
t.Fatalf("round-trip mismatch: got %d bytes, want %d bytes", len(got), len(raw))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue