7 "github.com/vapor/encoding/blockchain"
8 "github.com/vapor/errors"
9 "github.com/vapor/protocol/bc"
12 // serflag variables for input types.
14 IssuanceInputType uint8 = iota
22 // TxInput is the top level struct of tx input.
26 CommitmentSuffix []byte
31 // TypedInput return the txinput type.
32 TypedInput interface {
37 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
39 // AssetAmount return the asset id and amount of the txinput.
40 func (t *TxInput) AssetAmount() bc.AssetAmount {
41 switch inp := t.TypedInput.(type) {
43 assetID := inp.AssetID()
44 return bc.AssetAmount{
49 return inp.AssetAmount
51 return inp.AssetAmount
53 return inp.AssetAmount
55 return bc.AssetAmount{}
58 // AssetID return the assetID of the txinput
59 func (t *TxInput) AssetID() bc.AssetID {
60 switch inp := t.TypedInput.(type) {
74 // Amount return the asset amount of the txinput
75 func (t *TxInput) Amount() uint64 {
76 switch inp := t.TypedInput.(type) {
89 // ControlProgram return the control program of the spend input
90 func (t *TxInput) ControlProgram() []byte {
91 if si, ok := t.TypedInput.(*SpendInput); ok {
92 return si.ControlProgram
97 // IssuanceProgram return the control program of the issuance input
98 func (t *TxInput) IssuanceProgram() []byte {
99 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
100 return ii.IssuanceProgram
105 // AssetDefinition return the asset definition of the issuance input
106 func (t *TxInput) AssetDefinition() []byte {
107 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
108 return ii.AssetDefinition
113 // Arguments get the args for the input
114 func (t *TxInput) Arguments() [][]byte {
115 switch inp := t.TypedInput.(type) {
128 // SetArguments set the args for the input
129 func (t *TxInput) SetArguments(args [][]byte) {
130 switch inp := t.TypedInput.(type) {
142 // SpentOutputID calculate the hash of spended output
143 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
144 if si, ok := t.TypedInput.(*SpendInput); ok {
145 o, err = ComputeOutputID(&si.SpendCommitment)
150 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
151 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
155 if t.Peginwitness, err = blockchain.ReadVarstrList(r); err != nil {
158 var assetID bc.AssetID
159 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
160 if t.AssetVersion != 1 {
164 if _, err = io.ReadFull(r, icType[:]); err != nil {
165 return errors.Wrap(err, "reading input commitment type")
168 case IssuanceInputType:
169 ii := new(IssuanceInput)
172 if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
175 if _, err = assetID.ReadFrom(r); err != nil {
178 if ii.Amount, err = blockchain.ReadVarint63(r); err != nil {
183 si := new(SpendInput)
185 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
188 case ClainPeginInputType:
189 ci := new(ClaimInput)
191 if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
194 case CoinbaseInputType:
195 ci := new(CoinbaseInput)
197 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
203 if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
207 return fmt.Errorf("unsupported input type %d", icType[0])
215 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
216 if t.AssetVersion != 1 {
220 switch inp := t.TypedInput.(type) {
222 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
225 if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
228 if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
231 if inp.AssetID() != assetID {
234 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
239 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
243 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
248 if txType, err = blockchain.ReadVarint63(r); err != nil {
251 inp.Type = TxType(txType)
253 if from, err = blockchain.ReadVarstr31(r); err != nil {
256 inp.From = string(from)
258 if to, err = blockchain.ReadVarstr31(r); err != nil {
262 if inp.Amount, err = blockchain.ReadVarint63(r); err != nil {
265 if inp.Stake, err = blockchain.ReadVarint63(r); err != nil {
268 if inp.PaymentAmount, err = blockchain.ReadVarint63(r); err != nil {
271 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
276 if info, err = blockchain.ReadVarstr31(r); err != nil {
279 inp.Info = string(info)
287 func (t *TxInput) writeTo(w io.Writer) error {
288 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
289 return errors.Wrap(err, "writing asset version")
292 if _, err := blockchain.WriteVarstrList(w, t.Peginwitness); err != nil {
293 return errors.Wrap(err, "writing pegin witness")
295 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
296 return errors.Wrap(err, "writing input commitment")
299 _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness)
300 return errors.Wrap(err, "writing input witness")
303 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
304 if t.AssetVersion != 1 {
308 switch inp := t.TypedInput.(type) {
310 if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
313 if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
316 assetID := t.AssetID()
317 if _, err = assetID.WriteTo(w); err != nil {
320 _, err = blockchain.WriteVarint63(w, inp.Amount)
324 if _, err = w.Write([]byte{SpendInputType}); err != nil {
327 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
329 if _, err = w.Write([]byte{ClainPeginInputType}); err != nil {
332 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
334 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
337 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
338 return errors.Wrap(err, "writing coinbase arbitrary")
341 if _, err = w.Write([]byte{DposInputType}); err != nil {
344 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
349 func (t *TxInput) writeInputWitness(w io.Writer) error {
350 if t.AssetVersion != 1 {
353 switch inp := t.TypedInput.(type) {
355 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
358 if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
361 if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
364 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
368 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
371 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
375 if _, err := blockchain.WriteVarint63(w, uint64(inp.Type)); err != nil {
378 if _, err := blockchain.WriteVarstr31(w, []byte(inp.From)); err != nil {
381 if _, err := blockchain.WriteVarstr31(w, []byte(inp.To)); err != nil {
384 if _, err := blockchain.WriteVarint63(w, inp.Amount); err != nil {
387 if _, err := blockchain.WriteVarint63(w, inp.Stake); err != nil {
390 if _, err := blockchain.WriteVarint63(w, inp.PaymentAmount); err != nil {
393 if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
396 _, err := blockchain.WriteVarstr31(w, []byte(inp.Info))