PILLOLE DI BLOCKCHAIN -- GETH -- CONSOLE
Connessione JSON-RPC
Connessione WebSocket
Preload - eseguire script
Personal
Net
Eth
Web3
Db
Debug
Admin
Miner
Account
Chi ha minato un blocco
Txpool
Clique
Smart Contract into Blockchain
Per operare nella blockchain Ethereum tramite CLI si può utilizzare il programma GETH scritto in GO che ci permette di connettersi alle diverse reti Ethereum (Mainnet) e le reti di sviluppo come Rinkeby o Rospen o una rete privata. Per vedere come creare una rete privata vedere la documentazione al seguente link ETH PRIVATE NETWORK Una volta installato il pgm geth vediamo alcuni comandi utili per accedere alla console. Con il comando seguente utilizziamo il formato di configurazione toml per salvare nel file di configurazione mainnet.toml che ci permette di accedere alla rete MAINNET senza reinserire i parametri
geth dumpconfig > mainnet.toml oppure
geth --datadir "./data" --networkid 25 dumpconfig >chain25.toml //salvo parametri della Private Network 25
geth --config chain.toml //nel file chain.toml ci sono parametri per attivare la chain 25
Per comunicare con la rete privata possiamo utilizzare il protocollo JSON-RPC per comunicare la porta 8545 con http con i seguenti parametri :

--rpc //per abilitare json-rpc
--rpcapi //per abilitare di default eth, web3 e net
--rpcaddr "host" //di default localhost
--rpcport "port" //di default 8545
--rpccorsdomain “*”

questi comandi sono ora deprecati e si consiglia di usare al loro posto i seguenti comandi
--http
--http.api="net,eth,web3,personal,admin,miner"
--http.port 8545
--http.corsdomain '*'
vediamo un esempio:
geth --http --http.addr localhost --http.api --http.port --identity "chain 25" --trace "./trace.txt"
Nella console è possibile eseguire gli script Javascript indicando con il parametro --preload indicando dove trovare gli script
geth --preload “./path dove sono scripts/file.js” console
geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.port 8545 --verbosity "0" --preload "./js/primo.js" console
Lo script primo.js è il seguente con una function:
primo = function() {
console.log('esempio command js in console geth')
return "fatto"
}
ed una variabile

secondo = "Hello, everybody";

Ora vediamo il comando da terminal:
geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.port 8545 --verbosity "0" --preload "./js/primo.js" console
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2
at block: 0 (Thu Jan 01 1970 01:00:00 GMT+0100 (CET))
datadir: /home/mecbar/node1/data/data
modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> primo()
"fatto"

> secondo
"Hello, everybody"
>
Sotto in comando per aprire la console con altri parametri
si segnala in particolare --http.api="net,eth,web3,personal,admin,miner" che ci permette di eseguire le api indicate

geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.port 8545 --exec "personal.listAccounts" console
Vediamo per le classi principali l'elenco dei comandi e delle funzioni disponibili
> personal
{
listAccounts: [],
listWallets: [],
deriveAccount: function(),
ecRecover: function(),
getListAccounts: function(callback),
getListWallets: function(callback),
importRawKey: function(),
initializeWallet: function(),
lockAccount: function(),
newAccount: function(),
openWallet: function(),
sendTransaction: function(),
sign: function(),
signTransaction: function(),
unlockAccount: function(),
unpair: function()
}

> net
{
listening: true,
peerCount: 0,
version: "25",
getListening: function(callback),
getPeerCount: function(callback),
getVersion: function(callback)
}

