Add Bitcoin network listener to a SON plugin (#196)
* Add Bitcoin network listener to a SON plugin * Add default parameters for Peerplays Bitcoin test node * Add Bitcoin block processing * Update source code to last designs * Set default parameters for peerplays_sidechain plugin to Bitcoin test server * WIP: Some Bitcoin transaction processing
This commit is contained in:
parent
76b95729e1
commit
749fc2f330
13 changed files with 1137 additions and 19 deletions
|
|
@ -22,6 +22,7 @@ RUN \
|
|||
libreadline-dev \
|
||||
libssl-dev \
|
||||
libtool \
|
||||
libzmq3-dev \
|
||||
locales \
|
||||
ntp \
|
||||
pkg-config \
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ This is a quick introduction to get new developers and witnesses up to speed on
|
|||
The following dependencies were necessary for a clean install of Ubuntu 18.04 LTS:
|
||||
|
||||
```
|
||||
sudo apt-get install gcc-5 g++-5 cmake make libbz2-dev\
|
||||
libdb++-dev libdb-dev libssl-dev openssl libreadline-dev\
|
||||
autoconf libtool git
|
||||
sudo apt-get install autoconf bash build-essential ca-certificates cmake \
|
||||
doxygen git graphviz libbz2-dev libcurl4-openssl-dev libncurses-dev \
|
||||
libreadline-dev libssl-dev libtool libzmq3-dev locales ntp pkg-config \
|
||||
wget
|
||||
```
|
||||
## Build Boost 1.67.0
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ file(GLOB HEADERS "include/graphene/peerplays_sidechain/*.hpp")
|
|||
|
||||
add_library( peerplays_sidechain
|
||||
peerplays_sidechain_plugin.cpp
|
||||
sidechain_net_manager.cpp
|
||||
sidechain_net_handler.cpp
|
||||
sidechain_net_handler_bitcoin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( peerplays_sidechain graphene_chain graphene_app )
|
||||
target_link_libraries( peerplays_sidechain graphene_chain graphene_app fc zmq )
|
||||
target_include_directories( peerplays_sidechain
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
391
libraries/plugins/peerplays_sidechain/addresses.txt
Normal file
391
libraries/plugins/peerplays_sidechain/addresses.txt
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
2N5aFW5WFaYZLuJWx9RGziHBdEMj9Zf8s3J
|
||||
{
|
||||
"address": "2N5aFW5WFaYZLuJWx9RGziHBdEMj9Zf8s3J",
|
||||
"scriptPubKey": "a914873aad1ecf7510c80b83d8ca94d21432dc71b88787",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/2']0368dc31b2b547c74f52abfc67c7fc768c68115d8ab96430d9bb4996fa660121cd))#7s0qfnvz",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "00141d30ac0c47f7b32460265daf49c5925236f5882d",
|
||||
"pubkey": "0368dc31b2b547c74f52abfc67c7fc768c68115d8ab96430d9bb4996fa660121cd",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "1d30ac0c47f7b32460265daf49c5925236f5882d",
|
||||
"pubkey": "0368dc31b2b547c74f52abfc67c7fc768c68115d8ab96430d9bb4996fa660121cd",
|
||||
"address": "bcrt1qr5c2crz877ejgcpxtkh5n3vj2gm0tzpdqrw3n0",
|
||||
"scriptPubKey": "00141d30ac0c47f7b32460265daf49c5925236f5882d"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/2'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2MxAnE469fhhdvUqUB7daU997VSearb2mn7
|
||||
{
|
||||
"address": "2MxAnE469fhhdvUqUB7daU997VSearb2mn7",
|
||||
"scriptPubKey": "a914360175a50918495a20573aed68d506a790420fe587",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/3']02b510a452d6e80f943e4cc85af5cad6c528bda87fc92b821dd246a1a76c175b0d))#p3st4e4e",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "00146c1c0571f3132eb0702f487123d2026495592830",
|
||||
"pubkey": "02b510a452d6e80f943e4cc85af5cad6c528bda87fc92b821dd246a1a76c175b0d",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "6c1c0571f3132eb0702f487123d2026495592830",
|
||||
"pubkey": "02b510a452d6e80f943e4cc85af5cad6c528bda87fc92b821dd246a1a76c175b0d",
|
||||
"address": "bcrt1qdswq2u0nzvhtqup0fpcj85szvj24j2psgfwy6w",
|
||||
"scriptPubKey": "00146c1c0571f3132eb0702f487123d2026495592830"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/3'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2NAYptFvTU8vJ1pC7CxvVA9R7D3NdBJHpwL
|
||||
{
|
||||
"address": "2NAYptFvTU8vJ1pC7CxvVA9R7D3NdBJHpwL",
|
||||
"scriptPubKey": "a914bdce56e7f2fc04614c0f6f4d1d59fff63b0b73f187",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/4']020d771492947feb54abbcbc5f5e86ef26df3747c377573c709507a47f10636462))#3r63c8fu",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "00146abd0d5f055df80b41bc6449328eda09f61a2be3",
|
||||
"pubkey": "020d771492947feb54abbcbc5f5e86ef26df3747c377573c709507a47f10636462",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "6abd0d5f055df80b41bc6449328eda09f61a2be3",
|
||||
"pubkey": "020d771492947feb54abbcbc5f5e86ef26df3747c377573c709507a47f10636462",
|
||||
"address": "bcrt1qd27s6hc9thuqksduv3yn9rk6p8mp52lr2e846e",
|
||||
"scriptPubKey": "00146abd0d5f055df80b41bc6449328eda09f61a2be3"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/4'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2N9zPaLDfaJazUmVfr3wgn8BK75tid2kkzR
|
||||
{
|
||||
"address": "2N9zPaLDfaJazUmVfr3wgn8BK75tid2kkzR",
|
||||
"scriptPubKey": "a914b7abe6d957106da3a21782eea1164f4964b521ba87",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/5']03585ae695cfbbc8e1a93feeb6438c62d744b2581ba36a1e5ca780edd35aedb8ce))#e3sfze3l",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "00147a4fd72ff8e192004c70d8139b4ca53e1467d8c8",
|
||||
"pubkey": "03585ae695cfbbc8e1a93feeb6438c62d744b2581ba36a1e5ca780edd35aedb8ce",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "7a4fd72ff8e192004c70d8139b4ca53e1467d8c8",
|
||||
"pubkey": "03585ae695cfbbc8e1a93feeb6438c62d744b2581ba36a1e5ca780edd35aedb8ce",
|
||||
"address": "bcrt1q0f8awtlcuxfqqnrsmqfekn998c2x0kxgf4t7dm",
|
||||
"scriptPubKey": "00147a4fd72ff8e192004c70d8139b4ca53e1467d8c8"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/5'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2NDN7cDH3E57E1B8TwTYvBgF7CndL4FTBPL
|
||||
{
|
||||
"address": "2NDN7cDH3E57E1B8TwTYvBgF7CndL4FTBPL",
|
||||
"scriptPubKey": "a914dcb019e8330b4fffc50ba22bbf90215922a1379787",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/6']028c78c069d3d6eeb73373eb54edfa61f2e974c01c21b979b0b3f7058805b95013))#3326m2za",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "0014ccd3dee026a1d641352f5b8c7d72805d75fd0652",
|
||||
"pubkey": "028c78c069d3d6eeb73373eb54edfa61f2e974c01c21b979b0b3f7058805b95013",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "ccd3dee026a1d641352f5b8c7d72805d75fd0652",
|
||||
"pubkey": "028c78c069d3d6eeb73373eb54edfa61f2e974c01c21b979b0b3f7058805b95013",
|
||||
"address": "bcrt1qenfaacpx58tyzdf0twx86u5qt46l6pjjef5y7u",
|
||||
"scriptPubKey": "0014ccd3dee026a1d641352f5b8c7d72805d75fd0652"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/6'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2MzEmSiwrRzozxE6gfZ14LAyDHZ4DYP1zVG
|
||||
{
|
||||
"address": "2MzEmSiwrRzozxE6gfZ14LAyDHZ4DYP1zVG",
|
||||
"scriptPubKey": "a9144cb2b8f97d8e7ad5bfb81afd611394387f374ab887",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/7']02f7d952e00d9c262c20c3526d4029245ab890a28dbdcbadfec964578c47719f7b))#7gvhakzu",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "0014e3607a0f745e2fb8b04fe1fa7f078c35009a77c1",
|
||||
"pubkey": "02f7d952e00d9c262c20c3526d4029245ab890a28dbdcbadfec964578c47719f7b",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "e3607a0f745e2fb8b04fe1fa7f078c35009a77c1",
|
||||
"pubkey": "02f7d952e00d9c262c20c3526d4029245ab890a28dbdcbadfec964578c47719f7b",
|
||||
"address": "bcrt1quds85rm5tchm3vz0u8a87puvx5qf5a7pqw8u7l",
|
||||
"scriptPubKey": "0014e3607a0f745e2fb8b04fe1fa7f078c35009a77c1"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/7'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2NDCdm1WVJVCMWJzRaSSy9NDvpNKiqkbrMg
|
||||
{
|
||||
"address": "2NDCdm1WVJVCMWJzRaSSy9NDvpNKiqkbrMg",
|
||||
"scriptPubKey": "a914dae51c6601ef4e05817f67d57d3ac0c8cb64948e87",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/8']03b358000050ffc6318a44d08ee9da9484d5a7d95f509241adf8a52555a0fdde6b))#ckuy6v83",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "001460c1c7776b1f92cd36fe6138b99212ebe6381fe7",
|
||||
"pubkey": "03b358000050ffc6318a44d08ee9da9484d5a7d95f509241adf8a52555a0fdde6b",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "60c1c7776b1f92cd36fe6138b99212ebe6381fe7",
|
||||
"pubkey": "03b358000050ffc6318a44d08ee9da9484d5a7d95f509241adf8a52555a0fdde6b",
|
||||
"address": "bcrt1qvrquwamtr7fv6dh7vyutnysja0nrs8l8vzcnwj",
|
||||
"scriptPubKey": "001460c1c7776b1f92cd36fe6138b99212ebe6381fe7"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/8'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2Mu2iz3Jfqjyv3hBQGQZSGmZGZxhJp91TNX
|
||||
{
|
||||
"address": "2Mu2iz3Jfqjyv3hBQGQZSGmZGZxhJp91TNX",
|
||||
"scriptPubKey": "a91413930c6d40f5f01b169f2fc7884c2b3984ff8a3087",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/9']022752cd513f04f68074bd90a96a82b523a197171376382dedf3413bbdccae0dac))#f8cdpnn9",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "001435b75b7c34a7f908955b8b93aaa677aa47fab2c4",
|
||||
"pubkey": "022752cd513f04f68074bd90a96a82b523a197171376382dedf3413bbdccae0dac",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "35b75b7c34a7f908955b8b93aaa677aa47fab2c4",
|
||||
"pubkey": "022752cd513f04f68074bd90a96a82b523a197171376382dedf3413bbdccae0dac",
|
||||
"address": "bcrt1qxkm4klp55lus392m3wf64fnh4frl4vkyng4ffg",
|
||||
"scriptPubKey": "001435b75b7c34a7f908955b8b93aaa677aa47fab2c4"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/9'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2N1sFbwcn4QVbvjp7yRsN4mg4mBFbvC8gKM
|
||||
{
|
||||
"address": "2N1sFbwcn4QVbvjp7yRsN4mg4mBFbvC8gKM",
|
||||
"scriptPubKey": "a9145e91543069ae37d8bace2f59aade945f5916dc3287",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/10']03114bf9794439221c0f7e910d7b64f242847184381a5ef238cef8d70f8868b4af))#x7xpvc0y",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "0014ceb35b8198b58c76fcc78a70d1d3a2ed1d4325f2",
|
||||
"pubkey": "03114bf9794439221c0f7e910d7b64f242847184381a5ef238cef8d70f8868b4af",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "ceb35b8198b58c76fcc78a70d1d3a2ed1d4325f2",
|
||||
"pubkey": "03114bf9794439221c0f7e910d7b64f242847184381a5ef238cef8d70f8868b4af",
|
||||
"address": "bcrt1qe6e4hqvckkx8dlx83fcdr5aza5w5xf0jd22xet",
|
||||
"scriptPubKey": "0014ceb35b8198b58c76fcc78a70d1d3a2ed1d4325f2"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/10'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2NDmxr6ufBE7Zgdgq9hShF2grx2YPEiTyNy
|
||||
{
|
||||
"address": "2NDmxr6ufBE7Zgdgq9hShF2grx2YPEiTyNy",
|
||||
"scriptPubKey": "a914e132c578bd294a01a472d42b376b29e5ef6678c987",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "sh(wpkh([153472fd/0'/0'/11']02eb6e43fb6ad9f1bf23bf821a25d5a1e84550380e0973ea5b00b087b3e9059c7b))#2janhauz",
|
||||
"iswatchonly": false,
|
||||
"isscript": true,
|
||||
"iswitness": false,
|
||||
"script": "witness_v0_keyhash",
|
||||
"hex": "0014831d63f8d99be71f9b385f2ccc92ab2783da3762",
|
||||
"pubkey": "02eb6e43fb6ad9f1bf23bf821a25d5a1e84550380e0973ea5b00b087b3e9059c7b",
|
||||
"embedded": {
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "831d63f8d99be71f9b385f2ccc92ab2783da3762",
|
||||
"pubkey": "02eb6e43fb6ad9f1bf23bf821a25d5a1e84550380e0973ea5b00b087b3e9059c7b",
|
||||
"address": "bcrt1qsvwk87xen0n3lxectukvey4ty7pa5dmz0yanuv",
|
||||
"scriptPubKey": "0014831d63f8d99be71f9b385f2ccc92ab2783da3762"
|
||||
},
|
||||
"label": "",
|
||||
"ischange": false,
|
||||
"timestamp": 1571845292,
|
||||
"hdkeypath": "m/0'/0'/11'",
|
||||
"hdseedid": "7fc94a298c785719434c63458bb41bc1995a270d",
|
||||
"hdmasterfingerprint": "153472fd",
|
||||
"labels": [
|
||||
{
|
||||
"name": "",
|
||||
"purpose": "receive"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
enum network {
|
||||
bitcoin,
|
||||
//ethereum
|
||||
};
|
||||
|
||||
using bytes = std::vector<char>;
|
||||
|
||||
struct prev_out
|
||||
{
|
||||
bool operator!=( const prev_out& obj ) const
|
||||
{
|
||||
if( this->hash_tx != obj.hash_tx ||
|
||||
this->n_vout != obj.n_vout ||
|
||||
this->amount != obj.amount )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string hash_tx;
|
||||
uint32_t n_vout;
|
||||
uint64_t amount;
|
||||
};
|
||||
|
||||
struct info_for_vin
|
||||
{
|
||||
info_for_vin() = default;
|
||||
|
||||
info_for_vin( const prev_out& _out, const std::string& _address, bytes _script = bytes(), bool _resend = false );
|
||||
|
||||
bool operator!=( const info_for_vin& obj ) const;
|
||||
|
||||
struct comparer {
|
||||
bool operator() ( const info_for_vin& lhs, const info_for_vin& rhs ) const;
|
||||
};
|
||||
|
||||
static uint64_t count_id_info_for_vin;
|
||||
uint64_t id;
|
||||
|
||||
fc::sha256 identifier;
|
||||
|
||||
prev_out out;
|
||||
std::string address;
|
||||
bytes script;
|
||||
|
||||
bool used = false;
|
||||
bool resend = false;
|
||||
};
|
||||
|
||||
struct sidechain_event_data {
|
||||
network sidechain;
|
||||
std::string transaction_id;
|
||||
std::string from;
|
||||
std::string to;
|
||||
int64_t amount;
|
||||
};
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/app/plugin.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
|
||||
#include <fc/thread/future.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
using namespace chain;
|
||||
|
|
@ -30,5 +29,5 @@ class peerplays_sidechain_plugin : public graphene::app::plugin
|
|||
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
||||
};
|
||||
|
||||
} } //graphene::peerplays_sidechain_plugin
|
||||
} } //graphene::peerplays_sidechain
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
class sidechain_net_handler {
|
||||
public:
|
||||
sidechain_net_handler(const boost::program_options::variables_map& options);
|
||||
virtual ~sidechain_net_handler();
|
||||
|
||||
std::vector<std::string> get_user_sidechain_address_mapping();
|
||||
|
||||
protected:
|
||||
graphene::peerplays_sidechain::network network;
|
||||
|
||||
virtual std::string create_multisignature_wallet( const std::vector<std::string> public_keys ) = 0;
|
||||
virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 0;
|
||||
virtual std::string sign_transaction( const std::string& transaction ) = 0;
|
||||
virtual std::string send_transaction( const std::string& transaction ) = 0;
|
||||
|
||||
virtual void handle_event( const std::string& event_data ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <zmq.hpp>
|
||||
|
||||
#include <fc/signals.hpp>
|
||||
#include <fc/network/http/connection.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
class bitcoin_rpc_client {
|
||||
public:
|
||||
bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::string _user, std::string _password) ;
|
||||
std::string receive_full_block( const std::string& block_hash );
|
||||
int32_t receive_confirmations_tx( const std::string& tx_hash );
|
||||
bool receive_mempool_entry_tx( const std::string& tx_hash );
|
||||
uint64_t receive_estimated_fee();
|
||||
void send_btc_tx( const std::string& tx_hex );
|
||||
bool connection_is_not_defined() const;
|
||||
|
||||
private:
|
||||
|
||||
fc::http::reply send_post_request( std::string body );
|
||||
|
||||
std::string ip;
|
||||
uint32_t rpc_port;
|
||||
std::string user;
|
||||
std::string password;
|
||||
|
||||
fc::http::header authorization;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class zmq_listener {
|
||||
public:
|
||||
zmq_listener( std::string _ip, uint32_t _zmq );
|
||||
bool connection_is_not_defined() const { return zmq_port == 0; }
|
||||
|
||||
fc::signal<void( const std::string& )> event_received;
|
||||
private:
|
||||
void handle_zmq();
|
||||
std::vector<zmq::message_t> receive_multipart();
|
||||
|
||||
std::string ip;
|
||||
uint32_t zmq_port;
|
||||
|
||||
zmq::context_t ctx;
|
||||
zmq::socket_t socket;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class sidechain_net_handler_bitcoin : public sidechain_net_handler {
|
||||
public:
|
||||
sidechain_net_handler_bitcoin(const boost::program_options::variables_map& options);
|
||||
virtual ~sidechain_net_handler_bitcoin();
|
||||
|
||||
void update_tx_infos( const std::string& block_hash );
|
||||
|
||||
//void update_tx_approvals();
|
||||
|
||||
//void update_estimated_fee();
|
||||
|
||||
//void send_btc_tx( const sidechain::bitcoin_transaction& trx );
|
||||
|
||||
bool connection_is_not_defined() const;
|
||||
|
||||
std::string create_multisignature_wallet( const std::vector<std::string> public_keys );
|
||||
std::string transfer( const std::string& from, const std::string& to, const uint64_t amount );
|
||||
std::string sign_transaction( const std::string& transaction );
|
||||
std::string send_transaction( const std::string& transaction );
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
uint32_t zmq_port;
|
||||
uint32_t rpc_port;
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
|
||||
std::unique_ptr<zmq_listener> listener;
|
||||
std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
|
||||
graphene::chain::database* db;
|
||||
|
||||
void handle_event( const std::string& event_data);
|
||||
|
||||
std::vector<info_for_vin> extract_info_from_block( const std::string& _block );
|
||||
|
||||
void update_transaction_status( std::vector<fc::sha256> trx_for_check );
|
||||
|
||||
std::set<fc::sha256> get_valid_vins( const std::string tx_hash );
|
||||
|
||||
inline uint64_t parse_amount(std::string raw);
|
||||
|
||||
};
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
class sidechain_net_manager {
|
||||
public:
|
||||
sidechain_net_manager();
|
||||
virtual ~sidechain_net_manager();
|
||||
|
||||
bool create_handler(peerplays_sidechain::network network, const boost::program_options::variables_map& options);
|
||||
private:
|
||||
|
||||
std::vector<std::unique_ptr<sidechain_net_handler>> net_handlers;
|
||||
|
||||
};
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_manager.hpp>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
class peerplays_sidechain_plugin_impl
|
||||
{
|
||||
public:
|
||||
|
|
@ -16,8 +20,8 @@ class peerplays_sidechain_plugin_impl
|
|||
|
||||
peerplays_sidechain_plugin& _self;
|
||||
|
||||
uint32_t parameter;
|
||||
uint32_t optional_parameter;
|
||||
peerplays_sidechain::sidechain_net_manager _net_manager;
|
||||
|
||||
};
|
||||
|
||||
peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl()
|
||||
|
|
@ -48,8 +52,22 @@ void peerplays_sidechain_plugin::plugin_set_program_options(
|
|||
)
|
||||
{
|
||||
cli.add_options()
|
||||
("parameter", boost::program_options::value<uint32_t>(), "Parameter")
|
||||
("optional-parameter", boost::program_options::value<uint32_t>(), "Optional parameter")
|
||||
//("bitcoin-node-ip", bpo::value<string>()->implicit_value("127.0.0.1"), "IP address of Bitcoin node")
|
||||
//("bitcoin-node-zmq-port", bpo::value<uint32_t>()->implicit_value(28332), "ZMQ port of Bitcoin node")
|
||||
//("bitcoin-node-rpc-port", bpo::value<uint32_t>()->implicit_value(18332), "RPC port of Bitcoin node")
|
||||
//("bitcoin-node-rpc-user", bpo::value<string>(), "Bitcoin RPC user")
|
||||
//("bitcoin-node-rpc-password", bpo::value<string>(), "Bitcoin RPC password")
|
||||
//("bitcoin-address", bpo::value<string>(), "Bitcoin address")
|
||||
//("bitcoin-public-key", bpo::value<string>(), "Bitcoin public key")
|
||||
//("bitcoin-private-key", bpo::value<string>(), "Bitcoin private key")
|
||||
("bitcoin-node-ip", bpo::value<string>()->default_value("99.79.189.95"), "IP address of Bitcoin node")
|
||||
("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node")
|
||||
("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(22222), "RPC port of Bitcoin node")
|
||||
("bitcoin-node-rpc-user", bpo::value<string>()->default_value("1"), "Bitcoin RPC user")
|
||||
("bitcoin-node-rpc-password", bpo::value<string>()->default_value("1"), "Bitcoin RPC password")
|
||||
("bitcoin-address", bpo::value<string>()->default_value("2N911a7smwDzUGARg8s7Q1ViizFCw6gWcbR"), "Bitcoin address")
|
||||
("bitcoin-public-key", bpo::value<string>()->default_value("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772"), "Bitcoin public key")
|
||||
("bitcoin-private-key", bpo::value<string>()->default_value("cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr"), "Bitcoin private key")
|
||||
;
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
|
@ -58,11 +76,13 @@ void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options:
|
|||
{
|
||||
ilog("peerplays sidechain plugin: plugin_initialize()");
|
||||
|
||||
if (options.count("parameter")) {
|
||||
my->parameter = options["optional-parameter"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("optional-parameter")) {
|
||||
my->optional_parameter = options["optional-parameter"].as<uint32_t>();
|
||||
if( options.count( "bitcoin-node-ip" ) && options.count( "bitcoin-node-zmq-port" ) && options.count( "bitcoin-node-rpc-port" )
|
||||
&& options.count( "bitcoin-node-rpc-user" ) && options.count( "bitcoin-node-rpc-password" )
|
||||
&& options.count( "bitcoin-address" ) && options.count( "bitcoin-public-key" ) && options.count( "bitcoin-private-key" ) )
|
||||
{
|
||||
my->_net_manager.create_handler(network::bitcoin, options);
|
||||
} else {
|
||||
wlog("Haven't set up bitcoin sidechain parameters");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,4 +91,5 @@ void peerplays_sidechain_plugin::plugin_startup()
|
|||
ilog("peerplays sidechain plugin: plugin_startup()");
|
||||
}
|
||||
|
||||
} }
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
sidechain_net_handler::sidechain_net_handler(const boost::program_options::variables_map& options) {
|
||||
}
|
||||
|
||||
sidechain_net_handler::~sidechain_net_handler() {
|
||||
}
|
||||
|
||||
std::vector<std::string> sidechain_net_handler::get_user_sidechain_address_mapping() {
|
||||
std::vector<std::string> result;
|
||||
|
||||
switch (network) {
|
||||
case network::bitcoin:
|
||||
result.push_back("2N5aFW5WFaYZLuJWx9RGziHBdEMj9Zf8s3J");
|
||||
result.push_back("2MxAnE469fhhdvUqUB7daU997VSearb2mn7");
|
||||
result.push_back("2NAYptFvTU8vJ1pC7CxvVA9R7D3NdBJHpwL");
|
||||
result.push_back("2N9zPaLDfaJazUmVfr3wgn8BK75tid2kkzR");
|
||||
result.push_back("2NDN7cDH3E57E1B8TwTYvBgF7CndL4FTBPL");
|
||||
//result.push_back("2MzEmSiwrRzozxE6gfZ14LAyDHZ4DYP1zVG");
|
||||
//result.push_back("2NDCdm1WVJVCMWJzRaSSy9NDvpNKiqkbrMg");
|
||||
//result.push_back("2Mu2iz3Jfqjyv3hBQGQZSGmZGZxhJp91TNX");
|
||||
//result.push_back("2N1sFbwcn4QVbvjp7yRsN4mg4mBFbvC8gKM");
|
||||
//result.push_back("2NDmxr6ufBE7Zgdgq9hShF2grx2YPEiTyNy");
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -0,0 +1,403 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include <fc/crypto/base64.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
|
||||
#include "graphene/peerplays_sidechain/sidechain_net_manager.hpp"
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
// =============================================================================
|
||||
|
||||
bitcoin_rpc_client::bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::string _user, std::string _password ):
|
||||
ip( _ip ), rpc_port( _rpc ), user( _user ), password( _password )
|
||||
{
|
||||
authorization.key = "Authorization";
|
||||
authorization.val = "Basic " + fc::base64_encode( user + ":" + password );
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::receive_full_block( const std::string& block_hash )
|
||||
{
|
||||
fc::http::connection conn;
|
||||
conn.connect_to( fc::ip::endpoint( fc::ip::address( ip ), rpc_port ) );
|
||||
|
||||
const auto url = "http://" + ip + ":" + std::to_string( rpc_port ) + "/rest/block/" + block_hash + ".json";
|
||||
|
||||
const auto reply = conn.request( "GET", url );
|
||||
if ( reply.status != 200 )
|
||||
return "";
|
||||
|
||||
ilog( "Receive Bitcoin block: ${hash}", ( "hash", block_hash ) );
|
||||
return std::string( reply.body.begin(), reply.body.end() );
|
||||
}
|
||||
|
||||
//int32_t bitcoin_rpc_client::receive_confirmations_tx( const std::string& tx_hash )
|
||||
//{
|
||||
// const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getrawtransaction\", \"params\": [") +
|
||||
// std::string("\"") + tx_hash + std::string("\"") + ", " + "true" + std::string("] }");
|
||||
//
|
||||
// const auto reply = send_post_request( body );
|
||||
//
|
||||
// if ( reply.status != 200 )
|
||||
// return 0;
|
||||
//
|
||||
// const auto result = std::string( reply.body.begin(), reply.body.end() );
|
||||
//
|
||||
// std::stringstream ss( result );
|
||||
// boost::property_tree::ptree tx;
|
||||
// boost::property_tree::read_json( ss, tx );
|
||||
//
|
||||
// if( tx.count( "result" ) ) {
|
||||
// if( tx.get_child( "result" ).count( "confirmations" ) ) {
|
||||
// return tx.get_child( "result" ).get_child( "confirmations" ).get_value<int64_t>();
|
||||
// }
|
||||
// }
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
bool bitcoin_rpc_client::receive_mempool_entry_tx( const std::string& tx_hash )
|
||||
{
|
||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getmempoolentry\", \"params\": [") +
|
||||
std::string("\"") + tx_hash + std::string("\"") + std::string("] }");
|
||||
|
||||
const auto reply = send_post_request( body );
|
||||
|
||||
if ( reply.status != 200 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t bitcoin_rpc_client::receive_estimated_fee()
|
||||
{
|
||||
static const auto confirmation_target_blocks = 6;
|
||||
|
||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimated_feerate\", \"method\": \"estimatesmartfee\", \"params\": [") +
|
||||
std::to_string(confirmation_target_blocks) + std::string("] }");
|
||||
|
||||
const auto reply = send_post_request( body );
|
||||
|
||||
if( reply.status != 200 )
|
||||
return 0;
|
||||
|
||||
std::stringstream ss( std::string( reply.body.begin(), reply.body.end() ) );
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json( ss, json );
|
||||
|
||||
if( json.count( "result" ) )
|
||||
if ( json.get_child( "result" ).count( "feerate" ) ) {
|
||||
auto feerate_str = json.get_child( "result" ).get_child( "feerate" ).get_value<std::string>();
|
||||
feerate_str.erase( std::remove( feerate_str.begin(), feerate_str.end(), '.' ), feerate_str.end() );
|
||||
return std::stoll( feerate_str );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bitcoin_rpc_client::send_btc_tx( const std::string& tx_hex )
|
||||
{
|
||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"send_tx\", \"method\": \"sendrawtransaction\", \"params\": [") +
|
||||
std::string("\"") + tx_hex + std::string("\"") + std::string("] }");
|
||||
|
||||
const auto reply = send_post_request( body );
|
||||
|
||||
if( reply.body.empty() )
|
||||
return;
|
||||
|
||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
||||
|
||||
std::stringstream ss(reply_str);
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json( ss, json );
|
||||
|
||||
if( reply.status == 200 ) {
|
||||
idump(( tx_hex ));
|
||||
return;
|
||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
||||
const auto error_code = json.get_child( "error" ).get_child( "code" ).get_value<int>();
|
||||
if( error_code == -27 ) // transaction already in block chain
|
||||
return;
|
||||
|
||||
wlog( "BTC tx is not sent! Reply: ${msg}", ("msg", reply_str) );
|
||||
}
|
||||
}
|
||||
|
||||
bool bitcoin_rpc_client::connection_is_not_defined() const
|
||||
{
|
||||
return ip.empty() || rpc_port == 0 || user.empty() || password.empty();
|
||||
}
|
||||
|
||||
fc::http::reply bitcoin_rpc_client::send_post_request( std::string body )
|
||||
{
|
||||
fc::http::connection conn;
|
||||
conn.connect_to( fc::ip::endpoint( fc::ip::address( ip ), rpc_port ) );
|
||||
|
||||
const auto url = "http://" + ip + ":" + std::to_string( rpc_port );
|
||||
|
||||
return conn.request( "POST", url, body, fc::http::headers{authorization} );
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
zmq_listener::zmq_listener( std::string _ip, uint32_t _zmq ): ip( _ip ), zmq_port( _zmq ), ctx( 1 ), socket( ctx, ZMQ_SUB ) {
|
||||
std::thread( &zmq_listener::handle_zmq, this ).detach();
|
||||
}
|
||||
|
||||
std::vector<zmq::message_t> zmq_listener::receive_multipart() {
|
||||
std::vector<zmq::message_t> msgs;
|
||||
|
||||
int32_t more;
|
||||
size_t more_size = sizeof( more );
|
||||
while ( true ) {
|
||||
zmq::message_t msg;
|
||||
socket.recv( &msg, 0 );
|
||||
socket.getsockopt( ZMQ_RCVMORE, &more, &more_size );
|
||||
|
||||
if ( !more )
|
||||
break;
|
||||
msgs.push_back( std::move(msg) );
|
||||
}
|
||||
|
||||
return msgs;
|
||||
}
|
||||
|
||||
void zmq_listener::handle_zmq() {
|
||||
socket.setsockopt( ZMQ_SUBSCRIBE, "hashblock", 9 );
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "hashtx", 6 );
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "rawblock", 8 );
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "rawtx", 5 );
|
||||
socket.connect( "tcp://" + ip + ":" + std::to_string( zmq_port ) );
|
||||
|
||||
while ( true ) {
|
||||
auto msg = receive_multipart();
|
||||
const auto header = std::string( static_cast<char*>( msg[0].data() ), msg[0].size() );
|
||||
const auto hash = boost::algorithm::hex( std::string( static_cast<char*>( msg[1].data() ), msg[1].size() ) );
|
||||
|
||||
event_received( hash );
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(const boost::program_options::variables_map& options) :
|
||||
sidechain_net_handler(options) {
|
||||
network = peerplays_sidechain::network::bitcoin;
|
||||
|
||||
ip = options.at("bitcoin-node-ip").as<std::string>();
|
||||
zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
|
||||
rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
|
||||
rpc_user = options.at("bitcoin-node-rpc-user").as<std::string>();
|
||||
rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>();
|
||||
|
||||
fc::http::connection conn;
|
||||
try {
|
||||
conn.connect_to( fc::ip::endpoint( fc::ip::address( ip ), rpc_port ) );
|
||||
} catch ( fc::exception e ) {
|
||||
elog( "No BTC node running at ${ip} or wrong rpc port: ${port}", ("ip", ip) ("port", rpc_port) );
|
||||
FC_ASSERT( false );
|
||||
}
|
||||
|
||||
listener = std::unique_ptr<zmq_listener>( new zmq_listener( ip, zmq_port ) );
|
||||
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>( new bitcoin_rpc_client( ip, rpc_port, rpc_user, rpc_password ) );
|
||||
//db = _db;
|
||||
|
||||
listener->event_received.connect([this]( const std::string& event_data ) {
|
||||
std::thread( &sidechain_net_handler_bitcoin::handle_event, this, event_data ).detach();
|
||||
} );
|
||||
|
||||
//db->send_btc_tx.connect([this]( const sidechain::bitcoin_transaction& trx ) {
|
||||
// std::thread( &sidechain_net_handler_bitcoin::send_btc_tx, this, trx ).detach();
|
||||
//} );
|
||||
}
|
||||
|
||||
sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::update_tx_infos( const std::string& block_hash )
|
||||
{
|
||||
std::string block = bitcoin_client->receive_full_block( block_hash );
|
||||
if( block != "" ) {
|
||||
const auto& vins = extract_info_from_block( block );
|
||||
// const auto& addr_idx = db->get_index_type<bitcoin_address_index>().indices().get<by_address>();
|
||||
// for( const auto& v : vins ) {
|
||||
// const auto& addr_itr = addr_idx.find( v.address );
|
||||
// FC_ASSERT( addr_itr != addr_idx.end() );
|
||||
// db->i_w_info.insert_info_for_vin( prev_out{ v.out.hash_tx, v.out.n_vout, v.out.amount }, v.address, addr_itr->address.get_witness_script() );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_tx_approvals()
|
||||
//{
|
||||
// std::vector<fc::sha256> trx_for_check;
|
||||
// const auto& confirmations_num = db->get_sidechain_params().confirmations_num;
|
||||
//
|
||||
// db->bitcoin_confirmations.safe_for<by_hash>([&]( btc_tx_confirmations_index::iterator itr_b, btc_tx_confirmations_index::iterator itr_e ){
|
||||
// for(auto iter = itr_b; iter != itr_e; iter++) {
|
||||
// db->bitcoin_confirmations.modify<by_hash>( iter->transaction_id, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.count_block++;
|
||||
// });
|
||||
//
|
||||
// if( iter->count_block == confirmations_num ) {
|
||||
// trx_for_check.push_back( iter->transaction_id );
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// update_transaction_status( trx_for_check );
|
||||
//
|
||||
//}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_estimated_fee()
|
||||
//{
|
||||
// db->estimated_feerate = bitcoin_client->receive_estimated_fee();
|
||||
//}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::send_btc_tx( const sidechain::bitcoin_transaction& trx )
|
||||
//{
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// for( const auto& v : trx.vin ) {
|
||||
// valid_vins.insert( v.prevout.hash );
|
||||
// }
|
||||
// db->bitcoin_confirmations.insert( bitcoin_transaction_confirmations( trx.get_txid(), valid_vins ) );
|
||||
//
|
||||
// FC_ASSERT( !bitcoin_client->connection_is_not_defined() );
|
||||
// const auto tx_hex = fc::to_hex( pack( trx ) );
|
||||
//
|
||||
// bitcoin_client->send_btc_tx( tx_hex );
|
||||
//}
|
||||
|
||||
bool sidechain_net_handler_bitcoin::connection_is_not_defined() const
|
||||
{
|
||||
return listener->connection_is_not_defined() && bitcoin_client->connection_is_not_defined();
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_bitcoin::create_multisignature_wallet( const std::vector<std::string> public_keys )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_bitcoin::transfer( const std::string& from, const std::string& to, const uint64_t amount )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_bitcoin::sign_transaction( const std::string& transaction )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_bitcoin::send_transaction( const std::string& transaction )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) {
|
||||
ilog("peerplays sidechain plugin: sidechain_net_handler_bitcoin::handle_event");
|
||||
ilog(" event_data: ${event_data}", ("event_data", event_data));
|
||||
//update_tx_approvals();
|
||||
//update_estimated_fee();
|
||||
//update_tx_infos( block_hash );
|
||||
}
|
||||
|
||||
std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block( const std::string& _block )
|
||||
{
|
||||
std::stringstream ss( _block );
|
||||
boost::property_tree::ptree block;
|
||||
boost::property_tree::read_json( ss, block );
|
||||
|
||||
std::vector<info_for_vin> result;
|
||||
|
||||
const auto& addr_idx = get_user_sidechain_address_mapping();// db->get_index_type<bitcoin_address_index>().indices().get<by_address>();
|
||||
|
||||
for (const auto& tx_child : block.get_child("tx")) {
|
||||
const auto& tx = tx_child.second;
|
||||
|
||||
for ( const auto& o : tx.get_child("vout") ) {
|
||||
const auto script = o.second.get_child("scriptPubKey");
|
||||
|
||||
if( !script.count("addresses") ) continue;
|
||||
|
||||
for (const auto& addr : script.get_child("addresses")) { // in which cases there can be more addresses?
|
||||
const auto address_base58 = addr.second.get_value<std::string>();
|
||||
|
||||
auto it = find(addr_idx.begin(), addr_idx.end(), address_base58);
|
||||
if (it == addr_idx.end()) continue;
|
||||
|
||||
info_for_vin vin;
|
||||
vin.out.hash_tx = tx.get_child("txid").get_value<std::string>();
|
||||
vin.out.amount = parse_amount( o.second.get_child( "value" ).get_value<std::string>() );
|
||||
vin.out.n_vout = o.second.get_child( "n" ).get_value<uint32_t>();
|
||||
vin.address = address_base58;
|
||||
result.push_back( vin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_transaction_status( std::vector<fc::sha256> trx_for_check )
|
||||
//{
|
||||
// const auto& confirmations_num = db->get_sidechain_params().confirmations_num;
|
||||
//
|
||||
// for( const auto& trx : trx_for_check ) {
|
||||
// auto confirmations = bitcoin_client->receive_confirmations_tx( trx.str() );
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.count_block = confirmations;
|
||||
// });
|
||||
//
|
||||
// if( confirmations >= confirmations_num ) {
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.confirmed = true;
|
||||
// });
|
||||
//
|
||||
// } else if( confirmations == 0 ) {
|
||||
// auto is_in_mempool = bitcoin_client->receive_mempool_entry_tx( trx.str() );
|
||||
//
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// if( !is_in_mempool ) {
|
||||
// valid_vins = get_valid_vins( trx.str() );
|
||||
// }
|
||||
//
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.missing = !is_in_mempool;
|
||||
// obj.valid_vins = valid_vins;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//std::set<fc::sha256> sidechain_net_handler_bitcoin::get_valid_vins( const std::string tx_hash )
|
||||
//{
|
||||
// const auto& confirmations_obj = db->bitcoin_confirmations.find<sidechain::by_hash>( fc::sha256( tx_hash ) );
|
||||
// FC_ASSERT( confirmations_obj.valid() );
|
||||
//
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// for( const auto& v : confirmations_obj->valid_vins ) {
|
||||
// auto confirmations = bitcoin_client->receive_confirmations_tx( v.str() );
|
||||
// if( confirmations == 0 ) {
|
||||
// continue;
|
||||
// }
|
||||
// valid_vins.insert( v );
|
||||
// }
|
||||
// return valid_vins;
|
||||
//}
|
||||
|
||||
// Removes dot from amount output: "50.00000000"
|
||||
inline uint64_t sidechain_net_handler_bitcoin::parse_amount(std::string raw) {
|
||||
raw.erase(std::remove(raw.begin(), raw.end(), '.'), raw.end());
|
||||
return std::stoll(raw);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_manager.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
sidechain_net_manager::sidechain_net_manager() {
|
||||
ilog(__FUNCTION__);
|
||||
}
|
||||
|
||||
sidechain_net_manager::~sidechain_net_manager() {
|
||||
ilog(__FUNCTION__);
|
||||
}
|
||||
|
||||
bool sidechain_net_manager::create_handler(peerplays_sidechain::network network, const boost::program_options::variables_map& options) {
|
||||
ilog(__FUNCTION__);
|
||||
|
||||
bool ret_val = false;
|
||||
|
||||
switch (network) {
|
||||
case network::bitcoin: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_bitcoin(options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
ret_val = true;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
Loading…
Reference in a new issue