7 "github.com/bytom/errors"
8 "github.com/bytom/protocol"
9 "github.com/bytom/protocol/bc/types"
10 "github.com/bytom/protocol/vm"
14 // ErrRejected means the network rejected a tx (as a double-spend)
15 ErrRejected = errors.New("transaction rejected")
16 // ErrMissingRawTx means missing transaction
17 ErrMissingRawTx = errors.New("missing raw tx")
18 // ErrBadInstructionCount means too many signing instructions compare with inputs
19 ErrBadInstructionCount = errors.New("too many signing instructions in template")
22 // FinalizeTx validates a transaction signature template,
23 // assembles a fully signed tx, and stores the effects of
24 // its changes on the UTXO set.
25 func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error {
26 err := checkTxSighashCommitment(tx)
31 _, err = c.ValidateTx(tx)
32 if errors.Root(err) == protocol.ErrBadTx {
33 return errors.Sub(ErrRejected, err)
36 return errors.Wrap(err, "tx rejected")
39 return errors.Wrap(err)
43 // ErrNoTxSighashCommitment is returned when no input commits to the
44 // complete transaction.
45 // To permit idempotence of transaction submission, we require at
46 // least one input to commit to the complete transaction (what you get
47 // when you build a transaction with allow_additional_actions=false).
48 ErrNoTxSighashCommitment = errors.New("no commitment to tx sighash")
50 // ErrNoTxSighashAttempt is returned when there was no attempt made to sign
52 ErrNoTxSighashAttempt = errors.New("no tx sighash attempted")
54 // ErrTxSignatureFailure is returned when there was an attempt to sign this
55 // transaction, but it failed.
56 ErrTxSignatureFailure = errors.New("tx signature was attempted but failed")
59 func checkTxSighashCommitment(tx *types.Tx) error {
60 // TODO: this is the local sender check rules, we might don't need it due to the rule is difference
64 for i, inp := range tx.Inputs {
66 switch t := inp.TypedInput.(type) {
67 case *types.SpendInput:
69 case *types.IssuanceInput:
72 // Note: These numbers will need to change if more args are added such that the minimum length changes
74 // A conforming arguments list contains
75 // [... arg1 arg2 ... argN N sig1 sig2 ... sigM prog]
76 // The args are the opaque arguments to prog. In the case where
77 // N is 0 (prog takes no args), and assuming there must be at
78 // least one signature, args has a minimum length of 3.
80 lastError = ErrNoTxSighashAttempt
83 lastError = ErrTxSignatureFailure
86 lastError = ErrNoTxSighashCommitment
87 prog := args[len(args)-1]
91 if prog[0] != byte(vm.OP_DATA_32) {
94 if !bytes.Equal(prog[33:], []byte{byte(vm.OP_TXSIGHASH), byte(vm.OP_EQUAL)}) {
97 h := tx.SigHash(uint32(i))
98 if !bytes.Equal(h.Bytes(), prog[1:33]) {
101 // At least one input passes commitment checks
108 // RemoteGenerator implements the Submitter interface and submits the
109 // transaction to a remote generator.
110 // TODO(jackson): This implementation maybe belongs elsewhere.
111 /*type RemoteGenerator struct {
115 func (rg *RemoteGenerator) Submit(ctx context.Context, tx *types.Tx) error {
116 err := rg.Peer.Call(ctx, "/rpc/submit", tx, nil)
117 err = errors.Wrap(err, "generator transaction notice")