mirror of https://github.com/CIRCL/AIL-framework
chg: [Correlation UI] btc address: get related transaction input/output
parent
1ae43d5b31
commit
46f6f648a0
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
|
||||
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages/'))
|
||||
import Cryptocurrency
|
||||
|
||||
blockchain_all='https://blockchain.info/rawaddr'
|
||||
|
||||
# pre-alpha script
|
||||
|
||||
# default nb_transactions = 50
|
||||
def get_bitcoin_info(bitcoin_address, nb_transaction=50):
|
||||
dict_btc = {}
|
||||
set_btc_in = set()
|
||||
set_btc_out = set()
|
||||
req = None
|
||||
try:
|
||||
req = requests.get('{}/{}?limit={}'.format(blockchain_all, bitcoin_address, nb_transaction))
|
||||
jreq = req.json()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return dict_btc
|
||||
|
||||
#print(json.dumps(jreq))
|
||||
dict_btc['n_tx'] = jreq['n_tx']
|
||||
dict_btc['total_received'] = float(jreq['total_received'] / 100000000)
|
||||
dict_btc['total_sent'] = float(jreq['total_sent'] / 100000000)
|
||||
dict_btc['final_balance'] = float(jreq['final_balance'] / 100000000)
|
||||
|
||||
for transaction in jreq['txs']:
|
||||
for input in transaction['inputs']:
|
||||
if input['prev_out']['addr'] != bitcoin_address:
|
||||
set_btc_in.add(input['prev_out']['addr'])
|
||||
for output in transaction['out']:
|
||||
if output['addr'] != bitcoin_address:
|
||||
set_btc_out.add(output['addr'])
|
||||
|
||||
dict_btc['btc_in'] = filter_btc_seen(set_btc_in)
|
||||
dict_btc['btc_out'] = filter_btc_seen(set_btc_out)
|
||||
return dict_btc
|
||||
|
||||
# filter btc seen in ail
|
||||
def filter_btc_seen(btc_addr_set):
|
||||
list_seen_btc = []
|
||||
for btc_addr in btc_addr_set:
|
||||
if Cryptocurrency.cryptocurrency._exist_corelation_field('bitcoin', btc_addr):
|
||||
list_seen_btc.append(btc_addr)
|
||||
return list_seen_btc
|
|
@ -18,11 +18,12 @@ import Flask_config
|
|||
|
||||
# Import Role_Manager
|
||||
from Role_Manager import create_user_db, check_password_strength, check_user_role_integrity
|
||||
from Role_Manager import login_admin, login_analyst
|
||||
from Role_Manager import login_admin, login_analyst, login_read_only
|
||||
|
||||
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'lib'))
|
||||
import Correlate_object
|
||||
import Domain
|
||||
import btc_ail
|
||||
|
||||
sys.path.append(os.path.join(os.environ['AIL_BIN'], 'packages'))
|
||||
import Cryptocurrency
|
||||
|
@ -95,11 +96,13 @@ def sanitise_correlation_objects(correlation_objects):
|
|||
else:
|
||||
return all_correlation_objects
|
||||
|
||||
def get_card_metadata(object_type, correlation_id, type_id=None):
|
||||
def get_card_metadata(object_type, correlation_id, type_id=None, expand_card=False):
|
||||
card_dict = {}
|
||||
if object_type == 'cryptocurrency':
|
||||
card_dict["sparkline"] = Cryptocurrency.cryptocurrency.get_list_nb_previous_correlation_object(type_id, correlation_id, 6)
|
||||
card_dict["icon"] = Correlate_object.get_correlation_node_icon(object_type, type_id)
|
||||
if type_id == 'bitcoin' and expand_card:
|
||||
card_dict["related_btc"] = btc_ail.get_bitcoin_info(correlation_id)
|
||||
elif object_type == 'pgp':
|
||||
card_dict["sparkline"] = Pgp.pgp.get_list_nb_previous_correlation_object(type_id, correlation_id, 6)
|
||||
card_dict["icon"] = Correlate_object.get_correlation_node_icon(object_type, type_id)
|
||||
|
@ -118,7 +121,7 @@ def get_card_metadata(object_type, correlation_id, type_id=None):
|
|||
# ============= ROUTES ==============
|
||||
@correlation.route('/correlation/show_correlation', methods=['GET', 'POST']) # GET + POST
|
||||
@login_required
|
||||
@login_analyst
|
||||
@login_read_only
|
||||
def show_correlation():
|
||||
if request.method == 'POST':
|
||||
object_type = request.form.get('object_type')
|
||||
|
@ -168,6 +171,8 @@ def show_correlation():
|
|||
max_nodes = sanitise_nb_max_nodes(request.args.get('max_nodes'))
|
||||
mode = sanitise_graph_mode(request.args.get('mode'))
|
||||
|
||||
expand_card = request.args.get('expand_card')
|
||||
|
||||
correlation_names = sanitise_correlation_names(request.args.get('correlation_names'))
|
||||
correlation_objects = sanitise_correlation_objects(request.args.get('correlation_objects'))
|
||||
|
||||
|
@ -186,13 +191,13 @@ def show_correlation():
|
|||
dict_object["metadata"] = Correlate_object.get_object_metadata(object_type, correlation_id, type_id=type_id)
|
||||
if type_id:
|
||||
dict_object["metadata"]['type_id'] = type_id
|
||||
dict_object["metadata_card"] = get_card_metadata(object_type, correlation_id, type_id=type_id)
|
||||
dict_object["metadata_card"] = get_card_metadata(object_type, correlation_id, type_id=type_id, expand_card=expand_card)
|
||||
return render_template("show_correlation.html", dict_object=dict_object, bootstrap_label=bootstrap_label)
|
||||
|
||||
|
||||
@correlation.route('/correlation/graph_node_json')
|
||||
@login_required
|
||||
@login_analyst
|
||||
@login_read_only
|
||||
def graph_node_json(): # # TODO: use post
|
||||
correlation_id = request.args.get('correlation_id')
|
||||
type_id = request.args.get('type_id')
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
<div class="card my-3">
|
||||
<div class="card-header" style="background-color:#d9edf7;font-size: 15px">
|
||||
<h4 class="text-secondary">{{ dict_object["correlation_id"] }} :</h4>
|
||||
<ul class="list-group mb-2">
|
||||
<li class="list-group-item py-0">
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Object type</th>
|
||||
<th>type</th>
|
||||
<th>First seen</th>
|
||||
<th>Last seen</th>
|
||||
<th>Nb seen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ dict_object["object_type"] }}</td>
|
||||
<td>
|
||||
<svg height="26" width="26">
|
||||
<g class="nodes">
|
||||
<circle cx="13" cy="13" r="13" fill="orange"></circle>
|
||||
<text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="graph_node_icon {{ dict_object["metadata_card"]["icon"]["icon_class"] }}" font-size="16px">{{ dict_object["metadata_card"]["icon"]["icon_text"] }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
{{ dict_object["metadata"]["type_id"] }}
|
||||
</td>
|
||||
<td>{{ dict_object["metadata"]['first_seen'] }}</td>
|
||||
<td>{{ dict_object["metadata"]['last_seen'] }}</td>
|
||||
<td>{{ dict_object["metadata"]['nb_seen'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<div id="sparkline"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{% if dict_object["metadata"]["type_id"] == "bitcoin" %}
|
||||
{% if "related_btc" in dict_object["metadata_card"] %}
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Numbers of transactions</th>
|
||||
<th>Total received</th>
|
||||
<th>Total sent</th>
|
||||
<th>Balance</th>
|
||||
<th>Inputs address seen in AIL</th>
|
||||
<th>Ouputs address seen in AIL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ dict_object["metadata_card"]["related_btc"]["n_tx"] }}</td>
|
||||
<td>{{ dict_object["metadata_card"]["related_btc"]["total_received"] }}</td>
|
||||
<td>{{ dict_object["metadata_card"]["related_btc"]["total_sent"] }}</td>
|
||||
<td>{{ dict_object["metadata_card"]["related_btc"]["final_balance"] }}</td>
|
||||
<td>
|
||||
{% for btc_addr in dict_object["metadata_card"]["related_btc"]["btc_in"] %}
|
||||
<a target="_blank" href="{{ url_for('correlation.show_correlation') }}?object_type=cryptocurrency&type_id=bitcoin&correlation_id={{ btc_addr }}&correlation_objects=paste">{{ btc_addr }}</a>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% for btc_addr in dict_object["metadata_card"]["related_btc"]["btc_out"] %}
|
||||
<a target="_blank" href="{{ url_for('correlation.show_correlation') }}?object_type=cryptocurrency&type_id=bitcoin&correlation_id={{ btc_addr }}&correlation_objects=paste">{{ btc_addr }}</a>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<a class="btn btn-secondary" href="{{ url_for('correlation.show_correlation') }}?object_type=cryptocurrency&type_id=bitcoin&correlation_id={{ dict_object['correlation_id'] }}&expand_card=True&correlation_objects=paste">Expand Bitcoin address</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/d3/sparklines.js')}}"></script>
|
||||
<script>
|
||||
sparkline("sparkline", {{ dict_object["metadata_card"]["sparkline"] }}, {});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function create_line_chart(id, url){
|
||||
|
||||
var width = 900;
|
||||
var height = Math.round(width / 4);
|
||||
|
||||
var margin = {top: 20, right: 55, bottom: 50, left: 40};
|
||||
|
||||
var x = d3.scaleTime().range([0, width]);
|
||||
var y = d3.scaleLinear().rangeRound([height, 0]);
|
||||
|
||||
var xAxis = d3.axisBottom(x);
|
||||
var yAxis = d3.axisLeft(y);
|
||||
|
||||
var parseTime = d3.timeParse("%Y-%m-%d");
|
||||
|
||||
var line = d3.line()
|
||||
.x(function(d) {
|
||||
return x(d.date);
|
||||
}).y(function(d) {
|
||||
return y(d.value);
|
||||
});
|
||||
|
||||
var svg_line = d3.select('#'+id).append('svg')
|
||||
.attr("id", "graph_div")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('transform', "translate("+ margin.left +","+ margin.top +")");
|
||||
|
||||
var div = d3.select('body').append('div')
|
||||
.attr('class', 'tooltip')
|
||||
.style('opacity', 0);
|
||||
|
||||
//add div tooltip
|
||||
|
||||
d3.json(url)
|
||||
.then(function(data){
|
||||
|
||||
data.forEach(function(d) {
|
||||
d.date_label = d.date;
|
||||
d.date = parseTime(d.date);
|
||||
d.value = +d.value;
|
||||
});
|
||||
|
||||
// fit the data
|
||||
x.domain(d3.extent(data, function(d) { return d.date; }));
|
||||
//x.domain(data.map(function (d) { return d.date; })); //E
|
||||
y.domain([0, d3.max(data, function(d){ return d.value ; })]);
|
||||
|
||||
//line
|
||||
svg_line.append("path")
|
||||
.data([data])
|
||||
.attr("class", "line_graph")
|
||||
.attr("d", line);
|
||||
|
||||
// add X axis
|
||||
svg_line.append("g")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll("text")
|
||||
.style("text-anchor", "end")
|
||||
.attr("transform", "rotate(-45)" );
|
||||
|
||||
// Add the Y Axis
|
||||
svg_line.append("g")
|
||||
.call(d3.axisLeft(y));
|
||||
|
||||
//add a dot circle
|
||||
svg_line.selectAll('dot')
|
||||
.data(data).enter()
|
||||
.append('circle')
|
||||
.attr('r', 2)
|
||||
.attr('cx', function(d) { return x(d.date); })
|
||||
.attr('cy', function(d) { return y(d.value); })
|
||||
|
||||
.on('mouseover', function(d) {
|
||||
div.transition().style('opacity', .9);
|
||||
div.html('' + d.date_label+ '<br/>' + d.value).style('left', (d3.event.pageX) + 'px')
|
||||
.style("left", (d3.event.pageX) + "px")
|
||||
.style("top", (d3.event.pageY - 28) + "px");
|
||||
})
|
||||
.on('mouseout', function(d)
|
||||
{
|
||||
div.transition().style('opacity', 0);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -90,8 +90,10 @@
|
|||
|
||||
<div class="col-12 col-lg-10" id="core_content">
|
||||
|
||||
{% if dict_object["object_type"] in ["pgp", "cryptocurrency"] %}
|
||||
{% if dict_object["object_type"] == "pgp" %}
|
||||
{% include 'correlation/metadata_card_pgp.html' %}
|
||||
{% elif dict_object["object_type"] == "cryptocurrency" %}
|
||||
{% include 'correlation/metadata_card_cryptocurrency.html' %}
|
||||
{% elif dict_object["object_type"] == "decoded" %}
|
||||
{% include 'correlation/metadata_card_decoded.html' %}
|
||||
{% elif dict_object["object_type"] == "domain" %}
|
||||
|
|
Loading…
Reference in New Issue