7 "chain/crypto/sha3pool"
8 "chain/encoding/blockchain"
13 // SpendInput satisfies the TypedInput interface and represents a spend transaction.
14 type SpendInput struct {
18 // The unconsumed suffix of the output commitment
19 SpendCommitmentSuffix []byte
25 func (si *SpendInput) IsIssuance() bool { return false }
27 func NewSpendInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount uint64, sourcePos uint64, controlProgram []byte, outRefDataHash bc.Hash, referenceData []byte) *TxInput {
32 sc := SpendCommitment{
33 AssetAmount: bc.AssetAmount{
38 SourcePosition: sourcePos,
40 ControlProgram: controlProgram,
41 RefDataHash: outRefDataHash,
44 AssetVersion: assetver,
45 ReferenceData: referenceData,
46 TypedInput: &SpendInput{
53 // SpendCommitment contains the commitment data for a transaction
54 // output (which also appears in the spend input of that output).
55 type SpendCommitment struct {
64 func (sc *SpendCommitment) writeExtensibleString(w io.Writer, suffix []byte, assetVersion uint64) error {
65 _, err := blockchain.WriteExtensibleString(w, suffix, func(w io.Writer) error {
66 return sc.writeContents(w, suffix, assetVersion)
71 func (sc *SpendCommitment) writeContents(w io.Writer, suffix []byte, assetVersion uint64) (err error) {
72 if assetVersion == 1 {
73 _, err = sc.SourceID.WriteTo(w)
75 return errors.Wrap(err, "writing source id")
77 _, err = sc.AssetAmount.WriteTo(w)
79 return errors.Wrap(err, "writing asset amount")
81 _, err = blockchain.WriteVarint63(w, sc.SourcePosition)
83 return errors.Wrap(err, "writing source position")
85 _, err = blockchain.WriteVarint63(w, sc.VMVersion)
87 return errors.Wrap(err, "writing vm version")
89 _, err = blockchain.WriteVarstr31(w, sc.ControlProgram)
91 return errors.Wrap(err, "writing control program")
93 _, err = sc.RefDataHash.WriteTo(w)
95 return errors.Wrap(err, "writing reference data hash")
99 _, err = w.Write(suffix)
101 return errors.Wrap(err, "writing suffix")
107 func (sc *SpendCommitment) readFrom(r *blockchain.Reader, assetVersion uint64) (suffix []byte, err error) {
108 return blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
109 if assetVersion == 1 {
110 _, err := sc.SourceID.ReadFrom(r)
112 return errors.Wrap(err, "reading source id")
114 err = sc.AssetAmount.ReadFrom(r)
116 return errors.Wrap(err, "reading asset+amount")
118 sc.SourcePosition, err = blockchain.ReadVarint63(r)
120 return errors.Wrap(err, "reading source position")
122 sc.VMVersion, err = blockchain.ReadVarint63(r)
124 return errors.Wrap(err, "reading VM version")
126 if sc.VMVersion != 1 {
127 return fmt.Errorf("unrecognized VM version %d for asset version 1", sc.VMVersion)
129 sc.ControlProgram, err = blockchain.ReadVarstr31(r)
131 return errors.Wrap(err, "reading control program")
133 _, err = sc.RefDataHash.ReadFrom(r)
135 return errors.Wrap(err, "reading reference data hash")
143 func (sc *SpendCommitment) Hash(suffix []byte, assetVersion uint64) (spendhash bc.Hash) {
144 h := sha3pool.Get256()
145 defer sha3pool.Put256(h)
146 sc.writeExtensibleString(h, suffix, assetVersion) // TODO(oleg): get rid of this assetVersion parameter to actually write all the bytes
147 spendhash.ReadFrom(h)