Skip to content

Commit

Permalink
Bitcoin monitoring (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
dolgopolovwork authored and Alexey-N-Chernyshov committed Dec 14, 2018
1 parent e4cc607 commit 6236f36
Show file tree
Hide file tree
Showing 27 changed files with 183 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import mu.KLogging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Component
import provider.btc.BtcPublicKeyProvider
import provider.btc.generation.BtcPublicKeyProvider
import provider.btc.address.BtcAddressType
import provider.btc.address.getAddressTypeByAccountId
import sidechain.iroha.IrohaChainListener
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import generation.btc.config.btcAddressGenerationConfig
import sidechain.iroha.IrohaInitialization

@SpringBootApplication
@ComponentScan(basePackages = ["generation", "healthcheck", "provider.btc"])
@ComponentScan(basePackages = ["generation", "healthcheck", "provider.btc.generation", "provider.btc.network"])
class BtcAddressGenerationApplication

private val logger = KLogging().logger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.github.kittinunf.result.flatMap
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import provider.TriggerProvider
import provider.btc.BtcSessionProvider
import provider.btc.generation.BtcSessionProvider
import provider.btc.address.BtcAddressType

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import model.IrohaCredential
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import provider.TriggerProvider
import provider.btc.BtcSessionProvider
import provider.btc.generation.BtcSessionProvider
import sidechain.iroha.consumer.IrohaNetworkImpl
import sidechain.iroha.util.ModelUtil

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import provider.btc.network.BtcNetworkConfigProvider
import sidechain.SideChainEvent
import sidechain.iroha.IrohaChainListener
import sidechain.iroha.consumer.IrohaNetwork
import java.io.File


@Component
class BtcNotaryInitialization(
@Autowired private val wallet: Wallet,
@Autowired private val btcNotaryConfig: BtcNotaryConfig,
@Autowired private val irohaCredential: IrohaCredential,
@Autowired private val irohaNetwork: IrohaNetwork,
Expand All @@ -38,8 +39,6 @@ class BtcNotaryInitialization(
@Autowired private val btcNetworkConfigProvider: BtcNetworkConfigProvider
) : HealthyService() {

private val wallet = Wallet.loadFromFile(File(btcNotaryConfig.bitcoin.walletPath))

/**
* Init notary
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package notary.btc.config

import config.loadConfigs
import model.IrohaCredential
import org.bitcoinj.wallet.Wallet
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import provider.btc.address.BtcRegisteredAddressesProvider
import sidechain.iroha.IrohaChainListener
import sidechain.iroha.consumer.IrohaNetworkImpl
import sidechain.iroha.util.ModelUtil
import java.io.File

val notaryConfig = loadConfigs("btc-notary", BtcNotaryConfig::class.java, "/btc/notary.properties")

Expand Down Expand Up @@ -40,6 +42,9 @@ class BtcNotaryAppConfiguration {
}, { ex -> throw ex })
}

@Bean
fun wallet() = Wallet.loadFromFile(File(notaryConfig.bitcoin.walletPath))

@Bean
fun notaryCredential() = notaryCredential

Expand Down
2 changes: 1 addition & 1 deletion btc-deposit/src/main/kotlin/notary/btc/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import sidechain.iroha.IrohaInitialization
import java.util.*

@SpringBootApplication
@ComponentScan(basePackages = ["notary", "healthcheck", "provider.btc.network", "listener.btc", "handler.btc"])
@ComponentScan(basePackages = ["notary", "healthcheck", "provider.btc.network", "provider.btc.wallet", "listener.btc", "handler.btc"])
class BtcNotaryApplication

private val logger = KLogging().logger
Expand Down
4 changes: 2 additions & 2 deletions btc-withdrawal/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def getSendBtcArgs() {
if (project.hasProperty("address")) {
args.add(project.property("address").toString())
}
if (project.hasProperty("amount")) {
args.add(project.property("amount").toString())
if (project.hasProperty("amountSat")) {
args.add(project.property("amountSat").toString())
}
return args
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import java.util.concurrent.Executors
*/
@Component
class BtcWithdrawalInitialization(
@Autowired private val wallet: Wallet,
@Autowired private val btcWithdrawalConfig: BtcWithdrawalConfig,
@Autowired private val btcChangeAddressProvider: BtcChangeAddressProvider,
@Autowired private val irohaChainListener: IrohaChainListener,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package withdrawal.btc.config

import config.loadConfigs
import model.IrohaCredential
import org.bitcoinj.wallet.Wallet
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import provider.btc.address.BtcRegisteredAddressesProvider
Expand All @@ -11,6 +12,8 @@ import sidechain.iroha.consumer.IrohaNetworkImpl
import sidechain.iroha.util.ModelUtil
import withdrawal.btc.provider.BtcChangeAddressProvider
import withdrawal.btc.provider.BtcWhiteListProvider
import withdrawal.btc.statistics.WithdrawalStatistics
import java.io.File

val withdrawalConfig = loadConfigs("btc-withdrawal", BtcWithdrawalConfig::class.java, "/btc/withdrawal.properties")

Expand All @@ -29,6 +32,12 @@ class BtcWithdrawalAppConfiguration {
IrohaCredential(withdrawalConfig.registrationCredential.accountId, keypair)
}, { ex -> throw ex })

@Bean
fun withdrawalStatistics() = WithdrawalStatistics.create()

@Bean
fun wallet() = Wallet.loadFromFile(File(withdrawalConfig.bitcoin.walletPath))

@Bean
fun withdrawalCredential() =
IrohaCredential(withdrawalConfig.withdrawalCredential.accountId, withdrawalKeypair)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.bitcoinj.core.PeerGroup
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import sidechain.iroha.BTC_SIGN_COLLECT_DOMAIN
import withdrawal.btc.statistics.WithdrawalStatistics
import withdrawal.btc.transaction.SignCollector
import withdrawal.btc.transaction.UnsignedTransactions

Expand All @@ -14,6 +15,7 @@ import withdrawal.btc.transaction.UnsignedTransactions
*/
@Component
class NewSignatureEventHandler(
@Autowired private val withdrawalStatistics: WithdrawalStatistics,
@Autowired private val signCollector: SignCollector,
@Autowired private val unsignedTransactions: UnsignedTransactions
) {
Expand Down Expand Up @@ -44,10 +46,16 @@ class NewSignatureEventHandler(
.fold({
peerGroup.broadcastTransaction(tx)
unsignedTransactions.remove(shortTxHash)
}, { ex -> logger.error("Cannot complete tx $originalHash", ex) })
withdrawalStatistics.incSucceededTransfers()
}, { ex ->
withdrawalStatistics.incFailedTransfers()
logger.error("Cannot complete tx $originalHash", ex)
})


}, { ex -> logger.error("Cannot get signatures for tx $originalHash", ex) })
}, { ex ->
withdrawalStatistics.incFailedTransfers()
logger.error("Cannot get signatures for tx $originalHash", ex)
})
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import com.github.kittinunf.result.failure
import com.github.kittinunf.result.map
import helper.address.isValidBtcAddress
import iroha.protocol.Commands
import monitoring.Monitoring
import mu.KLogging
import org.bitcoinj.core.Transaction
import org.bitcoinj.wallet.Wallet
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import withdrawal.btc.config.BtcWithdrawalConfig
import withdrawal.btc.provider.BtcWhiteListProvider
import withdrawal.btc.statistics.WithdrawalStatistics
import withdrawal.btc.transaction.SignCollector
import withdrawal.btc.transaction.TransactionCreator
import withdrawal.btc.transaction.UnsignedTransactions
Expand All @@ -20,12 +22,15 @@ import withdrawal.btc.transaction.UnsignedTransactions
*/
@Component
class WithdrawalTransferEventHandler(
@Autowired private val withdrawalStatistics: WithdrawalStatistics,
@Autowired private val whiteListProvider: BtcWhiteListProvider,
@Autowired private val btcWithdrawalConfig: BtcWithdrawalConfig,
@Autowired private val transactionCreator: TransactionCreator,
@Autowired private val signCollector: SignCollector,
@Autowired private val unsignedTransactions: UnsignedTransactions
) {
) : Monitoring() {
override fun monitor() = withdrawalStatistics

private val newBtcTransactionListeners = ArrayList<(tx: Transaction) -> Unit>()

/**
Expand Down Expand Up @@ -56,6 +61,7 @@ class WithdrawalTransferEventHandler(
"to:$destinationAddress " +
"amount:${transferCommand.amount})"
}
withdrawalStatistics.incTotalTransfers()
whiteListProvider.checkWithdrawalAddress(transferCommand.srcAccountId, destinationAddress)
.fold({ ableToWithdraw ->
if (ableToWithdraw) {
Expand All @@ -64,6 +70,7 @@ class WithdrawalTransferEventHandler(
logger.warn { "Cannot withdraw to $destinationAddress, because it's not in ${transferCommand.srcAccountId} whitelist" }
}
}, { ex ->
withdrawalStatistics.incFailedTransfers()
logger.error("Cannot check ability to withdraw", ex)
})
}
Expand Down Expand Up @@ -96,7 +103,10 @@ class WithdrawalTransferEventHandler(
}.map { transaction ->
unsignedTransactions.markAsUnsigned(transaction)
logger.info { "Tx ${transaction.hashAsString} was added to collection of unsigned transactions" }
}.failure { ex -> logger.error("Cannot create withdrawal transaction", ex) }
}.failure { ex ->
withdrawalStatistics.incFailedTransfers()
logger.error("Cannot create withdrawal transaction", ex)
}
}

/**
Expand Down
4 changes: 3 additions & 1 deletion btc-withdrawal/src/main/kotlin/withdrawal/btc/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import mu.KLogging
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.EnableMBeanExport
import sidechain.iroha.IrohaInitialization
import withdrawal.btc.config.withdrawalConfig
import java.util.*

@EnableMBeanExport
@SpringBootApplication
@ComponentScan(basePackages = ["withdrawal", "healthcheck", "provider.btc.network", "listener.btc"])
@ComponentScan(basePackages = ["withdrawal", "healthcheck", "provider.btc.network", "handler.btc", "provider.btc.address", "provider.btc.wallet"])
class BtcWithdrawalApplication

private val logger = KLogging().logger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package withdrawal.btc.provider
import com.github.kittinunf.result.Result
import com.github.kittinunf.result.map
import model.IrohaCredential
import monitoring.Monitoring
import provider.btc.address.AddressInfo
import provider.btc.address.BtcAddress
import sidechain.iroha.consumer.IrohaNetwork
Expand All @@ -11,13 +12,14 @@ import sidechain.iroha.util.getAccountDetails
/*
Class that is used to get change address
*/

open class BtcChangeAddressProvider(
private val credential: IrohaCredential,
private val irohaNetwork: IrohaNetwork,
private val mstRegistrationAccount: String,
private val changeAddressesStorageAccount: String
) {
) : Monitoring() {
override fun monitor() = getChangeAddress()

/**
* Returns change address
* @return - result with change address object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package withdrawal.btc.statistics

import java.util.concurrent.atomic.AtomicInteger

/**
* Data class that holds short statistics about withdrawal service
*/
data class WithdrawalStatistics(
val totalTransfers: AtomicInteger,
val failedTransfers: AtomicInteger,
val succeededTransfers: AtomicInteger
) {
fun incTotalTransfers() = totalTransfers.incrementAndGet()

fun incFailedTransfers() = failedTransfers.incrementAndGet()

fun incSucceededTransfers() = succeededTransfers.incrementAndGet()

companion object {
fun create() = WithdrawalStatistics(AtomicInteger(), AtomicInteger(), AtomicInteger())
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package withdrawal.btc.transaction

import monitoring.Monitoring
import org.bitcoinj.core.Transaction
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
Expand All @@ -12,7 +13,9 @@ import java.util.concurrent.ConcurrentHashMap
@Component
class UnsignedTransactions(
@Autowired private val signCollector: SignCollector
) {
) : Monitoring() {
override fun monitor() = unsignedTransactions.values.map { timedTx -> timedTx.tx.toString() }

//TODO create rollback mechanism
private val unsignedTransactions = ConcurrentHashMap<String, TimedTx>()

Expand Down
33 changes: 33 additions & 0 deletions btc/src/main/kotlin/monitoring/Monitoring.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package monitoring

import com.github.kittinunf.result.Result
import org.springframework.jmx.export.annotation.ManagedAttribute
import org.springframework.jmx.export.annotation.ManagedResource
import util.toJson

/*
* Class that was developed to help you monitor things
*/
@ManagedResource
abstract class Monitoring {

/*
* Returns an object that must monitored
*/
protected abstract fun monitor(): Any

/*
* Takes monitored object and turns it into JSON.
* This function is used by JMX
*/
@ManagedAttribute
fun getMonitoring(): String {
val objectToMonitor = monitor()
if (objectToMonitor !is Result<Any, Exception>) {
return String.toJson(objectToMonitor)
}
return objectToMonitor.fold(
{ data -> String.toJson(data) },
{ ex -> throw ex })
}
}
1 change: 0 additions & 1 deletion btc/src/main/kotlin/provider/btc/address/BtcAddress.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package provider.btc.address
import com.squareup.moshi.Moshi
import util.irohaEscape


private val addressInfoJsonAdapter = Moshi.Builder().build().adapter(AddressInfo::class.java)

data class BtcAddress(val address: String, val info: AddressInfo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package provider.btc.address
import com.github.kittinunf.result.Result
import com.github.kittinunf.result.map
import model.IrohaCredential
import monitoring.Monitoring
import sidechain.iroha.consumer.IrohaNetwork
import sidechain.iroha.util.getAccountDetails

Expand All @@ -12,7 +13,8 @@ class BtcAddressesProvider(
private val irohaNetwork: IrohaNetwork,
private val mstRegistrationAccount: String,
private val notaryAccount: String
) {
) : Monitoring() {
override fun monitor() = getAddresses()

/**
* Get all created btc addresses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package provider.btc.address
import com.github.kittinunf.result.Result
import com.github.kittinunf.result.map
import model.IrohaCredential
import monitoring.Monitoring
import sidechain.iroha.consumer.IrohaNetwork
import sidechain.iroha.util.getAccountDetails

Expand All @@ -12,7 +13,8 @@ open class BtcRegisteredAddressesProvider(
private val irohaNetwork: IrohaNetwork,
private val registrationAccount: String,
private val notaryAccount: String
) {
) : Monitoring() {
override fun monitor() = getRegisteredAddresses()

/**
* Get all registered btc addresses
Expand Down
Loading

0 comments on commit 6236f36

Please sign in to comment.