Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transact_async failing on specific cases #228

Closed
ChaoticTempest opened this issue Nov 2, 2022 · 4 comments
Closed

transact_async failing on specific cases #228

ChaoticTempest opened this issue Nov 2, 2022 · 4 comments
Assignees

Comments

@ChaoticTempest
Copy link
Member

@austinabell noticed an issue with transact_async stalling for a while when calling specifically into here.

When replacing that call with a transact() instead, it completes fine without running into any issues. At first look, this seems to be a potential bug in nearcore potentially giving back an incorrect hash for the TransactionStatus to use and check the status of on the network.

@austinabell
Copy link
Contributor

More context, the async polling only indefinitely returns pending on transactions using a function call access key (from what I've noticed).

Guesses are that it could have something to do with the nonce caching (as it only caches based on account id when there could be any key associated with a contract with diff nonce) or something to do with the fact that I was manually generating an account using the contract that owns the access key and the public key generated.

For the latter, it could be beneficial to have a more ergonomic API for that, as using access keys is definitely a bit awkward.

@ChaoticTempest
Copy link
Member Author

I thought it was from the cached nonces using account-id as well, but it would run into the same issue with transact() where transact doesn't work but it does. Changed the code to use public keys to be sure, but that doesn't fix the issue either. Also, for manually generating the account, account.view_access_keys shows that it indeed is a registered access key for that account. Not sure where its add that generated key, but maybe through one of the calls?

@austinabell
Copy link
Contributor

austinabell commented Nov 3, 2022

I thought it was from the cached nonces using account-id as well, but it would run into the same issue with transact() where transact doesn't work but it does. Changed the code to use public keys to be sure, but that doesn't fix the issue either.

Well, wouldn't this mean that the transactions are unnecessarily increasing the nonce? As in, if multiple keys are sending txs on the same account alternating, they will share a nonce cache.

This might be sufficient enough to rule it out of this specific issue, though.

Also, for manually generating the account, account.view_access_keys shows that it indeed is a registered access key for that account. Not sure where its add that generated key, but maybe through one of the calls?

Yeah, it's done within the contract that's being called in the example given.

Digging in a bit through some related testing it seems as if the transaction is never processed, even though status is returning as Ok. Tested through testnet as well https://explorer.testnet.near.org/accounts/dev-20221103011932-96505814352369

code for reference:

#[tokio::test]
    async fn test_bug() -> anyhow::Result<()> {
        let initial_balance = U128(10000);
        let approve_amount = U128(50);
        let approve_transfer_amount = U128(20);
        let worker = workspaces::testnet().await?;
        let contract = init(&worker, initial_balance).await?;
        println!("CONTRACT: {}", contract.id());

        let access_pk = SecretKey::from_random(KeyType::ED25519);
        let access_pk_json = serde_json::json!({"type": "Key", "value": access_pk.public_key()});
        println!(
            "pk: {}",
            serde_json::to_string(&access_pk.public_key()).unwrap()
        );

        let f2 = contract
            .call("ft_approve")
            .args_json((&access_pk_json, "0", approve_amount))
            .deposit(parse_near!("1 N"))
            .transact()
            .await?;
        assert!(f2.is_success());

        let access_signer = Account::from_secret_key(contract.id().clone(), access_pk, &worker);

        println!("pre broadcast");
        let async_tx = access_signer
            .call(contract.id(), "ft_transfer_from_key")
            .args_json((
                contract.id(),
                "test.testnet",
                approve_transfer_amount,
                "test memo",
            ))
            .transact_async()
            .await?;
        let _ = async_tx.status().await?;

        println!("hash: {}", async_tx.hash());
        println!("sender: {}", async_tx.sender_id());
        panic!("HERE");
        async_tx.await?.into_result()?;

        Ok(())
    }

@ChaoticTempest
Copy link
Member Author

This issue should be resolved now. After testing it a lot more, it's pretty consistently working now. It should've been resolved mainly by the fix for nonce caching. Let me know if you're running into it again, but I ran that snippet you posted and it resolves correctly on testnet as well now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants