# Ice-node with Airdrop-pallet
> Source code: https://github.com/ibriz/ice-substrate/tree/airdrop-pallet
## Developing
### Gitpod ( Not actively developed )
https://github.com/ibriz/ice-substrate/tree/gitpod-setup
### Local machine ( Unix or WSL recommended )
- https://docs.substrate.io/v3/getting-started/installation/
- https://www.rust-lang.org/tools/install
- Install latest rust stable
- Install Rust nightly with wasm
Current dependency is compatiable with rust before`nightly-2022-01-20 1.60.0-nightly (5e57faa78 2022-01-19)` and stable `1.58.1`
```shell=
rustup toolchain update 1.58.1
rustup toolchain install nightly-2022-01-10
rustup target add wasm32-unknown-unknown --toolchain nightly-2022-01-10
rustup default 1.58.1
rustup component add rustfmt
```
- Compile in release mode
`cargo build --release`
- Verify the output executable
`file target/release/ice-node`
## Pre-launch setup
- Make sure that crucial rpc are restriected to public call
https://docs.substrate.io/v3/runtime/custom-rpcs/
## While launching
### About running offchain worker
Current implementation is best when offchain worker is ran within only one node per network. If ran on two node, both might process same entry ( currenlty there is no specification which node whould process which entry so ). When same entry is processed by two node but have to be writeen in onchain db by only one node. This implies that only one node processing is utilizes and computing resourse of other node got wasted.
* Enable offchain worker always ( for first node in network)
`./ice-node --offchain-worker Always`
* Disable offchain worker completly ( all other node that joins later )
`./ice-node --offchain-worker Never`
### Visiting Logs
Airdrop pallet may use any log level from `log::error!`( highest priority ) to `log::trace!` ( lowest priority ). It is however recommended to launch with log level `trace`
`RUST_LOG=runtime=trace ./ice-node <options>`
**Example while running local node**:
```shell=
RUST_LOG=runtime=trace cargo run --release -- --dev --tmp --offchain-worker Always
```
All the logs in Airdrop-pallet will be prefixed by string **"[Airdrop pallet] "**. So combined use of output piping and filtering will allow to see only logs of this pallet
## Post-launch setup
1) Insert an account in offchain keystore
Offchain needs an account from which to send signed transaction. And an account should be inserted for this purpose
In given rpc call,
- `ACCOUNT_ID`: Account to use while sending tx from offchain. This muct be same as Storage.OffchainAccount for the transaction to pass `ensure_` check in calls
- `SURI`: Recovery while creating this account
```shell=
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "author_insertKey", "params": ["_air", "<SURI>", "<ACCOUNT_ID>"]}' http://127.0.0.1:9933
```
Example call:
First create a new account from account section in substrate explorer and note the recovery prashe.
```shell=
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "author_insertKey", "params": ["_air", "weekend vocal plug athlete drink ecology swap climb isolate theme potato divide", "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"]}' http://127.0.0.1:9933
```
2) Give special permission to previously inserted account
We have to have a way to distinguish special origin that is being generated while calling from offchain. We do so my keeping a onchain value with accountId same as configured in offchain Keystore in above step.
This is done by calling `set_offchain_account` dispatchable call under `airdrop` pallet.
3) Fund the creditor account with enough balance
We use an seperate account referred as `creditorAccount` to fund the user that are eligible for claiming. Given that we have to make sure that Creditor account is funded with enough balance that it can do all airdropping.
For this, as soon as the launches creditor account will be printed to log as something like
```
2022-03-10 08:26:23 [Airdorp pallet] Creditor account address is <ss58 encoded addres> (Hex encoded address...)
```
Fund this address with enough tokens
4) Fund offchainAccount
Since offchain is calling extrinsic, it also have to pay for fees. For that, offchain Account must be credited with some amount to pay for fee. However, all call from airdrop-pallet tries to return fee if the call passes that it is from offchain. So allocating only few units for offchainWorer should be enough
### Keep an eye on log
There are few cases where some claiming might fail. For eg:
- Creditor is out of fund
- No value was set to `OffchinAccount` storage
- Error while doing http calls
Al this error will decrement the retry quota for a claimer. When this quota reach 0, a log will be thrown ( along with event too). So node operator might have an event subscriber as well as log notifier to identify such cases
---
# Unresolved Questions
## About creditor account
- Will not having an seperate account but doing all transfer from node total issuence will be better option?
reference: https://docs.rs/pallet-balances/latest/pallet_balances/#terminology
- Is there a way to put this account in GenesisConfig?
### Malcious input from user in extrinsic
We are receiving Vec<u8> in extrinsic. This implies that a user can supply potentially huge chunk of bytes trying to overflood the memory as well as transaction queue.
Only way we are assuming this might not happen is of associated fee. That user have to pay to do attack. Still, if someone wanted to be real nasty and decided to do so, it might still be possible.
#### Possible prevention
- [currently preferred] Accept static array `[u8; N]` instead of `Vec<u8>`. This will make it impossible in first place to pass huge data then expected
- [Insufficient research] There might something already be in substrate which will prevent this
## About storing authorised account in on-chain
Currently we are storing authorised account ( account that is considered to have special permission when called from offchain worker ) in on-chain value namely `OffchainAccount`.
Does this implies that all node must have same `OffchainAccount`?
If so then running on multiple node to pass, same account should be shared for offchain KeyStore too. Which is impractical from security point of view.
However as long as we stick with running claiming process in single node. This should not be much of a problem.
What if another node not running
Solution:
- Keep `OffchainAccount` on offchain storage so it won't be part of network agreement