> eth
{
accounts: [],
blockNumber: 0,
coinbase: undefined,
compile: {
lll: function(),
serpent: function(),
solidity: function()
},
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: 1000000000,
hashrate: 0,
mining: false,
pendingTransactions: [],
protocolVersion: "0x41",
syncing: false,
call: function(),
chainId: function(),
contract: function(abi),
estimateGas: function(),
fillTransaction: function(),
filter: function(options, callback, filterCreationErrorCallback),
getAccounts: function(callback),
getBalance: function(),
getBlock: function(),
getBlockByHash: function(),
getBlockByNumber: function(),
getBlockNumber: function(callback),
getBlockTransactionCount: function(),
getBlockUncleCount: function(),
getCode: function(),
getCoinbase: function(callback),
getCompilers: function(),
getGasPrice: function(callback),
getHashrate: function(callback),
getHeaderByHash: function(),
getHeaderByNumber: function(),
getMining: function(callback),
getPendingTransactions: function(callback),
getProof: function(),
getProtocolVersion: function(callback),
getRawTransaction: function(),
getRawTransactionFromBlock: function(),
getStorageAt: function(),
getSyncing: function(callback),
getTransaction: function(),
getTransactionCount: function(),
getTransactionFromBlock: function(),
getTransactionReceipt: function(),
getUncle: function(),
getWork: function(),
iban: function(iban),
icapNamereg: function(),
isSyncing: function(callback),
namereg: function(),
resend: function(),
sendIBANTransaction: function(),
sendRawTransaction: function(),
sendTransaction: function(),
sign: function(),
signTransaction: function(),
submitTransaction: function(),
submitWork: function()
}

web3
{
admin: {
datadir: "/home/mecbar/develop/mecbar-foto/data",
nodeInfo: {
enode: "enode://0fb1f5700a7b33605ada829078078d0c556c337d96211a30a1654aaa9e28c857f 313f9b34803da76430fc17c7ee98722d764687d628aa ed32b8987b620847b63@127.0.0.1:30305",
enr: "enr:-Jq4QP_GdHnJ_avNEGwYO-g1KsHFtTpHFX_88bSNzgtFeK0pGV6aHcserAxPNTxPOY X733O6RBv6_udO1S4IzYOy464Fg2V0aMrJhPxk7ASDEYwwgmlkgnY0gml whH8AAAGJc2VjcDI1NmsxoQMPsfVwCnszYFragpB4B40MVWwzfZYhGjCh UqqnijIV4N0Y3CCdmGDdWRwgnZh",
id: "19e02ca82ce3ee76a63078723b5cd4cc4ca81dea2d1bbb1637c9b3b4c9e7046e", ip: "127.0.0.1",
listenAddr: "[::]:30305",
name: "Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2",
ports: {
discovery: 30305,
listener: 30305
},
protocols: {
eth: {...}
}
},
peers: [],
addPeer: function(),
addTrustedPeer: function(),
clearHistory: function(),
exportChain: function(),
getDatadir: function(callback),
getNodeInfo: function(callback),
getPeers: function(callback),
importChain: function(),
removePeer: function(),
removeTrustedPeer: function(),
sleep: function(),
sleepBlocks: function(),
startRPC: function(),
startWS: function(),
stopRPC: function(),
stopWS: function()
},
info: undefined,
blockNetworkRead: function(),
download: function(),
get: function(),
getHive: function(callback),
getInfo: function(callback),
modify: function(),
put: function(),
retrieve: function(),
store: function(),
swapEnabled: function(),
syncEnabled: function(),
upload: function()
},
currentProvider: {
send: function(),
sendAsync: function()
},
db: {
getHex: function(),
getString: function(),
putHex: function(),
putString: function()
},
debug: {
accountRange: function(),
backtraceAt: function(),
blockProfile: function(),
chaindbCompact: function(),
chaindbProperty: function(),
cpuProfile: function(),
dumpBlock: function(),
freeOSMemory: function(),
freezeClient: function(),
gcStats: function(),
getBadBlocks: function(),
getBlockRlp: function(),
getModifiedAccountsByHash: function(),
getModifiedAccountsByNumber: function(),
goTrace: function(),
memStats: function(),
mutexProfile: function(),
preimage: function(),
printBlock: function(),
seedHash: function(),
setBlockProfileRate: function(),
setGCPercent: function(),
setHead: function(),
setMutexProfileFraction: function(),
stacks: function(),
standardTraceBadBlockToFile: function(),
standardTraceBlockToFile: function(),
startCPUProfile: function(),
startGoTrace: function(),
stopCPUProfile: function(),
stopGoTrace: function(),
storageRangeAt: function(),
testSignCliqueBlock: function(),
traceBadBlock: function(),
traceBlock: function(),
traceBlockByHash: function(),
traceBlockByNumber: function(),
traceBlockFromFile: function(),
traceTransaction: function(),
verbosity: function(),
vmodule: function(),
writeBlockProfile: function(),
writeMemProfile: function(),
writeMutexProfile: function()
},

