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

CLI transfer does not support offline-signed transactions. #21210

Closed
j-h-a opened this issue Nov 8, 2021 · 3 comments
Closed

CLI transfer does not support offline-signed transactions. #21210

j-h-a opened this issue Nov 8, 2021 · 3 comments

Comments

@j-h-a
Copy link

j-h-a commented Nov 8, 2021

Problem

When trying to submit an offline-signed transaction with the CLI, the transfer command on the online machine tries to use a local id instead of the --from or --signer passed in.

How to reproduce

This is the process described in the documentation (which could also use an update):

  1. ONLINE: Get a recent blockhash
  2. USB/OTHER: Send it to an offline / airgapped machine
  3. OFFLINE: Create and sign a transfer transaction from SENDER
  4. USB/OTHER: Send the signature back to the online machine
  5. ONLINE: Try to submit the transfer to the network.

However to make it easier to reproduce, we can use devnet doing it all from an online machine, but not give the "online" steps access to any keys.

  • First remove/backup your default id.json file and switch to devnet
  • Create a temporary address for the sender with keyfile called <sender-pubkey>.json to use in step 3, simulating the key which is present on the offline machine.
  • Fund the sender: solana airdrop 1 sender-pubkey
  • Check and run the script below, replacing the SENDER input with your own.
# Inputs
SENDER=HiQmVo9ABRuejfZitGdJfKYZ3fJwiRwUjykkHdZdpNfT
RECIPIENT=1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBurn
AMOUNT=0.01

echo Sender: $SENDER
echo Recipient: $RECIPIENT
echo Amount: $AMOUNT

# 1. Get a recent blockhash (there must be a better way than this!)
BLOCKHASH=$(solana block $(solana slot) | grep Recent | tail -n 1 | awk '{print $3}')

# 2. BLOCKHASH would be copied to a file on USB or otherwise transferred here, then
#    used on the offline machine, we will just reuse it for this demonstration

# 3. Create a signed `transfer` instruction from the SENDER
SIGNER=$(solana transfer --sign-only --blockhash $BLOCKHASH $RECIPIENT $AMOUNT -k ${SENDER}.json | tail -n 2 | head -n 1 | awk '{print $1}')

# 4. The output in SIGNER would now be transferred back on USB or other.
#    We can just reuse it here for demonstration.

# 5. Submit the signed `transfer` transaction (this is the bit that doesn't work)
solana transfer --from $SENDER $RECIPIENT $AMOUNT --allow-unfunded-recipient --blockhash $BLOCKHASH --signer $SIGNER

echo Signature: $SIGNER

The output is as follows:

Sender: HiQmVo9ABRuejfZitGdJfKYZ3fJwiRwUjykkHdZdpNfT
Recipient: 1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBurn
Amount: 0.01
Error: Dynamic program error: No default signer found, run "solana-keygen new -o /home/username/.config/solana/id.json" to create a new one
Signature: HiQmVo9ABRuejfZitGdJfKYZ3fJwiRwUjykkHdZdpNfT=2nuC4Z6JH7Z33LJfBDaAdZC6krETb2LAZpzL5h3LfM6QXQZhKnFhZvxeLSPVW8zka3sabnVtBp5T3z4vJX2EZy4A

If a valid local id is present, the transfer in step 5 attempts to use that - I'm not sure what happens if this is a real funded account on mainnet, so don't recommend trying it. If the local id is an unfunded account it does try to use it and complains that there are no funds.

Proposed Solution

There are a number of possibilities:

  1. transfer should use the signature that was passed in to identify the from-address, (or the from argument if specified), and not require a local id.
  2. Offline signed transactions shouldn't really need to be replicated on the online machine that submits them. It could spit out a transaction body that's already signed and a new submit-transaction command or similar could be used to send it to the network. This would be ideal as it would remove the need for a more complex process, replicating the transaction commands on the online machine.
@CriesofCarrots
Copy link
Contributor

I believe your issue is due to the fact that there is no --fee-payer specified for step #5, so the cli is attempting to use the default signer for that fee and signature. I believe if you add --fee-payer $SENDER, you will find the transaction submits properly, with no check for default signer.

@j-h-a
Copy link
Author

j-h-a commented Nov 8, 2021

Amazing, thanks! Yes this example now works. The documentation is quite misleading, and omits crucial information about who the fee payer is assumed to be (intuitively it would default to the sender) I'll close this ticket and create a new one re. the docs.

@j-h-a j-h-a closed this as completed Nov 8, 2021
@github-actions
Copy link
Contributor

This issue has been automatically locked since there has not been any activity in past 7 days after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants