Create Account On Android
import geth dependency to Android Studio
apply plugin: 'com.android.application'
android {
...
}
dependencies {
...
compile 'org.ethereum:geth:1.7.0'
}
create account
I can use KeyStore
of geth library to create account. I have to give newAccount()
a password, then it will create the private key, and using my password to encrypt the private key with AES-128 to the key store file. That key store file includes JSON content, it has account address and encrypted private key.
- MainActivity.java
import org.ethereum.geth.Account;
import org.ethereum.geth.Geth;
import org.ethereum.geth.KeyStore;
public class MainActivity extends AppCompatActivity {
private KeyStore keyStore;
private Account account;
...
private void createAccountDemo() throws Exception {
createKeyStore(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/ETH/privatechain/keystore").getPath());
account = createAccount("a1234567");
Log.d("main", account.getURL());
Log.d("main", "account address is " + account.getAddress().getHex());
}
private void createKeyStore(String keyStoreFolderPath) {
keyStore = new KeyStore(keyStoreFolderPath, Geth.LightScryptN, Geth.LightScryptP);
}
private Account createAccount(String password) throws Exception {
return keyStore.newAccount(password);
}
}
- LogCat
keystore:///storage/emulated/0/Download/ETH/privatechain/keystore/UTC--2017-10-02T07-02-09.341966351Z--eda1370b372a909aaec04e56ac395f1faa5b585d
account address is 0xEDA1370B372a909AAEC04E56ac395F1FAa5B585d
- key store file
{
"address":"eda1370b372a909aaec04e56ac395f1faa5b585d",
"crypto":{
"cipher":"aes-128-ctr",
"ciphertext":"a05359e5c053798ff0c6318f3c93d5f155b6a906767457a29c508b7bae4d9d96",
"cipherparams":{
"iv":"43856647487d92a5edc791fd495693af"
},
"kdf":"scrypt",
"kdfparams":{
"dklen":32,
"n":4096,
"p":6,
"r":8,
"salt":"200ba5f2f7d8ee0316f830f315e5450d480cb59fa9ccec999fce32995b8ddeb2"
},
"mac":"11f9e7746e2f066a48334ca725fec102a8972e470701f122bbcb8fd1e11ba436"
},
"id":"5f1ec8a3-62ff-4d43-90af-63edd1c8aa29",
"version":3
}
Accounts on Android (Java) section of Mobile: Account management
start node on Android to sync with my private chain
copy static-nodes.json to device folder
${android storage}/ETH/prviatechain/GethDroid/static-nodes.json
[
"enode://540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b@192.168.200.207:30303?discport=30304"
]
kelsoson Jul 25commented on go-ethereum issue 3789, said that "the static-nodes.json must be under the
$filesDir/.ethereum/GethDroid/static-nodes.json
in order to get picked."
set the network id
private static final long PRIVATE_CHAIN_NETWORK_ID = 56821;
set the genesis block
Make the /Users/yen/Desktop/privateChain/privateChain.json
to be one line, so that I can avoid the newline character problem.
public class PrivateChain {
public static final String genesis = "{ \"config\": { \"chainId\": 56821, \"homesteadBlock\": 1, \"eip150Block\": 2, \"eip150Hash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\", \"eip155Block\": 3, \"eip158Block\": 3, \"clique\": { \"period\": 3, \"epoch\": 30000 } }, \"nonce\": \"0x0\", \"timestamp\": \"0x59cf588f\", \"extraData\": \"0x0000000000000000000000000000000000000000000000000000000000000000726794b16f6c5b0be0b78d7713a876ed3da8be1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"gasLimit\": \"0x47b760\", \"difficulty\": \"0x1\", \"mixHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\", \"coinbase\": \"0x0000000000000000000000000000000000000000\", \"alloc\": { \"c077f8420d5b6c125897d9c5e21293ff6f77855c\": { \"balance\": \"0x200000000000000000000000000000000000000000000000000000000000000\" } }, \"number\": \"0x0\", \"gasUsed\": \"0x0\", \"parentHash\": \"0x0000000000000000000000000000000000000000000000000000000000000000\" }";
}
- MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final long PRIVATE_CHAIN_NETWORK_ID = 56821;
...
private void startNode2CheckBalance() throws Exception {
createKeyStore(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + "ETH" + "/privatechain/keystore").getPath());
Accounts accounts = keyStore.getAccounts();
account = accounts.get(0);
final Context ctx = new Context();
NodeConfig nodeConfig = Geth.newNodeConfig();
nodeConfig.setEthereumNetworkID(PRIVATE_CHAIN_NETWORK_ID);
nodeConfig.setEthereumGenesis(PrivateChain.genesis);
nodeConfig.setEthereumDatabaseCache(512);
nodeConfig.setMaxPeers(10);
nodeConfig.setWhisperEnabled(true);
nodeConfig.setEthereumEnabled(true);
final Node node = Geth.newNode(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + "ETH" + "/privatechain").getPath(), nodeConfig);
try {
node.start();
NodeInfo info = node.getNodeInfo();
Log.d("main", "name is " + info.getName());
Log.d("main", "address is " + info.getListenerAddress());
Log.d("main", "protocols is " + info.getProtocols());
Log.d("main", "ID is " + info.getID());
Log.d("main", "ListenerPort is " + info.getListenerPort());
Log.d("main", "DiscoveryPort is " + info.getDiscoveryPort());
Log.d("main", "IP is " + info.getIP());
Log.d("main", "enode is " + info.getEnode());
final EthereumClient ec = node.getEthereumClient();
Log.d("main", "Latest block: " + ec.getBlockByNumber(ctx, -1).getNumber() + ", syncing");
NewHeadHandler handler = new NewHeadHandler() {
@Override
public void onError(String error) {
Log.d("main", "NewHeadHandler: " + error);
}
@Override
public void onNewHead(final Header header) {
try {
Log.d("main", "#" + header.getNumber() + ": " + header.getHash().getHex().substring(0, 10));
PeerInfo peerInfo = node.getPeersInfo().get(0);
Log.d("main", "peers amount " + node.getPeersInfo().size() + "; " + peerInfo.getName() + "; " + peerInfo.getID() + "; " + peerInfo.getRemoteAddress());
Log.d("main", "balance of android node " + account.getAddress().getHex() + " is " + ec.getBalanceAt(ctx, account.getAddress(), -1).getInt64());
Log.d("main", "balance of server node 0x726794b16f6c5b0be0b78d7713a876ed3da8be1a is " + ec.getBalanceAt(ctx, new Address("0x726794b16f6c5b0be0b78d7713a876ed3da8be1a"), -1).getInt64());
Log.d("main", "balance of miner2 node 0xc077f8420d5b6c125897d9c5e21293ff6f77855c is " + ec.getBalanceAt(ctx, new Address("0xc077f8420d5b6c125897d9c5e21293ff6f77855c"), -1).getInt64());
Log.d("main", "balance of light node 0x52ea0215068f436f837788686aa4b25de1a98f07 is " + ec.getBalanceAt(ctx, new Address("0x52ea0215068f436f837788686aa4b25de1a98f07"), -1).getInt64());
} catch (Exception e) {
e.printStackTrace();
}
}
};
ec.subscribeNewHead(ctx, handler, 16);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- LogCat
E/GoLog: INFO [10-02|07:50:17] Starting peer-to-peer node instance=GethDroid/v1.7.0-stable/android-386/go1.9
E/GoLog: INFO [10-02|07:50:17] Allocated cache and file handles database=/storage/emulated/0/Download/ETH/privatechain/GethDroid/lightchaindata cache=512 handles=16
E/GoLog: INFO [10-02|07:50:17] Writing custom genesis block
E/GoLog: INFO [10-02|07:50:17] Initialised chain configuration config="{ChainID: 56821 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: <nil> Engine: clique}"
E/GoLog: INFO [10-02|07:50:17] Loaded most recent local header number=0 hash=ffaa00…d07f18 td=1
E/GoLog: INFO [10-02|07:50:17] Starting P2P networking
E/GoLog: WARN [10-02|07:50:18] Light client mode is an experimental feature E/GoLog: INFO [10-02|07:50:18] RLPx listener up self="enode://b916a97604eb9119798646149f3075393a9fad22df0a3206ae0d4a13dd2645c165fc0cf7e54e4006a54e36e69b5517abfdeee9f2fe327e290f15b2e54c3abd25@[::]:60934?discport=0"
E/GoLog: INFO [10-02|07:50:18] started whisper v.5.0
D/main: name is GethDroid/v1.7.0-stable/android-386/go1.9
D/main: address is [::]:60934
D/main: protocols is [les shh]
D/main: ID is b916a97604eb9119798646149f3075393a9fad22df0a3206ae0d4a13dd2645c165fc0cf7e54e4006a54e36e69b5517abfdeee9f2fe327e290f15b2e54c3abd25
D/main: ListenerPort is 60934
D/main: DiscoveryPort is 0
D/main: IP is ::
D/main: enode is enode://b916a97604eb9119798646149f3075393a9fad22df0a3206ae0d4a13dd2645c165fc0cf7e54e4006a54e36e69b5517abfdeee9f2fe327e290f15b2e54c3abd25@[::]:60934?discport=0
D/main: Latest block: 0, syncing
- check peers on server node console
> net.peerCount
3
> admin.peers
[{
caps: ["les/1"],
id: "66bd5b4e4801c069bd01cc3760a18d3c8f72fb2f433a680f8d2f77ce18d5ad0af7327a668b7c855675be0996367e76fc0f2b0f6de977ffdeaa9756cc99824ed7",
name: "Geth/light/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:30303",
remoteAddress: "192.168.200.207:62107"
},
protocols: {
les: {
difficulty: 121,
head: "2b8e637d11798c28a88d5a3623f8ca92fd39987c15abd6bc0a65e2ef85bdd53d",
version: 1
}
}
}, {
caps: ["eth/62", "eth/63"],
id: "acf05a7cc42e6504ca63e57c7cb70e7c0ec05c45cb38fe4691c9b71ec125b003751fbe00f2a6c6a4868fa1b17c50552687b7ec06677f9a19cca00411994994ac",
name: "Geth/miner2/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1",
network: {
localAddress: "192.168.200.207:30303",
remoteAddress: "192.168.200.207:62102"
},
protocols: {
eth: {
difficulty: 121,
head: "0x2b8e637d11798c28a88d5a3623f8ca92fd39987c15abd6bc0a65e2ef85bdd53d",
version: 63
}
}
}, {
caps: ["les/1", "shh/5"],
id: "b916a97604eb9119798646149f3075393a9fad22df0a3206ae0d4a13dd2645c165fc0cf7e54e4006a54e36e69b5517abfdeee9f2fe327e290f15b2e54c3abd25",
name: "GethDroid/v1.7.0-stable/android-386/go1.9",
network: {
localAddress: "192.168.200.207:30303",
remoteAddress: "192.168.200.207:64348"
},
protocols: {
les: {
difficulty: 1,
head: "ffaa00ed88c5cdc8b510dc5fbf5676d7373e040563c7133c9556eb8d21d07f18",
version: 1
}
}
}]
When start mine on server and miner2 nodes, the android node will sync the header of blocks.
E/GoLog: INFO [10-02|07:51:44] Block synchronisation started
E/GoLog: INFO [10-02|07:51:44] Imported new block headers count=120 elapsed=199.023ms number=120 hash=0d6418…b49f0e ignored=0
D/main: #1: 0x467bdf1a
D/main: peers amount 1; Geth/server/v1.7.0-stable-6c6c7b2a/darwin-amd64/go1.7.1; 540e892d76e86b3221aed4858613d7a9b96a1199db4c00901803dfc4abb59e1be359bd33281b91abb126aeb048c79a0720f80a5688c07b3ee4e16fcd5f44a83b; 192.168.200.207:30303
D/main: balance of android node 0xEDA1370B372a909AAEC04E56ac395F1FAa5B585d is 0
D/main: balance of server node 0x726794b16f6c5b0be0b78d7713a876ed3da8be1a is 1000000000000000000
D/main: balance of miner2 node 0xc077f8420d5b6c125897d9c5e21293ff6f77855c is 8447878073709551616
D/main: balance of light node 0x52ea0215068f436f837788686aa4b25de1a98f07 is 8998866000000000000
D/main: #2: 0x4027082e
D/main: #3: 0xeb71adf2
...
D/main: #120: 0x0d641802
E/GoLog: INFO [10-02|07:51:50] Imported new block headers count=2 elapsed=2.908ms number=122 hash=d5a7fd…d8d2fd ignored=0