OSDN Git Service

Dev (#148)
[bytom/bytom.git] / protocol / bc / legacy / txoutput.go
1 package legacy
2
3 import (
4         "io"
5
6         "github.com/bytom/encoding/blockchain"
7         "github.com/bytom/errors"
8         "github.com/bytom/protocol/bc"
9 )
10
11 // TODO(bobg): Review serialization/deserialization logic for
12 // assetVersions other than 1.
13
14 type TxOutput struct {
15         AssetVersion uint64
16         OutputCommitment
17
18         // Unconsumed suffixes of the commitment and witness extensible strings.
19         CommitmentSuffix []byte
20         WitnessSuffix    []byte
21
22         ReferenceData []byte
23 }
24
25 func NewTxOutput(assetID bc.AssetID, amount uint64, controlProgram, referenceData []byte) *TxOutput {
26         return &TxOutput{
27                 AssetVersion: 1,
28                 OutputCommitment: OutputCommitment{
29                         AssetAmount: bc.AssetAmount{
30                                 AssetId: &assetID,
31                                 Amount:  amount,
32                         },
33                         VMVersion:      1,
34                         ControlProgram: controlProgram,
35                 },
36                 ReferenceData: referenceData,
37         }
38 }
39
40 func (to *TxOutput) readFrom(r *blockchain.Reader, txVersion uint64) (err error) {
41         to.AssetVersion, err = blockchain.ReadVarint63(r)
42         if err != nil {
43                 return errors.Wrap(err, "reading asset version")
44         }
45
46         to.CommitmentSuffix, err = to.OutputCommitment.readFrom(r, to.AssetVersion)
47         if err != nil {
48                 return errors.Wrap(err, "reading output commitment")
49         }
50
51         to.ReferenceData, err = blockchain.ReadVarstr31(r)
52         if err != nil {
53                 return errors.Wrap(err, "reading reference data")
54         }
55
56         // read and ignore the (empty) output witness
57         _, err = blockchain.ReadVarstr31(r)
58
59         return errors.Wrap(err, "reading output witness")
60 }
61
62 func (to *TxOutput) writeTo(w io.Writer, serflags byte) error {
63         if _, err := blockchain.WriteVarint63(w, to.AssetVersion); err != nil {
64                 return errors.Wrap(err, "writing asset version")
65         }
66
67         if err := to.WriteCommitment(w); err != nil {
68                 return errors.Wrap(err, "writing output commitment")
69         }
70
71         if err := writeRefData(w, to.ReferenceData, serflags); err != nil {
72                 return errors.Wrap(err, "writing reference data")
73         }
74
75         // write witness (empty in v1)
76         if _, err := blockchain.WriteVarstr31(w, nil); err != nil {
77                 return errors.Wrap(err, "writing witness")
78         }
79         return nil
80 }
81
82 func (to *TxOutput) WriteCommitment(w io.Writer) error {
83         return to.OutputCommitment.writeExtensibleString(w, to.CommitmentSuffix, to.AssetVersion)
84 }
85
86 func (to *TxOutput) CommitmentHash() bc.Hash {
87         return to.OutputCommitment.Hash(to.CommitmentSuffix, to.AssetVersion)
88 }
89
90 // ComputeOutputID assembles an output entry given a spend commitment
91 // and computes and returns its corresponding entry ID.
92 func ComputeOutputID(sc *SpendCommitment) (h bc.Hash, err error) {
93         defer func() {
94                 if r, ok := recover().(error); ok {
95                         err = r
96                 }
97         }()
98         src := &bc.ValueSource{
99                 Ref:      &sc.SourceID,
100                 Value:    &sc.AssetAmount,
101                 Position: sc.SourcePosition,
102         }
103         o := bc.NewOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, &sc.RefDataHash, 0)
104
105         h = bc.EntryID(o)
106         return h, nil
107 }