> admin
{
datadir: "/home/mecbar/develop/mecbar-foto/data",
nodeInfo: {
enode: "enode://0fb1f5700a7b33605ada829078078d0c556c337d96211a30a1654aaa9e28c857f313f9b34803da76 430fc17c7ee98722d764687d628aaed32b8987b620847b63@127.0.0.1:30305",
enr: "enr:-Jq4QP_GdHnJ_avNEGwYO-g1KsHFtTpHFX_88bSNzgtFeK0pGV6aHcserAxPNTxPOYX733O6RBv6_ udO1S4IzYOy464Fg2V0aMrJhPxk7ASDEYwwgmlkgnY0gmlwhH8AAAGJc2Vjc DI1NmsxoQMPsfVwCnszYFragpB4B40MVWwzfZYhGjChZUqqnijIV4N0Y3CCdmGDdWRwgnZh",
id: "19e02ca82ce3ee76a63078723b5cd4cc4ca81dea2d1bbb1637c9b3b4c9e7046e",
ip: "127.0.0.1",
listenAddr: "[::]:30305",
name: "Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2",
ports: {
discovery: 30305,
listener: 30305
},
protocols: {
eth: {
config: {...},
difficulty: 17179869184,
genesis: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
head: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
network: 25 }
}
},
peers: [],
addPeer: function(),
addTrustedPeer: function(),
clearHistory: function(),
exportChain: function(),
getDatadir: function(callback),
getNodeInfo: function(callback),
getPeers: function(callback),
importChain: function(),
removePeer: function(),
removeTrustedPeer: function(),
sleep: function(),
sleepBlocks: function(),
startRPC: function(),
startWS: function(),
stopRPC: function(),
stopWS: function()
}

> miner
{
getHashrate: function(),
setEtherbase: function(),
setExtra: function(),
setGasPrice: function(),
setRecommitInterval: function(),
start: function(),
stop: function()
}
Tramite il comando account possiamo definire una nuovo account o fare la lista degli account appertenti alla chain o modificare la password di un account o importare un account già definito all'interno della nostra chain.

Vediamo questi comandi iniziando con il creare un nuovo account ma prima vediamo quali sono gli account già presenti.


ACCONT LIST

geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.addr localhost account list console
INFO [08-08|11:00:27.639] Maximum peer count ETH=50 LES=0 total=50
INFO [08-08|11:00:27.640] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [08-08|11:00:27.641] Set global gas cap cap=25000000
Account #0: {c9e54ccac280032fb89e1ca14607a952e5b9a84a} keystore:///home/mecbar/node1/data/keystore/UTC--2020-08-01T13-51-02.242478702Z--c9e54ccac280032fb89e1ca14607a952e5b9a84a


ACCOUNT NEW
geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.addr localhost account new console
INFO [08-08|11:02:51.817] Maximum peer count ETH=50 LES=0 total=50
INFO [08-08|11:02:51.817] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new account is locked with a password. Please give a password. Do not forget this password.
password:
Repeat password:
Your new key was generated


Public address of the key: 0x97e908aa7Bc94B05D581DfE9B5e37F558c646654
ath of the secret key file: data/keystore/UTC--2020-08-08T09-03-03.363284578Z--97e908aa7bc94b05d581dfe9b5e37f558c646654

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!


ACCOUNT LIST

geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.addr localhost account list console
INFO [08-08|11:04:51.122] Maximum peer count ETH=50 LES=0 total=50
INFO [08-08|11:04:51.122] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [08-08|11:04:51.123] Set global gas cap cap=25000000
Account #0: {c9e54ccac280032fb89e1ca14607a952e5b9a84a} keystore:///home/mecbar/node1/data/keystore/UTC--2020-08-01T13-51-02.242478702Z--c9e54ccac280032fb89e1ca14607a952e5b9a84a
Account #1: {97e908aa7bc94b05d581dfe9b5e37f558c646654} keystore:///home/mecbar/node1/data/keystore/UTC--2020-08-08T09-03-03.363284578Z--97e908aa7bc94b05d581dfe9b5e37f558c646654


ACCOUNT UPDATE -- key file password update la password di un account


geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --http.corsdomain '*' --http.api="net,eth,web3,personal,admin,miner" --http.addr localhost account update 97e908aa7bc94b05d581dfe9b5e37f558c646654 console
INFO [08-08|11:07:52.293] Maximum peer count ETH=50 LES=0 total=50
INFO [08-08|11:07:52.293] Smartcard socket not found, disabling err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [08-08|11:07:52.294] Set global gas cap cap=25000000
Unlocking account 97e908aa7bc94b05d581dfe9b5e37f558c646654 | Attempt 1/3
Password:
INFO [08-08|11:08:00.631] Unlocked account address=0x97e908aa7Bc94B05D581DfE9B5e37F558c646654
Please give a new password. Do not forget this password.
Password:
Repeat password:



ACCOUNT IMPORT


geth account import --datadir /directory dove trovare key ./key.prv
The new account will be encrypted with a passphrase.
Please enter a passphrase now.
Passphrase:
Repeat Passphrase:
Address: { address importato }
Queste operazioni possono essere eseguite senza digitare le password ma inserendo le stesse in un file e passando il nome del file
> eth.accounts
["0xc9e54ccac280032fb89e1ca14607a952e5b9a84a", "0x2ab6bd87a4c68d106824240dd9e6317c01070e08", "0x97e908aa7bc94b05d581dfe9b5e37f558c646654"]
Vediamo come eseguire una transazione tramite script indicando il mittente, il destinatario e la sooma entro un oggetto.
terzo = () => {
sender = personal.listAccounts[0];
receiver = personal.listAccounts[1];
quota = web3.toWei(0.05,"ether");
eth.sendTransaction({from:sender,to:receiver,value:quota}
)
}
Con il comando sottostante eseguiamo lo script e sblocchiamo il primo account della lista
geth –datadir …. networkid 25 –exec "loadScript('./primo.js')" unlock [0]


Per unlock account per problemi inserire :
--allow-insecure-unlock

Vediamo ora i comandi per minare i nuovi blocchi

Mine :
--mine enable mine
--miner.threads default:8
--etherbase default: account[0]
--gasprice
--extradata -- possibilità inserire dati extra nel block creato

Comandi in console
miner.start()
miner.stop()

