Debugging "Transaction simulation failed" when sending program instruction (Solana Solidity) - solidity

When attempting to make a call to a program compiled with #solana/solidity, I'm getting the following error:
Transaction simulation failed: Error processing Instruction 0: Program failed to complete
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N invoke [1]
Program log: pxKTQePwHC9MiR52J5AYaRtSLAtkVfcoGS3GaLD24YX
Program log: sender account missing from transaction
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N consumed 200000 of 200000 compute units
Program failed to complete: BPF program Panicked in solana.c at 285:0
Program jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N failed: Program failed to complete
jdN1wZjg5P4xi718DG2HraGuxVx1mM7ebjXpxbJ5R3N is the program's public key and pxKTQePwHC9MiR52J5AYaRtSLAtkVfcoGS3GaLD24YX is the sender's public key.
I'm using a fork of the #solana/solidity library that exposes the Transaction object so that it can be signed and sent by Phantom Wallet on the front end. The code that results in the error is as follows:
// Generate the transaction
const transaction = contract.transactions.send(...args);
// Add recent blockhash and fee payer
const recentBlockhash = (await connection.getRecentBlockhash()).blockhash;
transaction.recentBlockhash = recentBlockhash;
transaction.feePayer = provider.publicKey;
// Sign and send the transaction (throws an error)
const res = await provider.signAndSendTransaction(transaction);
I would attempt to debug this further myself, but I'm not sure where to start. Looking up the error message hasn't yielded any results and the error message isn't very descriptive. I'm not sure if this error is occurring within the program execution itself or if it's an issue with the composition of the transaction object. If it is an issue within the program execution, is there a way for me to add logs to my solidity code? If it's an issue with the transaction object, what could be missing? How can I better debug issues like this?
Thank you for any help.
Edit: I'm getting a different error now, although I haven't changed any of the provided code. The error message is now the following:
Phantom - RPC Error: Transaction creation failed. {code: -32003, message: 'Transaction creation failed.'}
Unfortunately this error message is even less helpful than the last one. I'm not sure if Phantom Wallet was updated or if a project dependency was updated at some point, but given the vague nature of both of these error messages and the fact that none of my code has changed, I believe they're being caused by the same issue. Again, any help or debugging tips are appreciated.

I was able to solve this issue, and although I've run into another issue it's not related to the contents of this question so I'll post it separately.
Regarding my edit, I found that the difference between the error messages came down to how I was sending the transaction. At first, I tried sending it with Phantom's .signAndSendTransaction() method, which yielded the second error message (listed under my edit). Then I tried signing & sending the transaction manually, like so:
const signed = await provider.request({
method: 'signTransaction',
params: {
message: bs58.encode(transaction.serializeMessage()),
},
});
const signature = bs58.decode(signed.signature);
transaction.addSignature(provider.publicKey, signature);
await connection.sendRawTransaction(transaction.serialize())
Which yielded the more verbose error included in my original post. That error message did turn out to be helpful once I realized what to look for -- the sending account's public key was missing from the keys field on the TransactionInstruction on the Transaction. I added it in my fork of the #solana/solidity library and the error went away.
In short, the way I was able to debug this was by
Using provider.request({ method: 'signTransaction' }) and connection.sendRawTransaction(transaction) rather than Phantom's provider.signAndSendTransaction() method for a more verbose error message
Logging the transaction object and inspecting the instructions closely
I hope this helps someone else in the future.

Related

A resource failed to call close

