added block, tx, address models and store them in mongodb. Joined config files to one config.json file
35
DevelopmentNotes.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Development Notes
|
||||||
|
|
||||||
|
## ToDo list
|
||||||
|
|
||||||
|
- Backend
|
||||||
|
- Network Address generation avoiding infinite relation loops
|
||||||
|
- Sankey Address generation without loops
|
||||||
|
- Frontend
|
||||||
|
- After Sankey visualization, go to Network Address visualization and render without Sankey dots
|
||||||
|
- Both
|
||||||
|
- Tx/day
|
||||||
|
- Tx volume
|
||||||
|
- Block size
|
||||||
|
- Blockchain size
|
||||||
|
|
||||||
|
other
|
||||||
|
- To get tx/hours of last 24 hours
|
||||||
|
Search for TxModel with DateF > last24h
|
||||||
|
Count for each hour
|
||||||
|
- To get tx/day of last month
|
||||||
|
Search TxModel with DateF > last month
|
||||||
|
Count each day
|
||||||
|
- Add counter with total blocks, total tx, total address
|
||||||
|
|
||||||
|
- store date hour, day, etc:
|
||||||
|
```Go
|
||||||
|
type DateModel struct {
|
||||||
|
Hour string `json:"hour"`
|
||||||
|
Day string `json:"day"`
|
||||||
|
Month string `json:"month"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
BlockHash string `json:"blockhash"`
|
||||||
|
BlockHeight string `json:"blockheight"`
|
||||||
|
}
|
||||||
|
```
|
||||||
48
README.md
@@ -2,16 +2,9 @@
|
|||||||
blockchain data analysis, written in Go
|
blockchain data analysis, written in Go
|
||||||
|
|
||||||
#### Not finished - ToDo list
|
#### Not finished - ToDo list
|
||||||
- Backend
|
To Do list in DevelopmentNotes.md https://github.com/arnaucode/goBlockchainDataAnalysis/blob/master/DevelopmentNotes.md
|
||||||
- Network Address generation avoiding infinite relation loops
|
|
||||||
- Sankey Address generation without loops
|
## Instructions
|
||||||
- Frontend
|
|
||||||
- After Sankey visualization, go to Network Address visualization and render without Sankey dots
|
|
||||||
- Both
|
|
||||||
- Tx/day
|
|
||||||
- Tx volume
|
|
||||||
- Block size
|
|
||||||
- Blockchain size
|
|
||||||
|
|
||||||
### Install
|
### Install
|
||||||
1. Nodejs & NPM https://nodejs.org/ --> to get npm packages for the web
|
1. Nodejs & NPM https://nodejs.org/ --> to get npm packages for the web
|
||||||
@@ -22,7 +15,7 @@ blockchain data analysis, written in Go
|
|||||||
### Configure
|
### Configure
|
||||||
- Wallet /home/user/.faircoin2/faircoin.conf:
|
- Wallet /home/user/.faircoin2/faircoin.conf:
|
||||||
```
|
```
|
||||||
rpcuser=usernamerpc
|
rpcuser=faircoinrpc
|
||||||
rpcpassword=password
|
rpcpassword=password
|
||||||
rpcport=3021
|
rpcport=3021
|
||||||
rpcworkqueue=2000
|
rpcworkqueue=2000
|
||||||
@@ -34,12 +27,26 @@ rpcallowip=127.0.0.1
|
|||||||
- goBlockchainDataAnalysis/config.json:
|
- goBlockchainDataAnalysis/config.json:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"user": "usernamerpc",
|
"user": "faircoinrpc",
|
||||||
"pass": "password",
|
"pass": "password",
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"port": "3021",
|
"port": "3021",
|
||||||
"genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046",
|
"genesisTx": "7c27ade2c28e67ed3077f8f77b8ea6d36d4f5eba04c099be3c9faa9a4a04c046",
|
||||||
"genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7"
|
"genesisBlock": "beed44fa5e96150d95d56ebd5d2625781825a9407a5215dd7eda723373a0a1d7",
|
||||||
|
"startFromBlock": 160,
|
||||||
|
"server": {
|
||||||
|
"serverIP": "127.0.0.1",
|
||||||
|
"serverPort": "3014",
|
||||||
|
"webServerPort": "8080",
|
||||||
|
"allowedIPs": [
|
||||||
|
"127.0.0.1"
|
||||||
|
],
|
||||||
|
"blockedIPs": []
|
||||||
|
},
|
||||||
|
"mongodb": {
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"database": "goBlockchainDataAnalysis"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -87,18 +94,19 @@ Webapp will run on 127.0.0.1:8080
|
|||||||
|
|
||||||
|
|
||||||
### Some screenshots
|
### Some screenshots
|
||||||
|
Some screenshots can be old, and can contain errors.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -24,8 +24,8 @@ func timeToDate(blockTime int64) string {
|
|||||||
func hourAnalysis(e EdgeModel, blockTime int64) {
|
func hourAnalysis(e EdgeModel, blockTime int64) {
|
||||||
//fmt.Println(blockTime)
|
//fmt.Println(blockTime)
|
||||||
date := timeToDate(blockTime)
|
date := timeToDate(blockTime)
|
||||||
date_hour := strings.Split(date, " ")[1]
|
dateHour := strings.Split(date, " ")[1]
|
||||||
hour := strings.Split(date_hour, ":")[0]
|
hour := strings.Split(dateHour, ":")[0]
|
||||||
|
|
||||||
hourCount := HourCountModel{}
|
hourCount := HourCountModel{}
|
||||||
err := hourCountCollection.Find(bson.M{"hour": hour}).One(&hourCount)
|
err := hourCountCollection.Find(bson.M{"hour": hour}).One(&hourCount)
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import (
|
|||||||
|
|
||||||
func explore(client *btcrpcclient.Client, blockHash string) {
|
func explore(client *btcrpcclient.Client, blockHash string) {
|
||||||
var realBlocks int
|
var realBlocks int
|
||||||
var nOrigin NodeModel
|
/*var nOrigin NodeModel
|
||||||
nOrigin.Id = "origin"
|
nOrigin.Id = "origin"
|
||||||
nOrigin.Label = "origin"
|
nOrigin.Label = "origin"
|
||||||
nOrigin.Title = "origin"
|
nOrigin.Title = "origin"
|
||||||
nOrigin.Group = "origin"
|
nOrigin.Group = "origin"
|
||||||
nOrigin.Value = 1
|
nOrigin.Value = 1
|
||||||
nOrigin.Shape = "dot"
|
nOrigin.Shape = "dot"
|
||||||
saveNode(nodeCollection, nOrigin)
|
saveNode(nodeCollection, nOrigin)*/
|
||||||
|
|
||||||
for blockHash != "" {
|
for blockHash != "" {
|
||||||
//generate hash from string
|
//generate hash from string
|
||||||
@@ -27,6 +27,17 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if block.Height > config.StartFromBlock {
|
if block.Height > config.StartFromBlock {
|
||||||
|
var newBlock BlockModel
|
||||||
|
newBlock.Hash = block.Hash
|
||||||
|
newBlock.Confirmations = block.Confirmations
|
||||||
|
newBlock.Size = block.Size
|
||||||
|
newBlock.Height = block.Height
|
||||||
|
//newBlock.Amount = block.Amount
|
||||||
|
//newBlock.Fee = block.Fee
|
||||||
|
newBlock.PreviousHash = block.PreviousHash
|
||||||
|
newBlock.NextHash = block.NextHash
|
||||||
|
newBlock.Time = block.Time
|
||||||
|
|
||||||
for k, txHash := range block.Tx {
|
for k, txHash := range block.Tx {
|
||||||
if k > 0 {
|
if k > 0 {
|
||||||
realBlocks++
|
realBlocks++
|
||||||
@@ -39,25 +50,24 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
|
|
||||||
th, err := chainhash.NewHashFromStr(txHash)
|
th, err := chainhash.NewHashFromStr(txHash)
|
||||||
check(err)
|
check(err)
|
||||||
tx, err := client.GetRawTransactionVerbose(th)
|
blockTx, err := client.GetRawTransactionVerbose(th)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
//save Tx
|
//save Tx
|
||||||
var nTx NodeModel
|
var nodeTx NodeModel
|
||||||
nTx.Id = txHash
|
nodeTx.Id = txHash
|
||||||
nTx.Label = txHash
|
nodeTx.Label = txHash
|
||||||
nTx.Title = txHash
|
nodeTx.Title = txHash
|
||||||
nTx.Group = strconv.FormatInt(block.Height, 10)
|
nodeTx.Group = strconv.FormatInt(block.Height, 10)
|
||||||
nTx.Value = 1
|
nodeTx.Value = 1
|
||||||
nTx.Shape = "square"
|
nodeTx.Shape = "square"
|
||||||
nTx.Type = "tx"
|
nodeTx.Type = "tx"
|
||||||
saveNode(nodeCollection, nTx)
|
saveNode(nodeCollection, nodeTx)
|
||||||
|
|
||||||
var originAddresses []string
|
var originAddresses []string
|
||||||
var outputAddresses []string
|
var outputAddresses []string
|
||||||
var outputAmount []float64
|
var outputAmount []float64
|
||||||
for _, Vo := range tx.Vout {
|
for _, Vo := range blockTx.Vout {
|
||||||
//if Vo.Value > 0 {
|
|
||||||
for _, outputAddr := range Vo.ScriptPubKey.Addresses {
|
for _, outputAddr := range Vo.ScriptPubKey.Addresses {
|
||||||
outputAddresses = append(outputAddresses, outputAddr)
|
outputAddresses = append(outputAddresses, outputAddr)
|
||||||
outputAmount = append(outputAmount, Vo.Value)
|
outputAmount = append(outputAmount, Vo.Value)
|
||||||
@@ -70,17 +80,36 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
n2.Shape = "dot"
|
n2.Shape = "dot"
|
||||||
n2.Type = "address"
|
n2.Type = "address"
|
||||||
saveNode(nodeCollection, n2)
|
saveNode(nodeCollection, n2)
|
||||||
|
|
||||||
|
//Address
|
||||||
|
var addr AddressModel
|
||||||
|
addr.Hash = outputAddr
|
||||||
|
addr.InBittrex = false
|
||||||
|
saveAddress(addr)
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
for _, Vi := range tx.Vin {
|
for _, Vi := range blockTx.Vin {
|
||||||
th, err := chainhash.NewHashFromStr(Vi.Txid)
|
th, err := chainhash.NewHashFromStr(Vi.Txid)
|
||||||
check(err)
|
check(err)
|
||||||
txVi, err := client.GetRawTransactionVerbose(th)
|
txVi, err := client.GetRawTransactionVerbose(th)
|
||||||
check(err)
|
check(err)
|
||||||
if len(txVi.Vout[Vi.Vout].ScriptPubKey.Addresses) > 0 {
|
if len(txVi.Vout[Vi.Vout].ScriptPubKey.Addresses) > 0 {
|
||||||
|
//add tx to newBlock
|
||||||
|
newBlock.Tx = append(newBlock.Tx, blockTx.Txid)
|
||||||
|
|
||||||
|
//Tx save
|
||||||
|
var newTx TxModel
|
||||||
|
newTx.Hex = blockTx.Hex
|
||||||
|
newTx.Txid = blockTx.Txid
|
||||||
|
newTx.Hash = blockTx.Hash
|
||||||
|
newTx.BlockHash = block.Hash
|
||||||
|
newTx.BlockHeight = strconv.FormatInt(block.Height, 10)
|
||||||
|
newTx.Time = blockTx.Time
|
||||||
for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
|
for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
|
||||||
originAddresses = append(originAddresses, originAddr)
|
originAddresses = append(originAddresses, originAddr)
|
||||||
|
|
||||||
|
newTx.From = originAddr
|
||||||
|
|
||||||
var n1 NodeModel
|
var n1 NodeModel
|
||||||
n1.Id = originAddr
|
n1.Id = originAddr
|
||||||
n1.Label = originAddr
|
n1.Label = originAddr
|
||||||
@@ -91,12 +120,18 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
n1.Type = "address"
|
n1.Type = "address"
|
||||||
saveNode(nodeCollection, n1)
|
saveNode(nodeCollection, n1)
|
||||||
|
|
||||||
|
//Address
|
||||||
|
var addr AddressModel
|
||||||
|
addr.Hash = originAddr
|
||||||
|
addr.InBittrex = false
|
||||||
|
saveAddress(addr)
|
||||||
|
|
||||||
for k, outputAddr := range outputAddresses {
|
for k, outputAddr := range outputAddresses {
|
||||||
var eIn EdgeModel
|
var eIn EdgeModel
|
||||||
eIn.From = originAddr
|
eIn.From = originAddr
|
||||||
eIn.To = txHash
|
eIn.To = txHash
|
||||||
eIn.Label = txVi.Vout[Vi.Vout].Value
|
eIn.Label = txVi.Vout[Vi.Vout].Value
|
||||||
eIn.Txid = tx.Txid
|
eIn.Txid = blockTx.Txid
|
||||||
eIn.Arrows = "to"
|
eIn.Arrows = "to"
|
||||||
eIn.BlockHeight = block.Height
|
eIn.BlockHeight = block.Height
|
||||||
saveEdge(edgeCollection, eIn)
|
saveEdge(edgeCollection, eIn)
|
||||||
@@ -105,7 +140,7 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
eOut.From = txHash
|
eOut.From = txHash
|
||||||
eOut.To = outputAddr
|
eOut.To = outputAddr
|
||||||
eOut.Label = outputAmount[k]
|
eOut.Label = outputAmount[k]
|
||||||
eOut.Txid = tx.Txid
|
eOut.Txid = blockTx.Txid
|
||||||
eOut.Arrows = "to"
|
eOut.Arrows = "to"
|
||||||
eOut.BlockHeight = block.Height
|
eOut.BlockHeight = block.Height
|
||||||
saveEdge(edgeCollection, eOut)
|
saveEdge(edgeCollection, eOut)
|
||||||
@@ -113,9 +148,13 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
//date analysis
|
//date analysis
|
||||||
//dateAnalysis(e, tx.Time)
|
//dateAnalysis(e, tx.Time)
|
||||||
//hour analysis
|
//hour analysis
|
||||||
hourAnalysis(eIn, tx.Time)
|
hourAnalysis(eIn, blockTx.Time)
|
||||||
|
|
||||||
|
newTx.To = outputAddr
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
saveTx(newTx)
|
||||||
} else {
|
} else {
|
||||||
originAddresses = append(originAddresses, "origin")
|
originAddresses = append(originAddresses, "origin")
|
||||||
}
|
}
|
||||||
@@ -127,6 +166,7 @@ func explore(client *btcrpcclient.Client, blockHash string) {
|
|||||||
fmt.Println(len(outputAddresses))
|
fmt.Println(len(outputAddresses))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
saveBlock(newBlock)
|
||||||
}
|
}
|
||||||
//set the next block
|
//set the next block
|
||||||
blockHash = block.NextHash
|
blockHash = block.NextHash
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ func ipFilter(w http.ResponseWriter, r *http.Request) {
|
|||||||
var err error
|
var err error
|
||||||
fmt.Println(r.RemoteAddr)
|
fmt.Println(r.RemoteAddr)
|
||||||
reqIP := strings.Split(r.RemoteAddr, ":")[0]
|
reqIP := strings.Split(r.RemoteAddr, ":")[0]
|
||||||
for _, ip := range serverConfig.BlockedIPs {
|
for _, ip := range config.Server.BlockedIPs {
|
||||||
if reqIP == ip {
|
if reqIP == ip {
|
||||||
err = errors.New("ip not allowed to post images")
|
err = errors.New("ip not allowed to post images")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ip := range serverConfig.AllowedIPs {
|
for _, ip := range config.Server.AllowedIPs {
|
||||||
if reqIP != ip {
|
if reqIP != ip {
|
||||||
err = errors.New("ip not allowed to post images")
|
err = errors.New("ip not allowed to post images")
|
||||||
}
|
}
|
||||||
|
|||||||
20
main.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
mgo "gopkg.in/mgo.v2"
|
mgo "gopkg.in/mgo.v2"
|
||||||
|
|
||||||
@@ -13,6 +14,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var blockCollection *mgo.Collection
|
var blockCollection *mgo.Collection
|
||||||
|
var txCollection *mgo.Collection
|
||||||
|
var addressCollection *mgo.Collection
|
||||||
var nodeCollection *mgo.Collection
|
var nodeCollection *mgo.Collection
|
||||||
var edgeCollection *mgo.Collection
|
var edgeCollection *mgo.Collection
|
||||||
var dateCountCollection *mgo.Collection
|
var dateCountCollection *mgo.Collection
|
||||||
@@ -24,10 +27,12 @@ func main() {
|
|||||||
readConfig("config.json")
|
readConfig("config.json")
|
||||||
|
|
||||||
//connect with mongodb
|
//connect with mongodb
|
||||||
readMongodbConfig("./mongodbConfig.json")
|
//readMongodbConfig("./mongodbConfig.json")
|
||||||
session, err := getSession()
|
session, err := getSession()
|
||||||
check(err)
|
check(err)
|
||||||
blockCollection = getCollection(session, "blocks")
|
blockCollection = getCollection(session, "blocks")
|
||||||
|
txCollection = getCollection(session, "txs")
|
||||||
|
addressCollection = getCollection(session, "address")
|
||||||
nodeCollection = getCollection(session, "nodes")
|
nodeCollection = getCollection(session, "nodes")
|
||||||
edgeCollection = getCollection(session, "edges")
|
edgeCollection = getCollection(session, "edges")
|
||||||
dateCountCollection = getCollection(session, "dateCounts")
|
dateCountCollection = getCollection(session, "dateCounts")
|
||||||
@@ -57,7 +62,10 @@ func main() {
|
|||||||
log.Printf("%s: %s", label, amount)
|
log.Printf("%s: %s", label, amount)
|
||||||
}
|
}
|
||||||
color.Blue("starting to explore blockchain")
|
color.Blue("starting to explore blockchain")
|
||||||
|
start := time.Now()
|
||||||
explore(client, config.GenesisBlock)
|
explore(client, config.GenesisBlock)
|
||||||
|
log.Println("blockchain exploration finished, time:")
|
||||||
|
log.Println(time.Since(start))
|
||||||
|
|
||||||
// Get the current block count.
|
// Get the current block count.
|
||||||
blockCount, err := client.GetBlockCount()
|
blockCount, err := client.GetBlockCount()
|
||||||
@@ -71,22 +79,22 @@ func main() {
|
|||||||
go webserver()
|
go webserver()
|
||||||
|
|
||||||
//http server start
|
//http server start
|
||||||
readServerConfig("./serverConfig.json")
|
//readServerConfig("./serverConfig.json")
|
||||||
log.Println("server running")
|
log.Println("server running")
|
||||||
log.Print("port: ")
|
log.Print("port: ")
|
||||||
log.Println(serverConfig.ServerPort)
|
log.Println(config.Server.ServerPort)
|
||||||
router := NewRouter()
|
router := NewRouter()
|
||||||
|
|
||||||
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"})
|
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"})
|
||||||
originsOk := handlers.AllowedOrigins([]string{"*"})
|
originsOk := handlers.AllowedOrigins([]string{"*"})
|
||||||
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
|
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
|
||||||
log.Fatal(http.ListenAndServe(":"+serverConfig.ServerPort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
|
log.Fatal(http.ListenAndServe(":"+config.Server.ServerPort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
|
||||||
//log.Fatal(http.ListenAndServe(":"+serverConfig.ServerPort, router))
|
//log.Fatal(http.ListenAndServe(":"+serverConfig.ServerPort, router))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func webserver() {
|
func webserver() {
|
||||||
log.Println("webserver in port " + serverConfig.WebServerPort)
|
log.Println("webserver in port " + config.Server.WebServerPort)
|
||||||
http.Handle("/", http.FileServer(http.Dir("./web")))
|
http.Handle("/", http.FileServer(http.Dir("./web")))
|
||||||
http.ListenAndServe(":"+serverConfig.WebServerPort, nil)
|
http.ListenAndServe(":"+config.Server.WebServerPort, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,44 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
type AddressModel struct {
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
InBittrex bool `json:"inbittrex"`
|
||||||
|
}
|
||||||
|
type DateModel struct {
|
||||||
|
Hour string `json:"hour"`
|
||||||
|
Day string `json:"day"`
|
||||||
|
Month string `json:"month"`
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
BlockHash string `json:"blockhash"`
|
||||||
|
BlockHeight string `json:"blockheight"`
|
||||||
|
}
|
||||||
type TxModel struct {
|
type TxModel struct {
|
||||||
Txid string
|
Hex string `json:"hex"`
|
||||||
From string
|
Txid string `json:"txid"`
|
||||||
To string
|
Hash string `json:"hash"`
|
||||||
Amount float64
|
From string `json:"from"` //hash of address
|
||||||
|
To string `json:"to"` //hash of address
|
||||||
|
Amount float64 `json:"amount"`
|
||||||
|
BlockHash string `json:"blockhash"`
|
||||||
|
BlockHeight string `json:"blockheight"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
DateF string `json:"datef"` //date formated
|
||||||
|
Date DateModel
|
||||||
}
|
}
|
||||||
type BlockModel struct {
|
type BlockModel struct {
|
||||||
Hash string
|
Hash string `json:"hash"`
|
||||||
Height int64
|
Confirmations uint64 `json:"confirmations"`
|
||||||
Confirmations uint64
|
Size int32 `json:"size"`
|
||||||
Amount float64
|
Height int64 `json:"height"`
|
||||||
Fee float64
|
//Amount float64 `json:"amount"`
|
||||||
Tx []TxModel
|
//Fee float64 `json:"fee"`
|
||||||
|
Tx []string `json:"txid"` //txid of the TxModel
|
||||||
|
PreviousHash string `json:"previoushash"`
|
||||||
|
NextHash string `json:"nexthash"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
DateF string `json:"datef"` //date formated
|
||||||
|
Date DateModel
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeModel struct {
|
type NodeModel struct {
|
||||||
|
|||||||
@@ -1,34 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
mgo "gopkg.in/mgo.v2"
|
mgo "gopkg.in/mgo.v2"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
//MongoConfig stores the configuration of mongodb to connect
|
|
||||||
type MongoConfig struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Database string `json:"database"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var mongoConfig MongoConfig
|
|
||||||
|
|
||||||
func readMongodbConfig(path string) {
|
|
||||||
file, e := ioutil.ReadFile(path)
|
|
||||||
if e != nil {
|
|
||||||
fmt.Println("error:", e)
|
|
||||||
}
|
|
||||||
content := string(file)
|
|
||||||
json.Unmarshal([]byte(content), &mongoConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSession() (*mgo.Session, error) {
|
func getSession() (*mgo.Session, error) {
|
||||||
session, err := mgo.Dial("mongodb://" + mongoConfig.IP)
|
session, err := mgo.Dial("mongodb://" + config.Mongodb.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -44,9 +24,11 @@ func getSession() (*mgo.Session, error) {
|
|||||||
}
|
}
|
||||||
func getCollection(session *mgo.Session, collection string) *mgo.Collection {
|
func getCollection(session *mgo.Session, collection string) *mgo.Collection {
|
||||||
|
|
||||||
c := session.DB(mongoConfig.Database).C(collection)
|
c := session.DB(config.Mongodb.Database).C(collection)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func saveBlock(c *mgo.Collection, block BlockModel) {
|
func saveBlock(c *mgo.Collection, block BlockModel) {
|
||||||
//first, check if the item already exists
|
//first, check if the item already exists
|
||||||
result := BlockModel{}
|
result := BlockModel{}
|
||||||
@@ -63,6 +45,7 @@ func saveBlock(c *mgo.Collection, block BlockModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func getAllNodes() ([]NodeModel, error) {
|
func getAllNodes() ([]NodeModel, error) {
|
||||||
result := []NodeModel{}
|
result := []NodeModel{}
|
||||||
@@ -126,3 +109,34 @@ func edgeInEdges(edges []EdgeModel, edge EdgeModel) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func saveAddress(address AddressModel) {
|
||||||
|
|
||||||
|
result := AddressModel{}
|
||||||
|
err := addressCollection.Find(bson.M{"hash": address.Hash}).One(&result)
|
||||||
|
if err != nil {
|
||||||
|
//address not found, so let's add a new entry
|
||||||
|
err = addressCollection.Insert(address)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func saveTx(tx TxModel) {
|
||||||
|
|
||||||
|
result := TxModel{}
|
||||||
|
err := txCollection.Find(bson.M{"txid": tx.Txid}).One(&result)
|
||||||
|
if err != nil {
|
||||||
|
//tx not found, so let's add a new entry
|
||||||
|
err = txCollection.Insert(tx)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveBlock(block BlockModel) {
|
||||||
|
|
||||||
|
result := BlockModel{}
|
||||||
|
err := blockCollection.Find(bson.M{"hash": block.Hash}).One(&result)
|
||||||
|
if err != nil {
|
||||||
|
//block not found, so let's add a new entry
|
||||||
|
err = blockCollection.Insert(block)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,14 +5,32 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//MongoConfig stores the configuration of mongodb to connect
|
||||||
|
type MongoConfig struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//ServerConfig reads the server configuration
|
||||||
|
type ServerConfig struct {
|
||||||
|
ServerIP string `json:"serverIP"`
|
||||||
|
ServerPort string `json:"serverPort"`
|
||||||
|
WebServerPort string `json:"webserverPort"`
|
||||||
|
AllowedIPs []string `json:"allowedIPs"`
|
||||||
|
BlockedIPs []string `json:"blockedIPs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Config reads the config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
Pass string `json:"pass"`
|
Pass string `json:"pass"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port string `json:"port"`
|
Port string `json:"port"`
|
||||||
GenesisTx string `json:"genesisTx"`
|
GenesisTx string `json:"genesisTx"`
|
||||||
GenesisBlock string `json:"genesisBlock"`
|
GenesisBlock string `json:"genesisBlock"`
|
||||||
StartFromBlock int64 `json:"startFromBlock"`
|
StartFromBlock int64 `json:"startFromBlock"`
|
||||||
|
Server ServerConfig `json:"server"`
|
||||||
|
Mongodb MongoConfig `json:"mongodb"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var config Config
|
var config Config
|
||||||
@@ -23,3 +41,27 @@ func readConfig(path string) {
|
|||||||
content := string(file)
|
content := string(file)
|
||||||
json.Unmarshal([]byte(content), &config)
|
json.Unmarshal([]byte(content), &config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
var mongoConfig MongoConfig
|
||||||
|
|
||||||
|
func readMongodbConfig(path string) {
|
||||||
|
file, e := ioutil.ReadFile(path)
|
||||||
|
if e != nil {
|
||||||
|
fmt.Println("error:", e)
|
||||||
|
}
|
||||||
|
content := string(file)
|
||||||
|
json.Unmarshal([]byte(content), &mongoConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverConfig ServerConfig
|
||||||
|
|
||||||
|
func readServerConfig(path string) {
|
||||||
|
file, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error: ", err)
|
||||||
|
}
|
||||||
|
content := string(file)
|
||||||
|
json.Unmarshal([]byte(content), &serverConfig)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
@@ -1,9 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@@ -18,26 +15,6 @@ type Route struct {
|
|||||||
HandlerFunc http.HandlerFunc
|
HandlerFunc http.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
//server config
|
|
||||||
type ServerConfig struct {
|
|
||||||
ServerIP string `json:"serverIP"`
|
|
||||||
ServerPort string `json:"serverPort"`
|
|
||||||
WebServerPort string `json:"webserverPort"`
|
|
||||||
AllowedIPs []string `json:"allowedIPs"`
|
|
||||||
BlockedIPs []string `json:"blockedIPs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var serverConfig ServerConfig
|
|
||||||
|
|
||||||
func readServerConfig(path string) {
|
|
||||||
file, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("error: ", err)
|
|
||||||
}
|
|
||||||
content := string(file)
|
|
||||||
json.Unmarshal([]byte(content), &serverConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Logger(inner http.Handler, name string) http.Handler {
|
func Logger(inner http.Handler, name string) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|||||||
@@ -102,25 +102,25 @@ func AllAddresses(w http.ResponseWriter, r *http.Request) {
|
|||||||
func GetLastAddr(w http.ResponseWriter, r *http.Request) {
|
func GetLastAddr(w http.ResponseWriter, r *http.Request) {
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
|
|
||||||
nodes := []NodeModel{}
|
addresses := []AddressModel{}
|
||||||
err := nodeCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&nodes)
|
err := addressCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&addresses)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
//convert []resp struct to json
|
//convert []resp struct to json
|
||||||
jNodes, err := json.Marshal(nodes)
|
jsonResp, err := json.Marshal(addresses)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
fmt.Fprintln(w, string(jNodes))
|
fmt.Fprintln(w, string(jsonResp))
|
||||||
}
|
}
|
||||||
func GetLastTx(w http.ResponseWriter, r *http.Request) {
|
func GetLastTx(w http.ResponseWriter, r *http.Request) {
|
||||||
ipFilter(w, r)
|
ipFilter(w, r)
|
||||||
|
|
||||||
edges := []EdgeModel{}
|
txs := []TxModel{}
|
||||||
err := edgeCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&edges)
|
err := txCollection.Find(bson.M{}).Limit(10).Sort("-$natural").All(&txs)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
//convert []resp struct to json
|
//convert []resp struct to json
|
||||||
jsonData, err := json.Marshal(edges)
|
jsonData, err := json.Marshal(txs)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
fmt.Fprintln(w, string(jsonData))
|
fmt.Fprintln(w, string(jsonData))
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
<h3 class="panel-title">Last addresses used</h3>
|
<h3 class="panel-title">Last addresses used</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body" style="max-height: 300px;overflow-y: scroll;">
|
<div class="panel-body" style="max-height: 300px;overflow-y: scroll;">
|
||||||
<div class="list-group-item" ng-repeat="node in addresses">
|
<div class="list-group-item" ng-repeat="address in addresses">
|
||||||
<div class="row-content">
|
<div class="row-content">
|
||||||
<p class="list-group-item-text">{{node.id}}</p>
|
<p class="list-group-item-text">{{address.hash}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||