Ethereum – Why Am I Getting “Error: Unknown Account” When Trying to Send ETH Using eth.sendTransaction?

go-ethereumjson-rpc

I have an ETH testnet set up using this docker-compose.yml file.

When I try to send 1 wei from the "buffer" account 0x411167FeFecAD12Da17F9063143706C39528aa28 to the test account 0x6d179e1d7715b6b2eedf82b16b90db3fd4cd64a3 using the following commands, I get the error ùnknown account`:

Screenshot 1

Buffer account

The buffer account is the account in which all mined ETH ends up. It is specified in the genesis.json file:

Screenshot 2

The buffer account exists on the testnet and when I run

curl -X POST http://localhost:8178 \
    -H "Content-Type: application/json" \
   --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x411167FeFecAD12Da17F9063143706C39528aa28","latest"], "id":1}'

I get the expected result: The buffer account has 0x200000000000000000000000000000000000000000000000000000000000000 ETH:

{"jsonrpc":"2.0","id":1,"result":"0x200000000000000000000000000000000000000000000000000000000000000"}

Test account

I created the test account myself using

geth account new --password address1pw.txt

It appears in the output of

geth account list

Screenshot 3

Question

What do I need to do in order to transfer 1 wei from the buffer account to the test account?

Update 1

Changing the request to

> eth.sendTransaction({from: '0c56352F05De44C9b5BA8bcF9BDEc7e654993339', to: '0x6D179e1d7715b6b2eeDF82b16B90db3fd4cd64A3', value: 1});

results in

Error: gas required exceeds allowance (8000000) or always failing transaction
    at web3.js:6347:37(47)
    at web3.js:5081:62(37)
    at <eval>:1:20(10)

0c56352F05De44C9b5BA8bcF9BDEc7e654993339 is ETH_ADDRESS specified in the docker-compose.yml file.

Update 2

Changing the request to

eth.sendTransaction({from: '0c56352F05De44C9b5BA8bcF9BDEc7e654993339', to: '0x6D179e1d7715b6b2eeDF82b16B90db3fd4cd64A3', gas:8000000 , value: 1});

results in

Error: insufficient funds for gas * price + value
    at web3.js:6347:37(47)
    at web3.js:5081:62(37)
    at <eval>:1:20(12)

Update 3

In the genesis.json file the account from which I try to send ETH appears in the alloc section:

    "alloc": {
        "411167FeFecAD12Da17F9063143706C39528aa28": {
            "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
        }
    },

Update 4:

Here is how the ETH is being initialized: The file entrypoint.sh is run where I find this:

echo $ETH_PASSWORD > /tmp/eth_pass
echo $ETH_PRIVATE_KEY > /tmp/eth_private_key

geth --datadir /data init ./.genesis.json
geth --datadir /data account import --password /tmp/eth_pass /tmp/eth_private_key || true

ETH_PASSWORD and ETH_PRIVATE_KEY come from the vriables in docker-compose.yml file:

  geth:
    image: ulamlabs/geth-poa-testnet:latest
    environment:
      - ETH_PASSWORD=QfdxTYxkwASj
      - ETH_PRIVATE_KEY=0d0b4c455973c883bb0fa584f0078178aa90c571a8f1d40f28d2339f4e757dde
      - ETH_ADDRESS=0c56352F05De44C9b5BA8bcF9BDEc7e654993339
    ports:
      - 8178:8178
      - 8546:8546
    volumes:
      - ./genesis.json:/app/genesis.json

It seems that the buffer account (411167FeFecAD12Da17F9063143706C39528aa28) is not created when the container is created.

Update 5:

I ran following commands in the geth shell:

echo carsdrivefasterbecausetheyhavebrakes > buffer-pw.txt
echo 766df34218d5a715018d54789d6383798a1885088d525670802ed8cf152db5b4 > buffer-private-key.txt
geth account import --datadir /data  --password buffer-pw.txt buffer-private-key.txt

echo a-turkey-is-a-chicken-designed-by-a-committee > exchange-pw.txt
echo b07aedf303f832664eb7a5295be737776cb1ad17a277ec287b3b3c7bac154e5e > exchange-private-key.txt
geth account import --datadir /data  --password exchange-pw.txt exchange-private-key.txt

When I check the balance of the buffer account using

geth attach http://localhost:8178
eth.getBalance("0x411167FeFecAD12Da17F9063143706C39528aa28");

I get this output:

9.04625697166532776746648320380374280103671755200316906558262375061821325312e+74

Then I tried to send 1 wei from the buffer account to the exchange account again:

eth.sendTransaction({from: '0x411167FeFecAD12Da17F9063143706C39528aa28', to: '0x190FD61ED8fE0067f0f09EA992C1BF96209bab66', value: 1});

I get the error

Error: authentication needed: password or unlock
    at web3.js:6347:37(47)
    at web3.js:5081:62(37)
    at <eval>:1:20(10)

I tried to unlock the account using the following commands, without success:

  • eth.unlockAccount('0x411167FeFecAD12Da17F9063143706C39528aa28', 'carsdrivefasterbecausetheyhavebrakes', 600).then(console.log('Account unlocked!'));
  • web3.personal.unlockAccount('0x411167FeFecAD12Da17F9063143706C39528aa28', 'carsdrivefasterbecausetheyhavebrakes', 600).then(console.log('Account unlocked!'));

Error messages when trying to unlock the account

Update 6:

Modified the entrypoint.sh of the Docker image with geth so that test accounts are included and the personal API is enabled.

Then, modified docker-compose.yml file to use that changed geth image.

Now unlocking the buffer account and sending money from it seems to work.

Best Answer

The error was caused by accounts missing in the geth testnet. If an account appears in genesis.json it does not mean that the respective account will automatically be created.

Therefore the first step to fixing the problem is to modify the existing entrypoin.sh so that the accounts are actually created:

#
# Create buffer account (start)
# 
echo carsdrivefasterbecausetheyhavebrakes > /tmp/buffer_pass
echo 766df34218d5a715018d54789d6383798a1885088d525670802ed8cf152db5b4 > /tmp/buffer_private_key
geth account import --datadir /data --password /tmp/buffer_pass /tmp/buffer_private_key
#
# Create buffer account (end)
#

#
# Create exchange account (start)
# 
echo a-turkey-is-a-chicken-designed-by-a-committee > /tmp/exchange_pass
echo b07aedf303f832664eb7a5295be737776cb1ad17a277ec287b3b3c7bac154e5e > /tmp/exchange_private_key
geth account import --datadir /data  --password /tmp/exchange_pass  /tmp/exchange_private_key
#
# Create exchange account (end)
# 

Also, in order for the eth.unlockAccount call to work, we need to enable the personal API when starting geth by adding --rpcapi="db,eth,net,web3,personal" to the original call.

Before

exec geth --config .config.toml --allow-insecure-unlock --nousb --verbosity $ETH_VERBOSITY --gcmode=archive --mine --miner.threads 1 --unlock $ETH_ADDRESS --password /tmp/eth_pass

After

exec geth --config .config.toml --allow-insecure-unlock --nousb --verbosity $ETH_VERBOSITY --gcmode=archive --mine --miner.threads 1 --unlock $ETH_ADDRESS --password /tmp/eth_pass --rpcapi="db,eth,net,web3,personal"

The resulting entrypoint.sh looks like this:

#!/bin/sh
set -e

export ETH_VERBOSITY=${ETH_VERBOSITY:-1}
export ETH_CHAIN_ID=${ETH_CHAIN_ID:-5555}

replace_env() {
  for key in $(env | sed 's;=.*;;' | grep ETH_); do
    val=$(eval echo \$$key)  # sh doesn't support indirect substitution
    sed -i "s|\$$key|$val|g" $1
  done
}

# replace $ETH_... strings with env variable values without overwriting genesis.json
cp genesis.json .genesis.json
cp config.toml .config.toml
replace_env .genesis.json
replace_env .config.toml

echo $ETH_PASSWORD > /tmp/eth_pass
echo $ETH_PRIVATE_KEY > /tmp/eth_private_key

geth --datadir /data init ./.genesis.json
geth --datadir /data account import --password /tmp/eth_pass /tmp/eth_private_key || true

#
# Create buffer account (start)
# 
echo carsdrivefasterbecausetheyhavebrakes > /tmp/buffer_pass
echo 766df34218d5a715018d54789d6383798a1885088d525670802ed8cf152db5b4 > /tmp/buffer_private_key
geth account import --datadir /data --password /tmp/buffer_pass /tmp/buffer_private_key
#
# Create buffer account (end)
#

#
# Create exchange account (start)
# 
echo a-turkey-is-a-chicken-designed-by-a-committee > /tmp/exchange_pass
echo b07aedf303f832664eb7a5295be737776cb1ad17a277ec287b3b3c7bac154e5e > /tmp/exchange_private_key
geth account import --datadir /data  --password /tmp/exchange_pass  /tmp/exchange_private_key
#
# Create exchange account (end)
# 

if [[ $# -eq 0 ]] ; then
  exec geth --config .config.toml --allow-insecure-unlock --nousb --verbosity $ETH_VERBOSITY --gcmode=archive --mine --miner.threads 1 --unlock $ETH_ADDRESS --password /tmp/eth_pass --rpcapi="db,eth,net,web3,personal"
else
  exec "$@"
fi

Finally, we need to replace the old docker image in docker-compose.yml with the new one, i. e. change the line from

    image: ulamlabs/geth-poa-testnet:latest

to

    image: mentiflectax/geth-poa-testnet:v1

Final version of docker-compose.yml looks like this:

version: '3'

services:
#
# BTC testnet setup (start)
#
  node:
    image: ulamlabs/bitcoind-custom-regtest:latest
  electrumx:
    image: lukechilds/electrumx:latest
    links:
      - node
    ports:
      - "51001:50001"
      - "51002:50002"
    environment:
      - NET=regtest
      - COIN=BitcoinSegwit
      - DAEMON_URL=http://test:test@node:19001
  explorer:
    image: ulamlabs/btc-rpc-explorer:latest
    links:
      - node
      - electrumx
    ports:
      - "3002:3002"
    environment:
      - BTCEXP_HOST=0.0.0.0
      - BTCEXP_BITCOIND_URI=http://test:test@node:19001
      - BTCEXP_ELECTRUMX_SERVERS=tls://electrumx:50002
      - BTCEXP_ADDRESS_API=electrumx
#
# BTC testnet setup (end)
#


#
# ETH testnet setup (start)
#
  geth:
    image: mentiflectax/geth-poa-testnet:v1
    environment:
      - ETH_PASSWORD=QfdxTYxkwASj
      - ETH_PRIVATE_KEY=0d0b4c455973c883bb0fa584f0078178aa90c571a8f1d40f28d2339f4e757dde
      - ETH_ADDRESS=0c56352F05De44C9b5BA8bcF9BDEc7e654993339
    ports:
      - 8178:8178
      - 8546:8546
    volumes:
      - ./genesis.json:/app/genesis.json

  postgres:
    image: postgres:12
    command: postgres -c 'max_connections=500'
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust

  blockscout:
    image: ulamlabs/blockscout:latest
    links:
      - geth
      - postgres
    ports:
      - 4000:4000
    environment:
      - DATABASE_URL=postgresql://postgres:@postgres:5432/postgres?ssl=false
      - ETHEREUM_JSONRPC_VARIANT=geth
      - ETHEREUM_JSONRPC_HTTP_URL=http://geth:8178
      - ETHEREUM_JSONRPC_WS_URL=ws://geth:8546
      - MIX_ENV=prod
      - BLOCKSCOUT_HOST=localhost
      - COIN=eth
      - NETWORK=POA
      - SUBNETWORK=Local Testnet

#
# ETH testnet setup (end)
#

It refers to genesis.json with the following content:

{
    "config": {
        "chainId": 5555,
        "clique": {
            "period": 60,
            "epoch": 30000
        },
        "homesteadBlock": 0,
        "eip150Block": 0,
        "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "eip155Block": 0,
        "eip158Block": 0,
        "byzantiumBlock": 0,
        "constantinopleBlock": 0,
        "petersburgBlock": 0,
        "istanbulBlock": 0,
        "muirGlacierBlock": 0
    },
    "extraData": "0x00000000000000000000000000000000000000000000000000000000000000000c56352F05De44C9b5BA8bcF9BDEc7e6549933390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "alloc": {
        "411167FeFecAD12Da17F9063143706C39528aa28": {
            "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
        }
    },
    "nonce": "0x0",
    "timestamp": "0x5eaa7b09",
    "gasLimit": "0x47b760",
    "difficulty": "0x1",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0x0000000000000000000000000000000000000000",
    "number": "0x0",
    "gasUsed": "0x0",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

Then, it is possible to start BTC and ETH testnets by running docker-compose up -d in the same directory as the docker-compose.yml file above.

Related Topic