github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/bc/types/txoutput.go (about) 1 package types 2 3 import ( 4 "io" 5 6 "github.com/bytom/bytom/encoding/blockchain" 7 "github.com/bytom/bytom/errors" 8 "github.com/bytom/bytom/protocol/bc" 9 ) 10 11 // TxOutput is the top level struct of tx output. 12 type TxOutput struct { 13 AssetVersion uint64 14 OutputCommitment 15 // Unconsumed suffixes of the commitment and witness extensible strings. 16 CommitmentSuffix []byte 17 } 18 19 // NewTxOutput create a new output struct 20 func NewTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput { 21 return &TxOutput{ 22 AssetVersion: 1, 23 OutputCommitment: OutputCommitment{ 24 AssetAmount: bc.AssetAmount{ 25 AssetId: &assetID, 26 Amount: amount, 27 }, 28 VMVersion: 1, 29 ControlProgram: controlProgram, 30 }, 31 } 32 } 33 34 func (to *TxOutput) readFrom(r *blockchain.Reader) (err error) { 35 if to.AssetVersion, err = blockchain.ReadVarint63(r); err != nil { 36 return errors.Wrap(err, "reading asset version") 37 } 38 39 if to.CommitmentSuffix, err = to.OutputCommitment.readFrom(r, to.AssetVersion); err != nil { 40 return errors.Wrap(err, "reading output commitment") 41 } 42 43 // read and ignore the (empty) output witness 44 _, err = blockchain.ReadVarstr31(r) 45 return errors.Wrap(err, "reading output witness") 46 } 47 48 func (to *TxOutput) writeTo(w io.Writer) error { 49 if _, err := blockchain.WriteVarint63(w, to.AssetVersion); err != nil { 50 return errors.Wrap(err, "writing asset version") 51 } 52 53 if err := to.writeCommitment(w); err != nil { 54 return errors.Wrap(err, "writing output commitment") 55 } 56 57 if _, err := blockchain.WriteVarstr31(w, nil); err != nil { 58 return errors.Wrap(err, "writing witness") 59 } 60 return nil 61 } 62 63 func (to *TxOutput) writeCommitment(w io.Writer) error { 64 return to.OutputCommitment.writeExtensibleString(w, to.CommitmentSuffix, to.AssetVersion) 65 } 66 67 // ComputeOutputID assembles an output entry given a spend commitment and 68 // computes and returns its corresponding entry ID. 69 func ComputeOutputID(sc *SpendCommitment) (h bc.Hash, err error) { 70 defer func() { 71 if r, ok := recover().(error); ok { 72 err = r 73 } 74 }() 75 src := &bc.ValueSource{ 76 Ref: &sc.SourceID, 77 Value: &sc.AssetAmount, 78 Position: sc.SourcePosition, 79 } 80 o := bc.NewOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0) 81 82 h = bc.EntryID(o) 83 return h, nil 84 }