OSDN Git Service

update master (#487)
[bytom/bytom.git] / protocol / bc / types / txoutput.go
1 package types
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
23 func NewTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput {
24         return &TxOutput{
25                 AssetVersion: 1,
26                 OutputCommitment: OutputCommitment{
27                         AssetAmount: bc.AssetAmount{
28                                 AssetId: &assetID,
29                                 Amount:  amount,
30                         },
31                         VMVersion:      1,
32                         ControlProgram: controlProgram,
33                 },
34         }
35 }
36
37 func (to *TxOutput) readFrom(r *blockchain.Reader, txVersion uint64) (err error) {
38         to.AssetVersion, err = blockchain.ReadVarint63(r)
39         if err != nil {
40                 return errors.Wrap(err, "reading asset version")
41         }
42
43         to.CommitmentSuffix, err = to.OutputCommitment.readFrom(r, to.AssetVersion)
44         if err != nil {
45                 return errors.Wrap(err, "reading output commitment")
46         }
47
48         // read and ignore the (empty) output witness
49         _, err = blockchain.ReadVarstr31(r)
50
51         return errors.Wrap(err, "reading output witness")
52 }
53
54 func (to *TxOutput) writeTo(w io.Writer, serflags byte) error {
55         if _, err := blockchain.WriteVarint63(w, to.AssetVersion); err != nil {
56                 return errors.Wrap(err, "writing asset version")
57         }
58
59         if err := to.WriteCommitment(w); err != nil {
60                 return errors.Wrap(err, "writing output commitment")
61         }
62
63         // write witness (empty in v1)
64         if _, err := blockchain.WriteVarstr31(w, nil); err != nil {
65                 return errors.Wrap(err, "writing witness")
66         }
67         return nil
68 }
69
70 func (to *TxOutput) WriteCommitment(w io.Writer) error {
71         return to.OutputCommitment.writeExtensibleString(w, to.CommitmentSuffix, to.AssetVersion)
72 }
73
74 func (to *TxOutput) CommitmentHash() bc.Hash {
75         return to.OutputCommitment.Hash(to.CommitmentSuffix, to.AssetVersion)
76 }
77
78 // ComputeOutputID assembles an output entry given a spend commitment
79 // and computes and returns its corresponding entry ID.
80 func ComputeOutputID(sc *SpendCommitment) (h bc.Hash, err error) {
81         defer func() {
82                 if r, ok := recover().(error); ok {
83                         err = r
84                 }
85         }()
86         src := &bc.ValueSource{
87                 Ref:      &sc.SourceID,
88                 Value:    &sc.AssetAmount,
89                 Position: sc.SourcePosition,
90         }
91         o := bc.NewOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0)
92
93         h = bc.EntryID(o)
94         return h, nil
95 }