diff --git a/rgbconsignment/fixtures_test.go b/rgbconsignment/fixtures_test.go index b8512d8..f74b8b7 100644 --- a/rgbconsignment/fixtures_test.go +++ b/rgbconsignment/fixtures_test.go @@ -54,7 +54,7 @@ func TestParseFileIFAContract(t *testing.T) { t.Errorf("alloc[0] = %+v", a) } e := a.Entries[0] - if e.Amount != 100000 || e.Seal.Kind != SealRevealed || e.Seal.Vout != 1 { + if e.Amount != 100000 || e.Seal.Kind != SealRevealed || e.Seal.Vout == nil || *e.Seal.Vout != 1 { t.Errorf("entry[0] = %+v", e) } if e.Seal.Txid == nil || *e.Seal.Txid != "14295d5bb1a191cdb6286dc0944df938421e3dfcbf0811353ccac4100c2068c5" { diff --git a/rgbconsignment/parse_test.go b/rgbconsignment/parse_test.go index dd6e1cc..99a042e 100644 --- a/rgbconsignment/parse_test.go +++ b/rgbconsignment/parse_test.go @@ -45,6 +45,34 @@ func TestJSONKinds(t *testing.T) { } } +func TestConfidentialSealHasNoVout(t *testing.T) { + // Rust emits confidential seals without vout; the Go type must not + // materialize a phantom vout:0 that consumers could mistake for txout 0. + var s Seal + if err := json.Unmarshal([]byte(`{"kind":"confidential","secret_seal":"deadbeef"}`), &s); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if s.Kind != SealConfidential || s.Vout != nil { + t.Fatalf("got %+v, want confidential seal with nil vout", s) + } + out, err := json.Marshal(s) + if err != nil { + t.Fatalf("marshal: %v", err) + } + if json.Valid(out) && containsKey(out, "vout") { + t.Fatalf("marshalled confidential seal must omit vout, got %s", out) + } +} + +func containsKey(raw []byte, key string) bool { + var m map[string]json.RawMessage + if err := json.Unmarshal(raw, &m); err != nil { + return false + } + _, ok := m[key] + return ok +} + func TestTransitionMetadataDecodesAndLooksUp(t *testing.T) { raw := `{"op_id":"op","transition_type":8010,"input_count":1,"fungible_allocations":[],` + `"metadata":[{"meta_type":1001,"value_hex":"1027000000000000"},{"meta_type":1003,"value_hex":"` + diff --git a/rgbconsignment/types.go b/rgbconsignment/types.go index 8b63dc3..2e58f1b 100644 --- a/rgbconsignment/types.go +++ b/rgbconsignment/types.go @@ -73,10 +73,13 @@ const ( ) type Seal struct { - Kind SealKind `json:"kind"` - Txid *string `json:"txid,omitempty"` - Vout uint32 `json:"vout"` - SecretSeal string `json:"secret_seal,omitempty"` + Kind SealKind `json:"kind"` + Txid *string `json:"txid,omitempty"` + // Vout is present only for revealed seals. A plain uint32 would decode an + // absent vout (confidential seals carry none) as 0, inviting consumers to + // mistake it for txout 0 — so it is a pointer and omitted when absent. + Vout *uint32 `json:"vout,omitempty"` + SecretSeal string `json:"secret_seal,omitempty"` } type TransitionInfo struct {