diff --git a/dateAnalysis.go b/dateAnalysis.go
new file mode 100644
index 0000000..d633203
--- /dev/null
+++ b/dateAnalysis.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+
+ "gopkg.in/mgo.v2/bson"
+)
+
+func timeToDate(blockTime int64) string {
+ stringTime := strconv.FormatInt(blockTime, 10)
+ i, err := strconv.ParseInt(stringTime, 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ tm := time.Unix(i, 0)
+ fmt.Println(tm)
+ stringDate := tm.String()
+ fmt.Println(stringDate)
+ return stringDate
+}
+func hourAnalysis(e EdgeModel, blockTime int64) {
+ fmt.Println(blockTime)
+ date := timeToDate(blockTime)
+ date_hour := strings.Split(date, " ")[1]
+ hour := strings.Split(date_hour, ":")[0]
+
+ hourCount := HourCountModel{}
+ err := hourCountCollection.Find(bson.M{"hour": hour}).One(&hourCount)
+ if err != nil {
+ //date not yet in DB
+ var hourCount HourCountModel
+ hourCount.Hour = hour
+ hourCount.Count = 1
+ err = hourCountCollection.Insert(hourCount)
+ check(err)
+ } else {
+ hourCount.Count++
+ err = hourCountCollection.Update(bson.M{"hour": hour}, &hourCount)
+ check(err)
+ }
+}
+func dateAnalysis(e EdgeModel, blockTime int64) {
+ fmt.Println(blockTime)
+ date := timeToDate(blockTime)
+
+ dateCount := DateCountModel{}
+ err := dateCountCollection.Find(bson.M{"date": date}).One(&dateCount)
+ if err != nil {
+ //date not yet in DB
+ var dateCount DateCountModel
+ dateCount.Date = date
+ dateCount.Time = blockTime
+ dateCount.Count = 1
+ err = dateCountCollection.Insert(dateCount)
+ check(err)
+ } else {
+ dateCount.Count++
+ err = dateCountCollection.Update(bson.M{"date": date}, &dateCount)
+ check(err)
+ }
+}
diff --git a/exploreBlockchain.go b/exploreBlockchain.go
index 7caf7cc..8057aa9 100644
--- a/exploreBlockchain.go
+++ b/exploreBlockchain.go
@@ -26,80 +26,84 @@ func explore(client *btcrpcclient.Client, blockHash string) {
block, err := client.GetBlockVerbose(bh)
check(err)
- //if len(block.Tx) < 10 {
- for k, txHash := range block.Tx {
- if k > 0 {
- realBlocks++
- fmt.Print("Block Height: ")
- fmt.Print(block.Height)
- fmt.Print(", num of Tx: ")
- fmt.Print(k)
- fmt.Print("/")
- fmt.Println(len(block.Tx) - 1)
+ if block.Height > 160 {
+ for k, txHash := range block.Tx {
+ if k > 0 {
+ realBlocks++
+ fmt.Print("Block Height: ")
+ fmt.Print(block.Height)
+ fmt.Print(", num of Tx: ")
+ fmt.Print(k)
+ fmt.Print("/")
+ fmt.Println(len(block.Tx) - 1)
- th, err := chainhash.NewHashFromStr(txHash)
- check(err)
- tx, err := client.GetRawTransactionVerbose(th)
- check(err)
-
- var originAddresses []string
- var outputAddresses []string
- for _, Vo := range tx.Vout {
- //if Vo.Value > 0 {
- for _, outputAddr := range Vo.ScriptPubKey.Addresses {
- outputAddresses = append(outputAddresses, outputAddr)
- var n2 NodeModel
- n2.Id = outputAddr
- n2.Label = outputAddr
- n2.Title = outputAddr
- n2.Group = strconv.FormatInt(block.Height, 10)
- n2.Value = 1
- n2.Shape = "dot"
- saveNode(nodeCollection, n2)
- }
- //}
- }
- for _, Vi := range tx.Vin {
- th, err := chainhash.NewHashFromStr(Vi.Txid)
+ th, err := chainhash.NewHashFromStr(txHash)
check(err)
- txVi, err := client.GetRawTransactionVerbose(th)
+ tx, err := client.GetRawTransactionVerbose(th)
check(err)
- if len(txVi.Vout[Vi.Vout].ScriptPubKey.Addresses) > 0 {
- for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
- originAddresses = append(originAddresses, originAddr)
- var n1 NodeModel
- n1.Id = originAddr
- n1.Label = originAddr
- n1.Title = originAddr
- n1.Group = string(block.Height)
- n1.Value = 1
- n1.Shape = "dot"
- saveNode(nodeCollection, n1)
- for _, outputAddr := range outputAddresses {
- var e EdgeModel
- e.From = originAddr
- e.To = outputAddr
- e.Label = txVi.Vout[Vi.Vout].Value
- e.Txid = tx.Txid
- e.Arrows = "to"
- e.BlockHeight = block.Height
- saveEdge(edgeCollection, e)
- //fmt.Println(e)
- }
+ var originAddresses []string
+ var outputAddresses []string
+ for _, Vo := range tx.Vout {
+ //if Vo.Value > 0 {
+ for _, outputAddr := range Vo.ScriptPubKey.Addresses {
+ outputAddresses = append(outputAddresses, outputAddr)
+ var n2 NodeModel
+ n2.Id = outputAddr
+ n2.Label = outputAddr
+ n2.Title = outputAddr
+ n2.Group = strconv.FormatInt(block.Height, 10)
+ n2.Value = 1
+ n2.Shape = "dot"
+ saveNode(nodeCollection, n2)
}
- } else {
- originAddresses = append(originAddresses, "origin")
+ //}
}
+ for _, Vi := range tx.Vin {
+ th, err := chainhash.NewHashFromStr(Vi.Txid)
+ check(err)
+ txVi, err := client.GetRawTransactionVerbose(th)
+ check(err)
+ if len(txVi.Vout[Vi.Vout].ScriptPubKey.Addresses) > 0 {
+ for _, originAddr := range txVi.Vout[Vi.Vout].ScriptPubKey.Addresses {
+ originAddresses = append(originAddresses, originAddr)
+ var n1 NodeModel
+ n1.Id = originAddr
+ n1.Label = originAddr
+ n1.Title = originAddr
+ n1.Group = string(block.Height)
+ n1.Value = 1
+ n1.Shape = "dot"
+ saveNode(nodeCollection, n1)
+
+ for _, outputAddr := range outputAddresses {
+ var e EdgeModel
+ e.From = originAddr
+ e.To = outputAddr
+ e.Label = txVi.Vout[Vi.Vout].Value
+ e.Txid = tx.Txid
+ e.Arrows = "to"
+ e.BlockHeight = block.Height
+ saveEdge(edgeCollection, e)
+ //date analysis
+ //dateAnalysis(e, tx.Time)
+ //hour analysis
+ hourAnalysis(e, tx.Time)
+ }
+ }
+ } else {
+ originAddresses = append(originAddresses, "origin")
+ }
+
+ }
+ fmt.Print("originAddresses: ")
+ fmt.Println(len(originAddresses))
+ fmt.Print("outputAddresses: ")
+ fmt.Println(len(outputAddresses))
}
- fmt.Print("originAddresses: ")
- fmt.Println(len(originAddresses))
- fmt.Print("outputAddresses: ")
- fmt.Println(len(outputAddresses))
}
}
- //}
//set the next block
blockHash = block.NextHash
}
diff --git a/goBlockchainDataAbalysis.gif b/goBlockchainDataAbalysis.gif
deleted file mode 100644
index e322fc2..0000000
Binary files a/goBlockchainDataAbalysis.gif and /dev/null differ
diff --git a/goBlockchainDataAnalysis04.png b/goBlockchainDataAnalysis04.png
new file mode 100644
index 0000000..a62c4f8
Binary files /dev/null and b/goBlockchainDataAnalysis04.png differ
diff --git a/main.go b/main.go
index a067a59..8b5d156 100644
--- a/main.go
+++ b/main.go
@@ -16,6 +16,8 @@ import (
var blockCollection *mgo.Collection
var nodeCollection *mgo.Collection
var edgeCollection *mgo.Collection
+var dateCountCollection *mgo.Collection
+var hourCountCollection *mgo.Collection
func main() {
//read goBlockchainDataAbalysis config
@@ -28,6 +30,8 @@ func main() {
blockCollection = getCollection(session, "blocks")
nodeCollection = getCollection(session, "nodes")
edgeCollection = getCollection(session, "edges")
+ dateCountCollection = getCollection(session, "dateCounts")
+ hourCountCollection = getCollection(session, "hourCounts")
// create new client instance
client, err := btcrpcclient.New(&btcrpcclient.ConnConfig{
diff --git a/mongoModels.go b/mongoModels.go
index 8964092..c4f79fb 100644
--- a/mongoModels.go
+++ b/mongoModels.go
@@ -53,3 +53,17 @@ type SankeyModel struct {
Nodes []SankeyNodeModel `json:"nodes"`
Links []SankeyLinkModel `json:"links"`
}
+
+type HourCountModel struct {
+ Hour string `json:"hour"`
+ Count int `json:"count"`
+}
+type HourAnalysisResp struct {
+ Labels []string `json:"labels"`
+ Data []int `json:"data"`
+}
+type DateCountModel struct {
+ Time int64 `json:"time"`
+ Date string `json:"date"`
+ Count int `json:"count"`
+}
diff --git a/serverRoutes.go b/serverRoutes.go
index 9987b70..28734ad 100644
--- a/serverRoutes.go
+++ b/serverRoutes.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "sort"
"gopkg.in/mgo.v2/bson"
@@ -43,6 +44,12 @@ var routes = Routes{
"/map",
NetworkMap,
},
+ Route{
+ "GetHourAnalysis",
+ "Get",
+ "/houranalysis",
+ GetHourAnalysis,
+ },
/*
Route{
"SelectItem",
@@ -200,3 +207,26 @@ func SelectItem(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "user: "+userid+", selects item: "+itemid)
}
*/
+func GetHourAnalysis(w http.ResponseWriter, r *http.Request) {
+ ipFilter(w, r)
+
+ hourAnalysis := []HourCountModel{}
+ iter := hourCountCollection.Find(bson.M{}).Limit(10000).Iter()
+ err := iter.All(&hourAnalysis)
+
+ //sort by hour
+ sort.Slice(hourAnalysis, func(i, j int) bool {
+ return hourAnalysis[i].Hour < hourAnalysis[j].Hour
+ })
+
+ var resp HourAnalysisResp
+ for _, d := range hourAnalysis {
+ resp.Labels = append(resp.Labels, d.Hour)
+ resp.Data = append(resp.Data, d.Count)
+ }
+
+ //convert []resp struct to json
+ jsonResp, err := json.Marshal(resp)
+ check(err)
+ fmt.Fprintln(w, string(jsonResp))
+}
diff --git a/web/app.js b/web/app.js
index c940c2b..8b27851 100644
--- a/web/app.js
+++ b/web/app.js
@@ -12,7 +12,8 @@ angular.module('webApp', [
'app.main',
'app.network',
'app.addressNetwork',
- 'app.sankey'
+ 'app.sankey',
+ 'app.dateAnalysis'
]).
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
diff --git a/web/index.html b/web/index.html
index a6d06e4..8fe287d 100644
--- a/web/index.html
+++ b/web/index.html
@@ -95,6 +95,7 @@
+