I'm getting the android logcat message "A resource failed to call close". I've tracked it down to where that message gets generated. Here's the code:
Properties defaultProperties = new Properties();
URL propURL = Util.class.getClassLoader().getResource(DEFAULT_PROPERTIES_FILE);
if (propURL != null)
{
InputStream is = null;
try
{
// Load properties from URL.
is = propURL.openConnection().getInputStream();
defaultProperties.load(is);
is.close();
}
catch (Exception ex)
{
The message is generated on the call to "defaultProperties.load(is)".
I put a breakpoint on that line, and when I step over that line, the warning message is generated. I'm not the author of the code but that line gets executed at least two times and its the second time when that line gets called when the warning gets generated. I just don't see how under any circumstances that a resource failed to close would be generated on that line. I'm at a lost to explain how or why that error message would be generated there. Any ideas?
After thinking about this, I've come to the conclusion that the problem doesn't have anything to do with the line "defaultProperties.load(is)" causing the warning. Although the message is always generated the second time that line is called, my current thought is that the problem is happening elsewhere but when this line gets called it's probably yielding to some other VM related thread time to process, and that process is detecting that some resource failed to close. I'm concluding that the problem is related to something altogether different and calling that line is the time when the problem surfaces, but it's not what's causing the problem.

WSO2 API Manager returning RunTime Error

I have an API in WSO2. When I try to test it in the store with valid parameters via GET, it returns the following error message:
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>101504</am:code>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description>Send timeout</am:description>
</am:fault>
I have already searched and tried a lot, but with no success, always returning the same error. Don't know if helps, but the api that I try to access is a PHP file.
Any ideas?
EDIT:
I have identical apis to this one, changing only the response, that are working properly. Even if I erase the php file that the API is pointing, the error keep coming.
EDIT:
I changed the code in Management Console, in Metadata>List>APIs:
{"production_endpoints":
{"url":"http://site/myapi.php","config":
{"format":"leave-as-is","optimize":"leave-as-
is","actionSelect":"fault","actionDuration":30000}},
"sandbox_endpoints":
{"url":"http://site/myapi.php","config":
{"format":"leave-as-is","optimize":"leave-as-
is","actionSelect":"fault","actionDuration":30000}},
"implementation_status":"managed","endpoint_type":"http"}
to this:
{"production_endpoints":
{"url":"http://10.20.40.189/ConsultaAutorizacaoCadPos.php","config":null},
"sandbox_endpoints":{"url":"http://10.20.40.189/ConsultaAutorizacaoCadPos.php","config":null},
"implementation_status":"managed","endpoint_type":"http"}
And this error message vanishes. But this new one appears:
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>303001</am:code>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description>Currently , Address endpoint : [ Name : admin--myapi_APIproductionEndpoint_0 ] [ State : SUSPENDED ]</am:description>
EDIT: this error message is appearing just sometimes. Most of the time the request takes long time to run and then returns nothing( no content )
Any ideas how to solve it?

SQS Extended - The input receipt handle is invalid

We wrappered an existing queue with the extended functionality. Messages are able to be put on the queue, and we see the message body being stored on S3.
However, when the message is consumed we get the following stack trace:
com.amazonaws.services.sqs.model.ReceiptHandleIsInvalidException: The input receipt handle is invalid. (Service: AmazonSQS; Status Code: 404; Error Code: ReceiptHandleIsInvalid; Request ID: ba9421e9-a9d2-56ba-8e17-70ff7190f05a)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1182)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:770)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:489)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2419)
at com.amazonaws.services.sqs.AmazonSQSClient.changeMessageVisibility(AmazonSQSClient.java:485)
at com.amazonaws.services.sqs.AmazonSQSClient.changeMessageVisibility(AmazonSQSClient.java:1692)
at com.amazon.sqs.javamessaging.AmazonSQSExtendedClientBase.changeMessageVisibility(AmazonSQSExtendedClientBase.java:1376)
Which happens when we attempt to change the visibility. Is that not supported?
sqsExtended.changeMessageVisibility(queueUrl, message.getReceiptHandle(), visibilityTimeout);
The answer is that this hasn't been implemented, nor does it try to warn you by throwing an exception when calling the method. There doesn't seem to be a reason to not be implemented, looking at the source code, it would be straightforward.
For our case, we are okay with relaying on the queue default value for this parameter and not setting each individually.

How to make Xlib print error message, but not exit?

"The action of the default handlers is to print an explanatory message and exit." (link)
Example of such message:
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 12 (X_ConfigureWindow)
Resource id in failed request: 0xc0007a
Serial number of failed request: 140
Current serial number in output stream: 141
If I set (XSetErrorHandler) my own "ignore everything" error handler, the "explanatory messages" disappear.
How to make Xlib ignore errors, but still print error messages?
If you actually want those error messages you pretty much have two options:
Pull _XPrintDefaultError out of XlibInt.c along with some private headers (with all the caveats of using library-private definitions).
Redefine exit() not to actually exit when _XDefautError calls it.
Neither is especially pretty and both may break and reduce your portability, but they do work.
You have to format your own message. The contents of the message is the contents of the XErrorEvent struct:
http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html

Suppressing NServicebus Transaction to write errors to database

I'm using NServiceBus to handle some calculation messages. I have a new requirement to handle calculation errors by writing them the same database. I'm using NHibernate as my DAL which auto enlists to the NServiceBus transaction and provides rollback in case of exceptions, which is working really well. However if I write this particular error to the database, it is also rolled back which is a problem.
I knew this would be a problem, but I thought I could just wrap the call in a new transaction with the TransactionScopeOption = Suppress. However the error data is still rolled back. I believe that's because it was using the existing session with has already enlisted in the NServiceBus transaction.
Next I tried opening a new session from the existing SessionFactory within the suppression transaction scope. However the first call to the database to retrieve or save data using this new session blocks and then times out.
InnerException: System.Data.SqlClient.SqlException
Message=Timeout expired. The timeout period elapsed prior to completion of the >operation or the server is not responding.
Finally I tried creating a new SessionFactory using it to open a new session within the suppression transaction scope. However again it blocks and times out.
I feel like I'm missing something obvious here, and would greatly appreciate any suggestions on this probably common task.
As Adam suggests in the comments, in most cases it is preferred to let the entire message fail processing, giving the built-in Retry mechanism a chance to get it right, and eventually going to the error queue. Then another process can monitor the error queue and do any required notification, including logging to a database.
However, there are some use cases where the entire message is not a failure, i.e. on the whole, it "succeeds" (whatever the business-dependent definition of that is) but there is some small part that is in error. For example, a financial calculation in which the processing "succeeds" but some human element of the data is "in error". In this case I would suggest catching that exception and sending a new message which, when processed by another endpoint, will log the information to your database.
I could see another case where you want the entire message to fail, but you want the fact that it was attempted noted somehow. This may be closest to what you are describing. In this case, create a new TransactionScope with TransactionScopeOption = Suppress, and then (again) send a new message inside that scope. That message will be sent whether or not your full message transaction rolls back.
You are correct that your transaction is rolling back because the NHibernate session is opened while the transaction is in force. Trying to open a new session inside the suppressed transaction can cause a problem with locking. That's why, most of the time, sending a new message asynchronously is part of the solution in these cases, but how you do it is dependent upon your specific business requirements.
I know I'm late to the party, but as an alternative suggestion, you coudl simply raise another separate log message, which NSB handles independently, for example:
public void Handle(DebitAccountMessage message)
{
var account = this.dbcontext.GetById(message.Id);
if (account.Balance <= 0)
{
// log request - new handler
this.Bus.Send(new DebitAccountLogMessage
{
originalMessage = message,
account = account,
timeStamp = DateTime.UtcNow
});
// throw error - NSB will handle
throw new DebitException("Not enough funds");
}
}
public void Handle(DebitAccountLogMessage message)
{
var messageString = message.originalMessage.Dump();
var accountString = message.account.Dump(DumpOptions.SuppressSecurityTokens);
this.Logger.Log(message.UniqueId, string.Format("{0}, {1}", messageString, accountString);
}