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 {
213 if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
217 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
221 if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
226 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
229 if inp.Vote, err = blockchain.ReadVarstr31(r); err != nil {
243 func (t *TxInput) writeTo(w io.Writer) error {
244 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
245 return errors.Wrap(err, "writing asset version")
248 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
249 return errors.Wrap(err, "writing input commitment")
252 if _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness); err != nil {
253 return errors.Wrap(err, "writing input witness")
259 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
260 if t.AssetVersion != 1 {
264 switch inp := t.TypedInput.(type) {
266 if _, err = w.Write([]byte{SpendInputType}); err != nil {
269 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
271 case *CrossChainInput:
272 if _, err = w.Write([]byte{CrossChainInputType}); err != nil {
275 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
278 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
281 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
282 return errors.Wrap(err, "writing coinbase arbitrary")
286 if _, err = w.Write([]byte{VetoInputType}); err != nil {
289 return inp.SpendCommitment.writeExtensibleString(w, inp.UnvoteCommitmentSuffix, t.AssetVersion)
294 func (t *TxInput) writeInputWitness(w io.Writer) error {
295 if t.AssetVersion != 1 {
299 switch inp := t.TypedInput.(type) {
301 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
304 case *CrossChainInput:
305 if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
309 if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
313 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
317 _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram)
321 if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
324 _, err := blockchain.WriteVarstr31(w, inp.Vote)