Per vedere chi ha minato i blocchi precedenti ad un dato block in console si può utilizzare la seguente function
> function minedBlocks(lastn, addr) { addrs = []; if (!addr) { addr = eth.coinbase } limit = eth.blockNumber - lastn for (i = eth.blockNumber; i >= limit; i--) { if (eth.getBlock(i).miner == addr) { addrs.push(i) } } return addrs } > minedBlocks(86, eth.coinbase)
[85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Per vedere il numero del blocco attuale
eth.blockNumber

eth.hashrate se ritorna valore > 0 sta minando altrimenti no.

Comando per settare l'account abilitato ad essere il minatore che deve essere sbloccato(unlock).


Per vedere il saldo di un account in questo caso specifico del minatore
eth.getBalance(eth.coinbase).toNumber();

Per settare il minatore
miner.setEtherbase("address)

Per vedere il saldo in ether di un account
> web3.fromWei(eth.getBalance(eth.coinbase), "ether")

9.04625697166532776746648320380374280103671755200316906558262375061821325312e+56
CONSOLE :
admin personal miner txpool debug
admin.nodeInfo
> admin.nodeInfo
{
enode: "enode://691407be50aae792c4d52bfaa42f913e77280aa410f3ef1fad5e2 ce84c0aaabd1693de33c75e5f9d904bedc3a74f065a3e63f331d 1e006556fe723e54f369d51@127.0.0.1:30303",
enr: "enr:-Je4QJ7T2254xicWAlkyNrsOQqwzd_Y_YR-xrjrd_a7qKdmfCSKWPG GwWb8uv-elToehaF997FcwH0h3XCanmn5mJxceg2V0aMfGhN0JU4CAg mlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQNpFAe-UKrnksTVK_qkL5E-dygKpBDz7x-tXizoTAqqvYN0Y3CCdl-DdWRwgnZf",
id: "177facbd7904233266f192e3c922656305d2f52af8dfe1a500ef1323a39a69bb",
ip: "127.0.0.1",
listenAddr: "[::]:30303",
name: "Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2", ports: {
discovery: 30303,
listener: 30303
},
protocols: {
eth: {
config: {
byzantiumBlock: 0,
chainId: 25,
clique: {...},
constantinopleBlock: 0,
eip150Block: 0,
eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000",
eip155Block: 0,
eip158Block: 0,
homesteadBlock: 0,
istanbulBlock: 0,
petersburgBlock: 0
},
difficulty: 3,
genesis: "0x17d40999df5f149ebca5df7439ac6431a3569f99ef59bec89f93e41f226084ab",
head: "0x090e5afeacd7fecc94f974e46604f51eafbd3b079c3023eaf0855b1ebc62553d",
network: 25
}
}
}

admin.peers
Per compilare gli Smart Contract creati con Solidity si può utilizzare Remix oppure compilarli con solc(prima va installato localmente)

--solc option per compiler solidity
--setSolc(‘path solidity compiler’)

TX POOL
personal.listAccounts
personal.newAccount(‘password’) //crea nuovo account
personal.importRawKey(keydata,paraphrase)
personal.unlockAccount("0xc9e54ccac280032fb89e1ca14607a952e5b9a84a"])
personal.sendTransaction(trx_object,’paraphrase’)
trx_object = from:addres to:address value in wei:1

ogni account ha un unico nonce per transaction
- indica la sequenza delle transazioni di un account

Dopo aver inviato la transazione con sendTransaction si può verificare la transaction pool per vedere le transazioni pendenti(pending POOL) e la Quequed POOL con le istruzioni seguenti:

txpool.status
txpool.inspect
txpool.content

Qui vediamo i comandi per vedere il numero di blocco attuale e poi i dati del blocco pendente eth.blockNumber
> txpool.inspect
{
pending: {
0x1205577aD6834043992CA4bFd2439c54BBF47f99: {
0: "contract creation: 0 wei + 100000 gas × 1000000000 wei"
}
},
queued: {}
}



> eth.getBlock('pending')
{
difficulty: 2,
extraData: "0xd883010912846765746888676f312e31342e32856c696e7578000000000000000",

gasLimit: 4709181,
gasUsed: 100000,
hash: null,
logsBloom: "0x000000000000000000000000000000000000000000000000000000000000000000000", miner: null,
mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
nonce: null,
number: 2,
parentHash: "0x2f436694c9ada6e2c8d04a0c52b205c2044ecaf99127a6187829864ef82c94e5",
receiptsRoot: "0x777f1c1c378807634128348e4f0eeca6a0e7f516ea411690ca04266323f671a4",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 1024,
stateRoot: "0xcc0e10e6362f37be2c648304ad4f443525a14d7c0ad92e7472395ab69d285d7f",
timestamp: 1596978215,
totalDifficulty: 0,
transactions: ["0x4095742701a2369bbfcdcbf33947f79914236f47b84f681fdb344a93c8881a5e"],
transactionsRoot: "0x99d9fb5b2025672c7a0ce757d2f58474bf9d4efdc86066d685133682169e7c51",
uncles: []
}
eth.pendingTransactions
Per interagire con la blockchain si può utilizzare la libreria web3.js che ci permette tramite Javascript di utilizzare i comandi previsti in console
- per i numeri usa Bignumber library ma max 20 floating point per questo si usa l'unità di misura wei e non gli ether
Sono previste function sincrone ed asincrone e le callback function
web3.net.getPeerCount(function(error, result) {
if (error) {
……
} else { …… }
}

CLIQUE
Clique è un metodo per implementare il Proof of Autority per determinare quale account è autorizzato a minare i blocchi della blockchain per le reti private.

Vediamo i comandi principali :
clique.getSnapshotAtHash(blockHash)
clique.getSigners(blockNumber)
clique.proposals()
clique.propose(address, auth)
clique.status()

Finora abbiamo visto come collegarci con con il JSON-RPC ma possiamo utilizzare anche WebSocket con la defult port 8546
geth --datadir "./data" --networkid 25 --port 30305 --ipcdisable --ws --ws.api="net,eth,web3,personal,admin,miner" --ws.port 8546 console
INFO [08-08|21:45:03.036] Started P2P networking
self=enode://018fc0979d4330cf1d0cf666e69dde441d584654f57b4f63deaf436eb729032251055153 f9cd31313ad01b5909b444e8eab90f8d6a0a96f40a1f0f336790b8f2@127.0.0.1:30305
INFO [08-08|21:45:03.039] WebSocket endpoint opened url=ws://127.0.0.1:8545
INFO [08-08|21:45:03.094] Etherbase automatically configured address=0x707F3592F561be42A8583a2D42F376F07F4F03bc
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.18-stable-f5382591/linux-amd64/go1.14.2
coinbase: 0x707f3592f561be42a8583a2d42f376f07f4f03bc
at block: 0 (Sat Aug 01 2020 15:55:43 GMT+0200 (CEST))
datadir: /home/mecbar/CHAIN25/data
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> debug
{
accountRange: function(),
backtraceAt: function(),
blockProfile: function(),
chaindbCompact: function(),
chaindbProperty: function(),
cpuProfile: function(),
dumpBlock: function(),
freeOSMemory: function(),
freezeClient: function(),
gcStats: function(),
getBadBlocks: function(),
getBlockRlp: function(),
getModifiedAccountsByHash: function(),
getModifiedAccountsByNumber: function(),
goTrace: function(),
memStats: function(),
mutexProfile: function(),
preimage: function(),
printBlock: function(),
seedHash: function(),
setBlockProfileRate: function(),
setGCPercent: function(),
setHead: function(),
setMutexProfileFraction: function(),
stacks: function(),
standardTraceBadBlockToFile: function(),
standardTraceBlockToFile: function(),
startCPUProfile: function(),
startGoTrace: function(),
stopCPUProfile: function(),
stopGoTrace: function(),
storageRangeAt: function(),
testSignCliqueBlock: function(),
traceBadBlock: function(),
traceBlock: function(),
traceBlockByHash: function(),
traceBlockByNumber: function(),
traceBlockFromFile: function(),
traceTransaction: function(),
verbosity: function(),
vmodule: function(),
writeBlockProfile: function(),
writeMemProfile: function(),
writeMutexProfile: function()
}
INSERIMENTO SMART CONTRACT NELLA BLOCKCHAIN
Iniziamo con la scrittura del sottostante programma in Solidity nel file primo.sol
primo.sol
pragma solidity >=0.4.13;

contract primo {
function operazioni(uint _a, uint _b) public pure returns (uint o_somma, uint o_prodotto) {
o_somma = _a + _b;
o_prodotto = _a * _b;
}
function moltiplicazione(uint _a, uint _b) public pure returns (uint) {
return _a * _b;
}
}

Compiliamo il programma con solc:

$ solc -o . --bin --abi primo.sol
e vediamo che il compilatore ha generato primo.abi e primo.bin, sotto il contenuto di primo.abi

Il file .abi contiene l'interfacaccia del contract mentre il file .bin contiene il codice compilato. Per inserire il contract in geth manualmente ma anche tramite javascript

Nel nostro esempio compiliamo il programma solidity e creiamo in output uno script Javascript che inseriremo nalla chain cno il comado loadScript come vedremo nei comandi sottostanti

per essere eseguito deve essere inserito il programma compilato da un account sbloccato e poi il blocco dove è inerito il contratto deve essere minato.

personal.unlockAccount(eth.coinbase)

Ora compiliamo il programma con la creazione dello script primoContract.js
echo "var primoContract=`solc --optimize --combined-json abi,bin,interface primo.sol`" > primoContract.js


carichiamo lo script nella chain
> loadScript("contract/primoContract.js")

e vediamo il risultato

> primoContract
{
contracts: {
primo.sol:primo: {
abi: "[{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_b\",\"type\":\"uint256\"}],\"name\":\"moltiplicazione\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\" :\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\ "_a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_b\",\"type\":\"uint256\"}],\"name\":\"operazioni\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"o_somma\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"o_prodotto\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]",
bin: "608060405234801561001057600080fd5b5060e48061001f6000396000f3fe608 ...032"
}
},
version: "0.5.16+commit.9c3226ce.Linux.g++"
}
Dopo aver inserito lo script passiamo ad inserire il file abi
> primo = web3.eth.contract(JSON.parse(primoContract.contracts["primo.sol:primo"].abi))
{
abi: [{
constant: true,
inputs: [{...}, {...}],
name: "moltiplicazione",
outputs: [{...}],
payable: false,
stateMutability: "pure",
type: "function"
}, {
constant: true,
inputs: [{...}, {...}],
name: "operazioni",
outputs: [{...}, {...}],
payable: false,
stateMutability: "pure",
type: "function"
}],
eth: {
accounts: ["0xa960a0c1d3affca95b41c6e30ef0ecf9a5da98fe", "0x89ba3bc13225c5afbfcf2d40c9bc134040e35dae"],
blockNumber: 94,
coinbase: "0xa960a0c1d3affca95b41c6e30ef0ecf9a5da98fe",
compile: {
lll: function(),
serpent: function(),
solidity: function()
},
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: 1000000000,
hashrate: 0,
mining: false,
pendingTransactions: [{
blockHash: null,
blockNumber: null,
from: "0xa960a0c1d3affca95b41c6e30ef0ecf9a5da98fe",
gas: 100000,
gasPrice: 1000000000,
hash: "0xbf94c2d861481f1d575473b7bb2cbb93166edb0725d7cac2f36317ea8572b8c5",
input: "0x608060405234801561001057600080fd5b5061012680610020....30005100032",
nonce: 1,
r: "0x783dcb48a96697f6e9f9a79ae6a6a71c37473373599b1c33c19ec23b525e8792",
s: "0xb5156db19ff296bad82084a2e82db22757de1a46b43779b04687aa3cb23036d",
to: null,
transactionIndex: null,
v: "0x91",
value: 0
}],
protocolVersion: "0x41",
syncing: false,
call: function(),
chainId: function(),
contract: function(abi),
estimateGas: function(),
fillTransaction: function(),
filter: function(options, callback, filterCreationErrorCallback),
getAccounts: function(callback),
getBalance: function(),
getBlock: function(),
getBlockByHash: function(),
getBlockByNumber: function(),
getBlockNumber: function(callback),
getBlockTransactionCount: function(),
getBlockUncleCount: function(),
getCode: function(),
getCoinbase: function(callback),
getCompilers: function(),
getGasPrice: function(callback),
getHashrate: function(callback),
getHeaderByHash: function(),
getHeaderByNumber: function(),
getMining: function(callback),
getPendingTransactions: function(callback),
getProof: function(),
getProtocolVersion: function(callback),
getRawTransaction: function(),
getRawTransactionFromBlock: function(),
getStorageAt: function(),
getSyncing: function(callback),
getTransaction: function(),
getTransactionCount: function(),
getTransactionFromBlock: function(),
getTransactionReceipt: function(),
getUncle: function(),
getWork: function(),
iban: function(iban),
icapNamereg: function(),
isSyncing: function(callback),
namereg: function(),
resend: function(),
sendIBANTransaction: function(),
sendRawTransaction: function(),
sendTransaction: function(),
sign: function(),
signTransaction: function(),
submitTransaction: function(),
submitWork: function()
},
at: function(address, callback),
getData: function(),
new: function()
}
Prepariamo il file bin con l'aggiunta di 0x all'inizio poi valutiamo quanto gas è necessario per inserire il contratto nella chain e vediamo che si necessita di gas > 115000 e successivamente inseriamo il contratto bin inserendo il file bin, il gas necessario e l'account che effettua l'inserimento che ricordiamo deve essere sbloccato
> primoBin = "0x" + primoContract.contracts["primo.sol:primo"].bin

> eth.estimateGas({data: primoBin })

> primoI = primo.new({data: primoBin ,gas: 130000, from: eth.coinbase})
gas stimato : 115415

INFO [08-09|19:50:11.256] Submitted contract creation fullhash=0x65a0e26484c0ace99c498313f151db8211eb6e399ff26cfd84ff4214a38198d1 contract=0x90B045daeA6D67CC610FfD75ED0B350C1162543A
{
abi: [{
constant: true,
inputs: [{...}, {...}],
name: "moltiplicazione",
outputs: [{...}],
payable: false,
stateMutability: "pure",
type: "function"
}, {
constant: true,
inputs: [{...}, {...}],
name: "operazioni",
outputs: [{...}, {...}],
payable: false,
stateMutability: "pure",
type: "function"
}],
address: undefined,
transactionHash: "0x65a0e26484c0ace99c498313f151db8211eb6e399ff26cfd84ff4214a38198d1"
}
Da notare che il l'operazione non ha ancora assegnato un address che riceverà dopo che il blocco verrò minato. Per cui ora faremi partire il mining vediamo il contratto che riceve l'address e poi fermiamo il mining
miner.start()

INFO [08-09|19:51:08.162] Commit new mining work number=95 sealhash="7fe2c3…68985d" uncles=0 txs=0 gas=0 fees=0 elapsed="227.387µs"
INFO [08-09|19:51:08.163] Commit new mining work number=95 sealhash="46fc80…f851fb" uncles=0 txs=2 gas=215415 fees=0.000215415 elapsed="875.409µs"
INFO [08-09|19:51:08.602] Successfully sealed new block number=95 sealhash="46fc80…f851fb" hash="0aa75c…9f6d40" elapsed=439.6
primoI
{
abi: [{
constant: true,
inputs: [{...}, {...}],
name: "moltiplicazione",
outputs: [{...}],
payable: false,
stateMutability: "pure",
type: "function"
}, {
constant: true,
inputs: [{...}, {...}],
name: "operazioni",
outputs: [{...}, {...}],
payable: false,
stateMutability: "pure",
type: "function"
}],
address: "0x90b045daea6d67cc610ffd75ed0b350c1162543a",
transactionHash: "0x65a0e26484c0ace99c498313f151db8211eb6e399ff26cfd84ff4214a38198d1",
allEvents: function(),
moltiplicazione: function(),
operazioni: function()
}

miner.stop()

Ora possiamo eseguire le function previste dallo Smart Contract e cioè operazioni con la somma e la moltiplicazione e la moltiplicazione diretta
primoI.moltiplicazione.call(3,5)
> primoI.moltiplicazione.call(3,5)
15

> primoI.operazioni.call(5,5)
[10, 25]
Comando per aprire console chain su network id 55 con mining ed inserimento smart contract ed esecuzione dello stesso in console
geth --datadir "./data" --networkid 55 --unlock a960a0c1d3affca95b41c6e30ef0ecf9a5da98fe --password password.txt --allow-insecure-unlock --mine --minerthreads=1 console