7 "github.com/bytom/encoding/blockchain"
8 "github.com/bytom/errors"
9 "github.com/bytom/protocol/bc"
17 // Unconsumed suffixes of the commitment and witness extensible
19 CommitmentSuffix []byte
23 TypedInput interface {
29 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
31 func (t *TxInput) AssetAmount() bc.AssetAmount {
32 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
33 assetID := ii.AssetID()
34 return bc.AssetAmount{
39 si := t.TypedInput.(*SpendInput)
43 func (t *TxInput) AssetID() bc.AssetID {
44 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
47 si := t.TypedInput.(*SpendInput)
51 func (t *TxInput) Amount() uint64 {
52 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
55 si := t.TypedInput.(*SpendInput)
59 func (t *TxInput) ControlProgram() []byte {
60 if si, ok := t.TypedInput.(*SpendInput); ok {
61 return si.ControlProgram
66 func (t *TxInput) IssuanceProgram() []byte {
67 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
68 return ii.IssuanceProgram
73 func (t *TxInput) Arguments() [][]byte {
74 switch inp := t.TypedInput.(type) {
83 func (t *TxInput) SetArguments(args [][]byte) {
84 switch inp := t.TypedInput.(type) {
92 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
93 t.AssetVersion, err = blockchain.ReadVarint63(r)
105 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
106 if t.AssetVersion != 1 {
110 if _, err = io.ReadFull(r, icType[:]); err != nil {
111 return errors.Wrap(err, "reading input commitment type")
115 ii = new(IssuanceInput)
117 ii.Nonce, err = blockchain.ReadVarstr31(r)
121 if _, err = assetID.ReadFrom(r); err != nil {
124 ii.Amount, err = blockchain.ReadVarint63(r)
131 si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1)
137 ci = new(CoinbaseInput)
138 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
143 return fmt.Errorf("unsupported input type %d", icType[0])
150 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
151 // TODO(bobg): test that serialization flags include SerWitness, when we relax the serflags-must-be-0x7 rule
152 if t.AssetVersion != 1 {
161 // read IssuanceInput witness
162 ii.AssetDefinition, err = blockchain.ReadVarstr31(r)
167 ii.VMVersion, err = blockchain.ReadVarint63(r)
172 ii.IssuanceProgram, err = blockchain.ReadVarstr31(r)
177 if ii.AssetID() != assetID {
181 args, err := blockchain.ReadVarstrList(r)
187 } else if si != nil {
197 } else if ii != nil {
199 } else if si != nil {
205 func (t *TxInput) writeTo(w io.Writer, serflags uint8) error {
206 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
207 return errors.Wrap(err, "writing asset version")
210 _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, func(w io.Writer) error {
211 return t.WriteInputCommitment(w, serflags)
214 return errors.Wrap(err, "writing input commitment")
218 if serflags&SerWitness != 0 {
219 if _, err = blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness); err != nil {
220 return errors.Wrap(err, "writing input witness")
227 func (t *TxInput) WriteInputCommitment(w io.Writer, serflags uint8) (err error) {
228 if t.AssetVersion != 1 {
231 switch inp := t.TypedInput.(type) {
233 if _, err = w.Write([]byte{0}); err != nil {
236 if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
239 assetID := t.AssetID()
240 if _, err = assetID.WriteTo(w); err != nil {
243 _, err = blockchain.WriteVarint63(w, inp.Amount)
247 if _, err = w.Write([]byte{1}); err != nil {
250 if serflags&SerPrevout != 0 {
251 err = inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
253 prevouthash := inp.SpendCommitment.Hash(inp.SpendCommitmentSuffix, t.AssetVersion)
254 _, err = prevouthash.WriteTo(w)
259 if _, err = w.Write([]byte{2}); err != nil {
262 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
263 return errors.Wrap(err, "writing coinbase arbitrary")
269 func (t *TxInput) writeInputWitness(w io.Writer) error {
270 if t.AssetVersion != 1 {
273 switch inp := t.TypedInput.(type) {
275 _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition)
279 _, err = blockchain.WriteVarint63(w, inp.VMVersion)
283 _, err = blockchain.WriteVarstr31(w, inp.IssuanceProgram)
287 _, err = blockchain.WriteVarstrList(w, inp.Arguments)
291 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
297 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
298 if si, ok := t.TypedInput.(*SpendInput); ok {
299 o, err = ComputeOutputID(&si.SpendCommitment)