Last active
August 29, 2015 14:01
-
-
Save Abstrct/e77e51f9283b9284b3cf to your computer and use it in GitHub Desktop.
Copy contents of altcoin defcoind to a postgres database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
WARNING - I think this goes without saying for random gists you find on the internet, but you | |
probably shouldn't use this in production. | |
For every altcoin you want to store, create this schema: | |
CREATE SCHEMA altcoin; | |
CREATE TABLE altcoin.block ( | |
hash character varying PRIMARY KEY, | |
details json | |
); | |
CREATE TABLE altcoin.transaction ( | |
hash character varying PRIMARY KEY, | |
block_hash character varying, | |
details json, | |
status character varying | |
); | |
Todo: | |
Validate | |
Missing Blocks | |
Incomplete Blocks (Missing Transactions) | |
=end | |
require 'net/http' | |
require 'uri' | |
require 'json' | |
require 'pg' | |
$altcoin = 'defcoin' | |
$rpc_url = 'http://user:password@127.0.0.1:1338' | |
$db_url = 'host=127.0.0.1 dbname=pgcoin' | |
# This number should not be higher than the number of connections allowed by postgres | |
$max_threads = 90 | |
# This class is just a copy from the Bitcoin class shared here: https://en.bitcoin.it/wiki/API_reference_(JSON-RPC) | |
class CoinRPC | |
def initialize(service_url) | |
@uri = URI.parse(service_url) | |
end | |
def method_missing(name, *args) | |
post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json | |
resp = JSON.parse( http_post_request(post_body) ) | |
raise JSONRPCError, resp['error'] if resp['error'] | |
resp['result'] | |
end | |
def http_post_request(post_body) | |
http = Net::HTTP.new(@uri.host, @uri.port) | |
request = Net::HTTP::Post.new(@uri.request_uri) | |
request.basic_auth @uri.user, @uri.password | |
request.content_type = 'application/json' | |
request.body = post_body | |
http.request(request).body | |
end | |
class JSONRPCError < RuntimeError; end | |
end | |
def insertBlock block | |
conn = PG.connect($db_url) | |
conn.prepare('InsertBlock', 'insert into defcoin.block (hash, details) values ($1, $2)') | |
conn.prepare('InsertGenesisTX', 'insert into defcoin.transaction (hash, block_hash) values ($1, $2)') | |
conn.prepare('InsertTX', 'insert into defcoin.transaction (hash, block_hash, details) values ($1, $2, $3)') | |
conn.exec_prepared('InsertBlock', [ block["hash"], JSON.generate(block) ]) | |
block["tx"].each do |tx_hash| | |
if block["height"] == 0 | |
conn.exec_prepared('InsertGenesisTX', [ tx_hash, block["hash"] ]) | |
else | |
t = CoinRPC.new($rpc_url) | |
transaction = t.decoderawtransaction(t.getrawtransaction(tx_hash)) | |
conn.exec_prepared('InsertTX', [ transaction["txid"], block["hash"], JSON.generate(transaction) ]) | |
end | |
end | |
conn.finish | |
Thread.exit | |
end | |
def getLastSyncedBlock | |
conn = PG.connect($db_url) | |
res = conn.exec('SELECT details->>\'hash\' as h from defcoin.block order by (details->>\'height\')::integer DESC LIMIT 1 ') | |
unless res.cmd_tuples() == 0 | |
lastBlockHash = res[0]['h'] | |
end | |
conn.finish | |
lastBlockHash | |
end | |
if $0 == __FILE__ | |
h = CoinRPC.new($rpc_url) | |
p 'Checking for last stored block' | |
startingBlock = getLastSyncedBlock() | |
if startingBlock.nil? | |
p 'Could not find a block, starting at the Genesis' | |
block = h.getblock(h.getblockhash(0)) | |
p block["hash"] | |
Thread.new{insertBlock(block)} | |
else | |
p startingBlock | |
block = h.getblock(startingBlock) | |
p 'Next Hash Found ' + block["hash"] | |
end | |
nextBlockHash = block["nextblockhash"] | |
while true | |
if Thread.list.count < $max_threads | |
begin | |
while nextBlockHash.nil? | |
p "Up to date, sleeping" | |
p block["hash"] | |
sleep 60 | |
block = h.getblock(block["hash"]) | |
nextBlockHash = block["nextblockhash"] | |
end | |
block = h.getblock(nextBlockHash) | |
nextBlockHash = block["nextblockhash"] | |
Thread.new{insertBlock(block)} | |
rescue | |
p nextBlockHash | |
end | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment