geth(private)で手数料を無料にする

# 概要
クライアント側は、1 Gas 当たり 何 wei なのかをトランザクションの Gas Price で指定できる。Gas Price を 0 とすることで、実質手数料を無料としたい。一方、ノード(geth)側では、どのトランザクションをマイニング対象とするかを Gas Price の最低値を指定することで選んでいるわけだが、こちらも 0 にする。（手数料を無料にすることの良し悪しはさておき）

# 環境
- geth 1.8.20
- web3.js 1.0.0-beta

# gethのオプション
| オプション       |       説明 |
|:-----------------|:------------------|
| --gasprice &lt;value&gt; | トランザクションのマイニングに必要な最低限のガス代を指定します。 |

# 手数料無料で1ether送金
Gethコンソールにて、accounts[1]からaccounts[2]へ、Gas Price 0 で 1ether 送金してみる。

```
$ geth --gasprice 0 --networkid "15" --nodiscover --datadir "~/data" console 2>> ~/data/geth_err.log
> miner.start()
> eth.getBalance(eth.accounts[1])
3000000000000000000
> eth.getBalance(eth.accounts[2])
0

> personal.unlockAccount(eth.accounts[1], "password1", 60)
true
> web3.eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[2], gasPrice: 0, value: web3.toWei(1, 'ether')})
"0x2d197255813eb4b48e3015aaaa1f2aefc8ba7dc4abc6879264a52eaa56d2ff50"
> eth.getBalance(eth.accounts[1])
2000000000000000000 // 手数料分は引かれていない。
> eth.getBalance(eth.accounts[2])
1000000000000000000
> web3.eth.getTransaction('0x2d197255813eb4b48e3015aaaa1f2aefc8ba7dc4abc6879264a52eaa56d2ff50')
{
  blockHash: "0xdc63a43b6bc5b4bc683184aa4eafdc264fedce2785e3c0849f103a5675df4f64",
  blockNumber: 27,
  from: "0x27b3eb0b4dab1e3ff597977516bf96add644a6bb",
  gas: 90000,
  gasPrice: 0,
  hash: "0x2d197255813eb4b48e3015aaaa1f2aefc8ba7dc4abc6879264a52eaa56d2ff50",
  input: "0x",
  nonce: 0,
  r: "0x125cd0bceb7ab2b62756f7090b7a380aee537743b016f30ce76468ad1151c3f7",
  s: "0x338b94e9f5622046ccd164ee4a9a737ee15510b04d3f6130696ddfd25b90f70a",
  to: "0x91c69b59c308fd40f87caf4b0667267701e91549",
  transactionIndex: 0,
  v: "0x1c",
  value: 1000000000000000000
}

```

eth.accounts[1] は送金分のみ減っており、手数料分は引かれていない。トランザクション "0x2d197255813eb4b48e3015aaaa1f2aefc8ba7dc4abc6879264a52eaa56d2ff50" も確認してみると、手数料 = gas * gasPrice = 90000 * 0 = 0 と計算できる。


# 手数料無料でweb3.jsでスマートコントラクトを呼び出す
呼び出す前に gethコンソールで 残高の確認。

```
$ geth --rpc --rpcapi "db,eth,net,personal,web3" --gasprice 0 --networkid "15" --nodiscover --datadir "~/data" console 2>> ~/data/geth_err.log
> eth.getBalance(eth.accounts[2])
1000000000000000000
```

スマートコントラクト HelloWorld を gasprice 0 で呼び出す。web3.jsで実装。

```HelloWorld_client01.js
web3.eth.getAccounts().then(function (accounts) {
  acc2 = accounts[2];
  return web3.eth.personal.unlockAccount(acc2, "password2", 60);
}).then(function (value) {
  return helloWorld.methods.setMessage("hello").send({from: acc2, gasPrice: 0});
}).then(function (value) {
  console.log('transactionHash', value.transactionHash);
});
```

上記実装の実行。

```
$ node HelloWorld_client01.js
hello_address 0x777f0a60bFA595B253dad49152d62c97DD568DCE
transactionHash 0x379fcb2e8eb8556716a01c0cb483234672f8f10e9f2504ed8b0bc91bc6a53bc3
```

gethコンソールで残高を確認。

```
> eth.getBalance(eth.accounts[2])
1000000000000000000 // 残高は変わっていない。
> web3.eth.getTransaction('0x379fcb2e8eb8556716a01c0cb483234672f8f10e9f2504ed8b0bc91bc6a53bc3')
{
  blockHash: "0x91276b3b33475278effc51dc1c620d0bcb2d0ac10e4eec658df98a157226e455",
  blockNumber: 1455,
  from: "0x91c69b59c308fd40f87caf4b0667267701e91549",
  gas: 90000,
  gasPrice: 0,
  hash: "0x379fcb2e8eb8556716a01c0cb483234672f8f10e9f2504ed8b0bc91bc6a53bc3",
  input: "0x368b87720000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000",
  nonce: 2,
  r: "0x198c3d732cd6f7a4fa7b63a8313a11f421f6a9894973d96433b53b20913b1ddf",
  s: "0x502f7eed10513e3bd3fc0a575dcd0bc35f73c55baa79824f25506abe461eb64e",
  to: "0x777f0a60bfa595b253dad49152d62c97dd568dce",
  transactionIndex: 0,
  v: "0x1c",
  value: 0
}
```

残高は変わっておらず、手数料はかかっていない。トランザクションも確認してみると、手数料 = gas * gasPrice = 90000 * 0 = 0 と計算できる。

# 参考

- [web3.js - web3.eth.Contract](https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html)
- [stackoverflow - How to make sure transactions take 0 fee in a private Ethereum blockchain?](https://stackoverflow.com/questions/49318479/how-to-make-sure-transactions-take-0-fee-in-a-private-ethereum-blockchain)