Skip to content

Commit 96f5120

Browse files
committed
add utxo id to siacoin and siafund json marshalling
1 parent 8d9c47c commit 96f5120

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: minor
3+
---
4+
5+
# Added UTXO IDs to v1 transaction JSON marshalling

types/types.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,13 +430,42 @@ type Transaction struct {
430430

431431
// MarshalJSON implements json.Marshaler.
432432
//
433-
// For convenience, the transaction's ID is also calculated and included. This field is ignored during unmarshalling.
433+
// The transaction and UTXO IDs are calculated and included for convenience.
434+
// These fields are ignored during unmarshalling.
434435
func (txn Transaction) MarshalJSON() ([]byte, error) {
435-
type jsonTxn Transaction // prevent recursion
436-
return json.Marshal(struct {
437-
ID TransactionID `json:"id"`
436+
type jsonTxn Transaction
437+
type jsonSiacoinOutput struct {
438+
ID SiacoinOutputID `json:"id"`
439+
SiacoinOutput
440+
}
441+
type jsonSiafundOutput struct {
442+
ID SiafundOutputID `json:"id"`
443+
SiafundOutput
444+
}
445+
obj := struct {
446+
ID TransactionID `json:"id"`
447+
SiacoinOutputs []jsonSiacoinOutput `json:"siacoinOutputs,omitempty"`
448+
SiafundOutputs []jsonSiafundOutput `json:"siafundOutputs,omitempty"`
438449
jsonTxn
439-
}{txn.ID(), jsonTxn(txn)})
450+
}{
451+
ID: txn.ID(),
452+
jsonTxn: jsonTxn(txn),
453+
SiacoinOutputs: make([]jsonSiacoinOutput, 0, len(txn.SiacoinOutputs)),
454+
SiafundOutputs: make([]jsonSiafundOutput, 0, len(txn.SiafundOutputs)),
455+
}
456+
for i := range txn.SiacoinOutputs {
457+
obj.SiacoinOutputs = append(obj.SiacoinOutputs, jsonSiacoinOutput{
458+
ID: txn.SiacoinOutputID(i),
459+
SiacoinOutput: txn.SiacoinOutputs[i],
460+
})
461+
}
462+
for i := range txn.SiafundOutputs {
463+
obj.SiafundOutputs = append(obj.SiafundOutputs, jsonSiafundOutput{
464+
ID: txn.SiafundOutputID(i),
465+
SiafundOutput: txn.SiafundOutputs[i],
466+
})
467+
}
468+
return json.Marshal(obj)
440469
}
441470

442471
// ID returns the "semantic hash" of the transaction, covering all of the

types/types_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,20 @@ func TestTransactionJSONMarshalling(t *testing.T) {
775775
},
776776
},
777777
},
778+
SiafundInputs: []SiafundInput{
779+
{
780+
ParentID: frand.Entropy256(),
781+
UnlockConditions: UnlockConditions{
782+
PublicKeys: []UnlockKey{
783+
PublicKey(frand.Entropy256()).UnlockKey(),
784+
},
785+
SignaturesRequired: 1,
786+
},
787+
},
788+
},
789+
SiafundOutputs: []SiafundOutput{
790+
{Address: frand.Entropy256(), Value: frand.Uint64n(10000)},
791+
},
778792
}
779793
expectedID := txn.ID()
780794

@@ -790,11 +804,43 @@ func TestTransactionJSONMarshalling(t *testing.T) {
790804
t.Fatalf("expected ID %q, got %q", expectedID.String(), txnMap["id"].(string))
791805
}
792806

807+
expectedSiacoinID := txn.SiacoinOutputID(0)
808+
siacoinOutputID := txnMap["siacoinOutputs"].([]any)[0].(map[string]any)["id"].(string)
809+
if siacoinOutputID != expectedSiacoinID.String() {
810+
t.Fatalf("expected siacoin output id %q, got %q", expectedSiacoinID.String(), siacoinOutputID)
811+
}
812+
813+
expectedSiafundID := txn.SiafundOutputID(0)
814+
siafundOutputID := txnMap["siafundOutputs"].([]any)[0].(map[string]any)["id"].(string)
815+
if siafundOutputID != expectedSiafundID.String() {
816+
t.Fatalf("expected siafund output id %q, got %q", expectedSiafundID.String(), siafundOutputID)
817+
}
818+
819+
expectedSiacoinInputAddress := txn.SiacoinInputs[0].UnlockConditions.UnlockHash()
820+
siacoinInputAddress := txnMap["siacoinInputs"].([]any)[0].(map[string]any)["address"].(string)
821+
if siacoinInputAddress != expectedSiacoinInputAddress.String() {
822+
t.Fatalf("expected siacoin input address %q, got %q", expectedSiacoinInputAddress.String(), siacoinInputAddress)
823+
}
824+
825+
expectedSiafundInputAddress := txn.SiafundInputs[0].UnlockConditions.UnlockHash()
826+
siafundInputAddress := txnMap["siafundInputs"].([]any)[0].(map[string]any)["address"].(string)
827+
if siafundInputAddress != expectedSiafundInputAddress.String() {
828+
t.Fatalf("expected siafund input address %q, got %q", expectedSiafundInputAddress.String(), siafundInputAddress)
829+
}
830+
793831
var txn2 Transaction
794832
if err := json.Unmarshal(buf, &txn2); err != nil {
795833
t.Fatal(err)
796834
} else if txn2.ID() != expectedID {
797835
t.Fatalf("expected unmarshalled ID to be %q, got %q", expectedID, txn2.ID())
836+
} else if txn2.SiacoinOutputID(0) != expectedSiacoinID {
837+
t.Fatalf("expected unmarshalled siacoin output id to be %q, got %q", expectedSiacoinID, txn2.SiacoinOutputID(0))
838+
} else if txn2.SiafundOutputID(0) != expectedSiafundID {
839+
t.Fatalf("expected unmarshalled siafund output id to be %q, got %q", expectedSiafundID, txn2.SiafundOutputID(0))
840+
} else if txn2.SiacoinInputs[0].UnlockConditions.UnlockHash() != expectedSiacoinInputAddress {
841+
t.Fatalf("expected unmarshalled siacoin input address to be %q, got %q", expectedSiacoinInputAddress, txn2.SiacoinInputs[0].UnlockConditions.UnlockHash())
842+
} else if txn2.SiafundInputs[0].UnlockConditions.UnlockHash() != expectedSiafundInputAddress {
843+
t.Fatalf("expected unmarshalled siafund input address to be %q, got %q", expectedSiafundInputAddress, txn2.SiafundInputs[0].UnlockConditions.UnlockHash())
798844
}
799845
}
800846

0 commit comments

Comments
 (0)