7 "github.com/vapor/encoding/blockchain"
8 "github.com/vapor/errors"
9 "github.com/vapor/protocol/bc/types/bytom"
12 // serflag variables for input types.
14 IssuanceInputType uint8 = iota
20 // TxInput is the top level struct of tx input.
24 CommitmentSuffix []byte
28 // TypedInput return the txinput type.
29 TypedInput interface {
34 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
36 // AssetAmount return the asset id and amount of the txinput.
37 func (t *TxInput) AssetAmount() bytom.AssetAmount {
38 switch inp := t.TypedInput.(type) {
40 assetID := inp.AssetID()
41 return bytom.AssetAmount{
46 return inp.AssetAmount
48 return bytom.AssetAmount{}
51 // AssetID return the assetID of the txinput
52 func (t *TxInput) AssetID() bytom.AssetID {
53 switch inp := t.TypedInput.(type) {
60 return bytom.AssetID{}
63 // Amount return the asset amount of the txinput
64 func (t *TxInput) Amount() uint64 {
65 switch inp := t.TypedInput.(type) {
74 // ControlProgram return the control program of the spend input
75 func (t *TxInput) ControlProgram() []byte {
76 if si, ok := t.TypedInput.(*SpendInput); ok {
77 return si.ControlProgram
82 // IssuanceProgram return the control program of the issuance input
83 func (t *TxInput) IssuanceProgram() []byte {
84 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
85 return ii.IssuanceProgram
90 // Arguments get the args for the input
91 func (t *TxInput) Arguments() [][]byte {
92 switch inp := t.TypedInput.(type) {
101 // SetArguments set the args for the input
102 func (t *TxInput) SetArguments(args [][]byte) {
103 switch inp := t.TypedInput.(type) {
111 // SpentOutputID calculate the hash of spended output
112 func (t *TxInput) SpentOutputID() (o bytom.Hash, err error) {
113 if si, ok := t.TypedInput.(*SpendInput); ok {
114 o, err = ComputeOutputID(&si.SpendCommitment)
119 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
120 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
124 var assetID bytom.AssetID
125 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
126 if t.AssetVersion != 1 {
130 if _, err = io.ReadFull(r, icType[:]); err != nil {
131 return errors.Wrap(err, "reading input commitment type")
134 case IssuanceInputType:
135 ii := new(IssuanceInput)
138 if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
141 if _, err = assetID.ReadFrom(r); err != nil {
144 if ii.Amount, err = blockchain.ReadVarint63(r); err != nil {
149 si := new(SpendInput)
151 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
155 case CoinbaseInputType:
156 ci := new(CoinbaseInput)
158 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
163 return fmt.Errorf("unsupported input type %d", icType[0])
171 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
172 if t.AssetVersion != 1 {
176 switch inp := t.TypedInput.(type) {
178 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
181 if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
184 if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
187 if inp.AssetID() != assetID {
190 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
195 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
205 func (t *TxInput) writeTo(w io.Writer) error {
206 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
207 return errors.Wrap(err, "writing asset version")
210 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
211 return errors.Wrap(err, "writing input commitment")
214 _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness)
215 return errors.Wrap(err, "writing input witness")
218 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
219 if t.AssetVersion != 1 {
223 switch inp := t.TypedInput.(type) {
225 if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
228 if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
231 assetID := t.AssetID()
232 if _, err = assetID.WriteTo(w); err != nil {
235 _, err = blockchain.WriteVarint63(w, inp.Amount)
239 if _, err = w.Write([]byte{SpendInputType}); err != nil {
242 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
245 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
248 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
249 return errors.Wrap(err, "writing coinbase arbitrary")
255 func (t *TxInput) writeInputWitness(w io.Writer) error {
256 if t.AssetVersion != 1 {
259 switch inp := t.TypedInput.(type) {
261 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
264 if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
267 if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
270 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
274 _, err := blockchain.WriteVarstrList(w, inp.Arguments)