problem: Bitcoin listunspent is not working when the upstream do not provide it, though have other sources of unspent data

solution: wrapper for listunspent requests that uses Dshackle mechanism to gather data
This commit is contained in:
Igor Artamonov
2022-07-21 22:09:37 -04:00
parent 7f67171ad6
commit d65a217535
16 changed files with 144 additions and 41 deletions

View File

@@ -51,7 +51,7 @@ class TrackBitcoinAddressSpec extends Specification {
def "Correct sum for single"() {
setup:
def unspents = [
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L, 123L)
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L)
]
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
def address = new TrackBitcoinAddress.Address(
@@ -68,8 +68,8 @@ class TrackBitcoinAddressSpec extends Specification {
def "Correct sum for few"() {
setup:
def unspents = [
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L, 123L),
new SimpleUnspent("17d1c4adf14b222e652c58d11435fa9ee2ddea000c6f5e20e6b715eb940fc28f", 0, 123L, 123L),
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L),
new SimpleUnspent("17d1c4adf14b222e652c58d11435fa9ee2ddea000c6f5e20e6b715eb940fc28f", 0, 123L),
]
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
def address = new TrackBitcoinAddress.Address(
@@ -120,8 +120,8 @@ class TrackBitcoinAddressSpec extends Specification {
def "Correct sum for few with utxo"() {
setup:
def unspents = [
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L, 123L),
new SimpleUnspent("17d1c4adf14b222e652c58d11435fa9ee2ddea000c6f5e20e6b715eb940fc28f", 0, 123L, 123L),
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 100L),
new SimpleUnspent("17d1c4adf14b222e652c58d11435fa9ee2ddea000c6f5e20e6b715eb940fc28f", 0, 123L),
]
TrackBitcoinAddress track = new TrackBitcoinAddress(Stub(MultistreamHolder))
def address = new TrackBitcoinAddress.Address(
@@ -282,7 +282,7 @@ class TrackBitcoinAddressSpec extends Specification {
2 * listUnspent(_) >>> [
Mono.just([]),
Mono.just([
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 1230000L, 123L)
new SimpleUnspent("f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef", 0, 1230000L)
])
]
}

View File

@@ -34,7 +34,8 @@ class BitcoinReaderSpec extends Specification {
api.answerOnce("getblockhash", [100000], "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506")
api.answerOnce("getblock", ["000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"], block)
def ups = Mock(BitcoinMultistream) {
_ * it.getDirectApi(_) >> Mono.just(api)
_ * getDirectApi(_) >> Mono.just(api)
_ * upstreams >> []
}
def reader = new BitcoinReader(ups, Stub(Head), null)

View File

@@ -29,7 +29,7 @@ class RpcUnspentReaderSpec extends Specification {
setup:
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-one-addr.json").bytes
def rpcReader = Mock(Reader) {
1 * read(new JsonRpcRequest("listunspent", [])) >> Mono.just(JsonRpcResponse.ok(json))
1 * read(new JsonRpcRequest("listunspent", [1, 9999999, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"]])) >> Mono.just(JsonRpcResponse.ok(json))
}
def upstreams = Mock(BitcoinMultistream) {
1 * getDirectApi(_) >> Mono.just(rpcReader)
@@ -45,19 +45,16 @@ class RpcUnspentReaderSpec extends Specification {
with(act[0]) {
txid == "e0f946c8f971b25cdffa64eed71d886019e437c0bf6a1b280584c0be5d1b5409"
vout == 29
confirmations == 2010
value == 1230030
}
with(act[1]) {
txid == "66e1e4d14ed6f454d2fda036f35cba423274ecdf5d46deb93f172c412a0f650d"
vout == 83
confirmations == 4963
value == 756339
}
with(act[35]) {
txid == "f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef"
vout == 58
confirmations == 2139
value == 1105047
}
}
@@ -66,7 +63,7 @@ class RpcUnspentReaderSpec extends Specification {
setup:
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json").bytes
def rpcReader = Mock(Reader) {
1 * read(new JsonRpcRequest("listunspent", [])) >> Mono.just(JsonRpcResponse.ok(json))
1 * read(new JsonRpcRequest("listunspent", [1, 9999999, ["35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP"]])) >> Mono.just(JsonRpcResponse.ok(json))
}
def upstreams = Mock(BitcoinMultistream) {
1 * getDirectApi(_) >> Mono.just(rpcReader)
@@ -83,19 +80,16 @@ class RpcUnspentReaderSpec extends Specification {
txid == "8ad0d954a01eeb4f2c62d58d291699af847f9c8df43b775c27ffe8a5f76eba00"
vout == 1
value == 216465
confirmations == 2583
}
with(act[11]) {
txid == "777671a46b30b068052a73387e036bc8515cd3ba6adf9be4c70dfc0699f67c09"
vout == 0
confirmations == 13705
value == 307906
}
// cat src/test/resources/bitcoin/unspent-two-addr.json | jq '[.[] | select(.address == "35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP")] | .[211]'
with(act[211]) {
txid == "f20727393b0a586a3062a615fb71f43ec21c24258c3c6ec546fee5cbc1fa2ba7"
vout == 0
confirmations == 21890
value == 50000000000
}
}
@@ -104,7 +98,7 @@ class RpcUnspentReaderSpec extends Specification {
setup:
def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json").bytes
def rpcReader = Mock(Reader) {
1 * read(new JsonRpcRequest("listunspent", [])) >> Mono.just(JsonRpcResponse.ok(json))
1 * read(_) >> Mono.just(JsonRpcResponse.ok(json))
}
def upstreams = Mock(BitcoinMultistream) {
1 * getDirectApi(_) >> Mono.just(rpcReader)
@@ -122,13 +116,11 @@ class RpcUnspentReaderSpec extends Specification {
txid == "e0f946c8f971b25cdffa64eed71d886019e437c0bf6a1b280584c0be5d1b5409"
vout == 29
value == 1230030
confirmations == 2030
}
// cat src/test/resources/bitcoin/unspent-two-addr.json | jq '[.[] | select(.address == "1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK")] | .[35]'
with(act[35]) {
txid == "f14b222e652c58d11435fa9172ddea000c6f5e20e6b715eb940fc28d1c4adeef"
vout == 58
confirmations == 2159
value == 1105047
}
}