7 "github.com/vapor/encoding/blockchain"
8 "github.com/vapor/errors"
9 "github.com/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 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
37 // AssetAmount return the asset id and amount of the txinput.
38 func (t *TxInput) AssetAmount() bc.AssetAmount {
39 switch inp := t.TypedInput.(type) {
41 return inp.AssetAmount
43 case *CrossChainInput:
44 return inp.AssetAmount
47 return inp.AssetAmount
50 return bc.AssetAmount{}
53 // AssetID return the assetID of the txinput
54 func (t *TxInput) AssetID() bc.AssetID {
55 switch inp := t.TypedInput.(type) {
59 case *CrossChainInput:
60 return *inp.AssetAmount.AssetId
69 // Amount return the asset amount of the txinput
70 func (t *TxInput) Amount() uint64 {
71 switch inp := t.TypedInput.(type) {
75 case *CrossChainInput:
76 return inp.AssetAmount.Amount
85 // ControlProgram return the control program of the spend input
86 func (t *TxInput) ControlProgram() []byte {
87 switch inp := t.TypedInput.(type) {
89 return inp.ControlProgram
91 case *CrossChainInput:
92 return inp.ControlProgram
95 return inp.ControlProgram
102 // Arguments get the args for the input
103 func (t *TxInput) Arguments() [][]byte {
104 switch inp := t.TypedInput.(type) {
108 case *CrossChainInput:
117 // SetArguments set the args for the input
118 func (t *TxInput) SetArguments(args [][]byte) {
119 switch inp := t.TypedInput.(type) {
123 case *CrossChainInput:
131 // SpentOutputID calculate the hash of spended output
132 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
133 switch inp := t.TypedInput.(type) {
135 o, err = ComputeOutputID(&inp.SpendCommitment, SpendInputType, nil)
138 o, err = ComputeOutputID(&inp.SpendCommitment, VetoInputType, inp.Vote)
144 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
145 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
149 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
150 if t.AssetVersion != 1 {
154 if _, err = io.ReadFull(r, icType[:]); err != nil {
155 return errors.Wrap(err, "reading input commitment type")
160 si := new(SpendInput)
162 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
166 case CoinbaseInputType:
167 ci := new(CoinbaseInput)
169 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
173 case CrossChainInputType:
174 ci := new(CrossChainInput)
176 if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
183 if ui.UnvoteCommitmentSuffix, err = ui.SpendCommitment.readFrom(r, 1); err != nil {
189 return fmt.Errorf("unsupported input type %d", icType[0])
197 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
198 if t.AssetVersion != 1 {
202 switch inp := t.TypedInput.(type) {
204 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
208 case *CrossChainInput:
209 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
214 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
217 if inp.Vote, err = blockchain.ReadVarstr31(r); err != nil {
228 switch inp := t.TypedInput.(type) {
229 case *CrossChainInput:
230 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
238 func (t *TxInput) writeTo(w io.Writer) error {
239 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
240 return errors.Wrap(err, "writing asset version")
243 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
244 return errors.Wrap(err, "writing input commitment")
247 if _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness); err != nil {
248 return errors.Wrap(err, "writing input witness")
251 switch inp := t.TypedInput.(type) {
252 case *CrossChainInput:
253 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
254 return errors.Wrap(err, "writing AssetDefinition")
261 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
262 if t.AssetVersion != 1 {
266 switch inp := t.TypedInput.(type) {
268 if _, err = w.Write([]byte{SpendInputType}); err != nil {
271 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
273 case *CrossChainInput:
274 if _, err = w.Write([]byte{CrossChainInputType}); err != nil {
277 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
280 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
283 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
284 return errors.Wrap(err, "writing coinbase arbitrary")
288 if _, err = w.Write([]byte{VetoInputType}); err != nil {
291 return inp.SpendCommitment.writeExtensibleString(w, inp.UnvoteCommitmentSuffix, t.AssetVersion)
296 func (t *TxInput) writeInputWitness(w io.Writer) error {
297 if t.AssetVersion != 1 {
301 switch inp := t.TypedInput.(type) {
303 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
306 case *CrossChainInput:
307 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
310 if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
313 _, err := blockchain.WriteVarstr31(w, inp.Vote)