MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.
MIT License
1.87k stars 848 forks source link

Script Error: When spending coin in BTC #785

Open Ashish81 opened 4 years ago

Ashish81 commented 4 years ago

While trying to spend the below coin.. Live BTC 4c4b7d7cd0ab2c05e735d280901ac808f5eedc9deb09c300a3f98fd4b0754153

we get this error : Script error on input 0 (InvalidStackOperation)

NicolasDorier commented 4 years ago

show the code

Ashish81 commented 4 years ago

Using the transaction builder and then the verify method, somewhere in verify method throw the error. It is particularly with this coin. Others go well.

NicolasDorier commented 4 years ago

show the code

Ashish81 commented 4 years ago
var builder = new TransactionBuilder();
                    var b = builder
                        .AddCoins(usecoin)
                        .AddKeys(keys)
                        .SetChange(changeKey.ScriptPubKey);

                    //Adding addresses to send
                    request.ForEach(o =>
                    {
                        b.Send(BitcoinAddress.Create(o.Address, Config.Network), new Money((decimal)o.Coin, MoneyUnit.BTC));
                    });

                    var tx = b.BuildTransaction(false);
                    var feerate = new FeeRate(new Money(5000));//getFeeRAte(commision);
                    var fee = builder.EstimateFees(tx,feerate);
                    //if empty wallet...
                    if (emptywallet)
                    {
                        tx.Outputs.First().Value -= fee ;
                    }
                    tx = b.SendFees(fee).BuildTransaction(true);

                    if (!builder.Verify(tx,null as Money, out TransactionPolicyError[] errorsTx))
                    {
                        result.Message = "No fund not verified" + String.Join(", ", errorsTx.Select(o=> o.ToString()).AsEnumerable()) ;
                        return result;
                    }

                    BroadcastResponse broadcastResponse;
                    broadcastResponse = Client.Broadcast(tx);
                    if (!broadcastResponse.Success)
                    {
                        result.Message = "Error code: " + broadcastResponse.Error.ErrorCode + "  Reason:  " + broadcastResponse.Error.Reason;
                    }

Getting error on builder.Verify Digging dip i found that in class ScriptEvaluationContext , and the method evalscript() throwing error.

case OpcodeType.OP_VERIFY:
                                {
                                    // (true -- ) or
                                    // (false -- false) and return
                                    if(_stack.Count < 1)
                                        return SetError(ScriptError.InvalidStackOperation);

                                    if(!CastToBool(_stack.Top(-1)))
                                        return SetError(ScriptError.Verify);

                                    _stack.Pop();
                                    break;
                                }
NicolasDorier commented 4 years ago

Don't do this.

 tx.Outputs.First().Value -= fee ;

If you want to substract fee to one of the destination, just call .SubstractFee().

Fix this and try again.

Ashish81 commented 4 years ago

This line doestnt run as the emptywallet is always false. So no eefect in current scenario. What i want can you replicate at your end i can send you the private key

NicolasDorier commented 4 years ago

don't call twice BuildTransaction. You should not need to. If that still fail, then it means usecoin is not the right coin. Or if you use P2SH/P2WSH, you did not gave it the RedeemScript/

Ashish81 commented 4 years ago

How can i estimatefees if transaction is not built, second after sending the fees transaction need to build again i guess. Redeem script is given i hope the script when evaluated throw the error.

Possibly script is not valid script. Or evaluation method haa something missed. Actually cant figure out

Ashish81 commented 4 years ago

I am using qbit ninja toget coins by address. Which returs the coin and scripts.

NicolasDorier commented 4 years ago

How can i estimatefees if transaction is not built, second after sending the fees transaction need to build again i guess.

You use txbuilder.SendEstimatedFees(feeRate); and it will caluclate for you.