7 "github.com/bytom/vapor/encoding/blockchain"
8 "github.com/bytom/vapor/errors"
9 "github.com/bytom/vapor/protocol/bc"
12 // serflag variables for input types.
14 CrossChainInputType uint8 = iota
21 // TxInput is the top level struct of tx input.
25 CommitmentSuffix []byte
29 // TypedInput return the txinput type.
30 TypedInput interface {
35 // AssetAmount return the asset id and amount of the txinput.
36 func (t *TxInput) AssetAmount() bc.AssetAmount {
37 switch inp := t.TypedInput.(type) {
39 return inp.AssetAmount
41 case *CrossChainInput:
42 return inp.AssetAmount
45 return inp.AssetAmount
48 return bc.AssetAmount{}
51 // AssetID return the assetID of the txinput
52 func (t *TxInput) AssetID() bc.AssetID {
53 switch inp := t.TypedInput.(type) {
57 case *CrossChainInput:
58 return *inp.AssetAmount.AssetId
67 // Amount return the asset amount of the txinput
68 func (t *TxInput) Amount() uint64 {
69 switch inp := t.TypedInput.(type) {
73 case *CrossChainInput:
74 return inp.AssetAmount.Amount
83 // ControlProgram return the control program of the spend input
84 func (t *TxInput) ControlProgram() []byte {
85 switch inp := t.TypedInput.(type) {
87 return inp.ControlProgram
89 case *CrossChainInput:
90 return inp.ControlProgram
93 return inp.ControlProgram
100 // Arguments get the args for the input
101 func (t *TxInput) Arguments() [][]byte {
102 switch inp := t.TypedInput.(type) {
106 case *CrossChainInput:
115 // SetArguments set the args for the input
116 func (t *TxInput) SetArguments(args [][]byte) {
117 switch inp := t.TypedInput.(type) {
121 case *CrossChainInput:
129 // SpentOutputID calculate the hash of spended output
130 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
131 switch inp := t.TypedInput.(type) {
133 o, err = ComputeOutputID(&inp.SpendCommitment, SpendInputType, nil)
136 o, err = ComputeOutputID(&inp.SpendCommitment, VetoInputType, inp.Vote)
138 case *CrossChainInput:
139 o, err = ComputeOutputID(&inp.SpendCommitment, SpendInputType, nil)
145 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
146 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
150 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
151 if t.AssetVersion != 1 {
155 if _, err = io.ReadFull(r, icType[:]); err != nil {
156 return errors.Wrap(err, "reading input commitment type")
161 si := new(SpendInput)
163 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
167 case CoinbaseInputType:
168 ci := new(CoinbaseInput)
170 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
174 case CrossChainInputType:
175 ci := new(CrossChainInput)
177 if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
181 if ci.IssuanceVMVersion, err = blockchain.ReadVarint63(r); err != nil {
185 if ci.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
189 if ci.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
196 if ui.VetoCommitmentSuffix, err = ui.SpendCommitment.readFrom(r, 1); err != nil {
200 if ui.Vote, err = blockchain.ReadVarstr31(r); err != nil {
205 return fmt.Errorf("unsupported input type %d", icType[0])
213 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
214 if t.AssetVersion != 1 {
219 switch inp := t.TypedInput.(type) {
221 inp.Arguments, err = blockchain.ReadVarstrList(r)
223 case *CrossChainInput:
224 inp.Arguments, err = blockchain.ReadVarstrList(r)
227 inp.Arguments, err = blockchain.ReadVarstrList(r)
235 func (t *TxInput) writeTo(w io.Writer) error {
236 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
237 return errors.Wrap(err, "writing asset version")
240 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
241 return errors.Wrap(err, "writing input commitment")
244 if _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness); err != nil {
245 return errors.Wrap(err, "writing input witness")
251 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
252 if t.AssetVersion != 1 {
256 switch inp := t.TypedInput.(type) {
258 if _, err = w.Write([]byte{SpendInputType}); err != nil {
262 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
264 case *CrossChainInput:
265 if _, err = w.Write([]byte{CrossChainInputType}); err != nil {
269 if err := inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion); err != nil {
273 if _, err := blockchain.WriteVarint63(w, inp.IssuanceVMVersion); err != nil {
277 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
281 if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
286 if _, err := w.Write([]byte{CoinbaseInputType}); err != nil {
290 if _, err := blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
291 return errors.Wrap(err, "writing coinbase arbitrary")
295 if _, err = w.Write([]byte{VetoInputType}); err != nil {
299 if err := inp.SpendCommitment.writeExtensibleString(w, inp.VetoCommitmentSuffix, t.AssetVersion); err != nil {
303 _, err := blockchain.WriteVarstr31(w, inp.Vote)
309 func (t *TxInput) writeInputWitness(w io.Writer) error {
310 if t.AssetVersion != 1 {
315 switch inp := t.TypedInput.(type) {
317 _, err = blockchain.WriteVarstrList(w, inp.Arguments)
319 case *CrossChainInput:
320 _, err = blockchain.WriteVarstrList(w, inp.Arguments)
323 _, err = blockchain.WriteVarstrList(w, inp.Arguments)