· 8 years ago · Apr 17, 2018, 08:12 PM
1package tcs.examples.ethereum.sql
2
3import tcs.blockchain.BlockchainLib
4import tcs.db.sql.Table
5import tcs.db.{DatabaseSettings, PostgreSQL}
6import scalikejdbc._
7import tcs.blockchain.ethereum.EthereumSettings
8
9object EthereumPools {
10 def main(args: Array[String]): Unit = {
11 val start = 500000
12 val nBlocks = 20
13 val end = start + nBlocks
14 val blockchain = BlockchainLib.getEthereumBlockchain(new EthereumSettings("https://mainnet.infura.io/lGhdnAJw7n56K0xXGP3i:8545")).start(start).end(end)
15 val pg = new DatabaseSettings("ethereum", PostgreSQL, "postgres", "0")
16
17 /**
18 * Table:
19 * address: ~
20 * sent: amount of ethereum that the address has sent
21 * received: amount of ethereum that the address has received
22 * total: ~
23 * n_sent: number of transactions which the address has sent etheruem,
24 * or number of transactions that have withdrawn from that address
25 * n_received: number of transactions which the address has received
26 * etheruem from, or number of transactions that have sent
27 * ethereum to that address
28 */
29 val blockTable = new Table(
30 sql"""
31 CREATE TABLE IF NOT EXISTS balances(
32 address CHARACTER VARYING(100) NOT NULL PRIMARY KEY,
33 sent DECIMAL,
34 received DECIMAL,
35 total DECIMAL,
36 n_sent DECIMAL,
37 n_received DECIMAL
38 )
39 """,
40 sql"""
41 INSERT INTO balances(address,sent,received, total, n_sent, n_received)
42 VALUES (?, ?, ?, ?, ?, ?)
43 """,
44 pg, nBlocks
45 )
46
47 println("table created")
48
49 // address => sent, received, total, n_sent, n_received
50 var map = Map[String, Array[scala.math.BigInt]]()
51
52 var counter = 0
53
54 println("foreach starting...")
55 blockchain.foreach(block => {
56 counter += 1
57
58 block.txs.foreach(transaction => {
59 println(counter.toString + ") n transactions: " + map.values.toList.length)
60
61 if (map.contains(transaction.from)) {
62 // if the address "from" is already present in the map,
63 // we can update its balance
64
65 /** how to update:
66 * the "value" goes from the "from" address to the "to" address
67 * 1. add "value" to the sent ethereums
68 * 2. substract "value" from the total
69 * 3. increment the number of transactions that have taken
70 * eth from "from", i.e. increment n_sent
71 */
72
73 // first, save the current balance
74 val balance: Array[BigInt] = map(transaction.from)
75 map -= transaction.from // delete the value from the map
76
77 // update of the quantities
78
79 // update of the quantity of eth sent
80 balance(0) += transaction.value // sent += value
81
82 // update of the total
83 balance(2) -= transaction.value // total -= value
84
85 // update of the number of transaction that the address has sent to
86 balance(3) += 1 // n_sent ++
87
88 // re-add the value to the map
89 map += transaction.from -> balance
90 }
91 else {
92 // the address "from" is not in the map, so it must be added
93 // only if there is a transaction sending money
94 if (transaction.value > 0)
95 /** add an entry to the map which goes from the "from" address to
96 * an array with:
97 * sent: value
98 * received: 0
99 * total: -value
100 * n_sent: 1
101 * n_received: 0
102 */
103 map += transaction.from -> Array(transaction.value, 0, -transaction.value, 1, 0)
104 }
105
106 if (map.contains(transaction.to)) {
107 // if the address "to" is already present in the map,
108 // we can update its balance
109
110 /** how to update:
111 * the "value" goes from the "from" address to the "to" address
112 * 1. add "value" to the received ethereums
113 * 2. add "value" from the total
114 * 3. increment the number of transactions that have sent
115 * eth to "to", i.e. increment n_receivd
116 */
117
118 // first, save the current balance
119 val balance: Array[BigInt] = map(transaction.to)
120 map -= transaction.to // delete the value from the map
121
122 // update of the quantity of eth sent
123 balance(1) += transaction.value // received += value
124
125 // update of the total
126 balance(2) += transaction.value // total += value
127
128 // update of the number of transaction that have taken eth from that address
129 balance(4) += 1 // n_received ++
130
131 // re-add the value to the map
132 map += transaction.to -> balance
133 }
134 else {
135 // the address "to" is not in the map, so it must be added
136 // only if there is a transaction sending money
137 if (transaction.value > 0)
138 /** add an entry to the map which goes from the "to" address to
139 * an array with:
140 * sent: 0
141 * received: value
142 * total: value
143 * n_sent: 0
144 * n_received: 1
145 */
146 map += transaction.to -> Array(0, transaction.value, transaction.value, 0, 1)
147 }
148 })
149 })
150 println("...foreach ended")
151
152 for(address <- map.keys) {
153 blockTable.insert(address :: map(address).toList) // insert each element of the map in the db
154 println(address::map(address).toList)
155 }
156 println("data inserted")
157
158 blockTable.close
159 println("table closed")
160
161 println("END")
162 }
163}