Skip to content

fix: expose signer interface #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/BitcoinCore/Classes/ApiSync/BlockHashFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class BlockHashFetcher: IBlockHashFetcher {
}

if afterCheckpoint.count > 0 {
await try blockHashes.merge(blockchairFetcher.fetch(heights: afterCheckpoint), uniquingKeysWith: { a, _ in a })
try await blockHashes.merge(blockchairFetcher.fetch(heights: afterCheckpoint), uniquingKeysWith: { a, _ in a })
}

return blockHashes
Expand Down
20 changes: 15 additions & 5 deletions Sources/BitcoinCore/Classes/Core/BitcoinCoreBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class BitcoinCoreBuilder {
private var storage: IStorage?
private var checkpoint: Checkpoint?
private var apiSyncStateManager: ApiSyncStateManager?
private var signer: ITransactionSigner?

@discardableResult public func set(extendedKey: HDExtendedKey?) -> BitcoinCoreBuilder {
self.extendedKey = extendedKey
Expand All @@ -42,6 +43,11 @@ public class BitcoinCoreBuilder {
self.watchAddressPublicKey = watchAddressPublicKey
return self
}

public func set(signer: ITransactionSigner?) -> BitcoinCoreBuilder {
self.signer = signer
return self
}

public func set(network: INetwork) -> BitcoinCoreBuilder {
self.network = network
Expand Down Expand Up @@ -297,16 +303,20 @@ public class BitcoinCoreBuilder {
var transactionCreator: TransactionCreator?

if let hdWallet {
let ecdsaInputSigner = EcdsaInputSigner(hdWallet: hdWallet, network: network)
let schnorrInputSigner = SchnorrInputSigner(hdWallet: hdWallet)
let transactionSizeCalculatorInstance = TransactionSizeCalculator()
if (self.signer == nil) {
let ecdsaInputSigner = EcdsaInputSigner(hdWallet: hdWallet, network: network)
let schnorrInputSigner = SchnorrInputSigner(hdWallet: hdWallet)
let transactionSigner = TransactionSigner(ecdsaInputSigner: ecdsaInputSigner, schnorrInputSigner: schnorrInputSigner)
self.signer = transactionSigner
}

let dustCalculatorInstance = DustCalculator(dustRelayTxFee: network.dustRelayTxFee, sizeCalculator: transactionSizeCalculatorInstance)
let recipientSetter = RecipientSetter(addressConverter: addressConverter, pluginManager: pluginManager)
let outputSetter = OutputSetter(outputSorterFactory: transactionDataSorterFactory, factory: factory)
let inputSetter = InputSetter(unspentOutputSelector: unspentOutputSelector, transactionSizeCalculator: transactionSizeCalculatorInstance, addressConverter: addressConverter, publicKeyManager: publicKeyManager, factory: factory, pluginManager: pluginManager, dustCalculator: dustCalculatorInstance, changeScriptType: purpose.scriptType, inputSorterFactory: transactionDataSorterFactory)
let lockTimeSetter = LockTimeSetter(storage: storage)
let transactionSigner = TransactionSigner(ecdsaInputSigner: ecdsaInputSigner, schnorrInputSigner: schnorrInputSigner)
let transactionBuilder = TransactionBuilder(recipientSetter: recipientSetter, inputSetter: inputSetter, lockTimeSetter: lockTimeSetter, outputSetter: outputSetter, signer: transactionSigner)
let transactionBuilder = TransactionBuilder(recipientSetter: recipientSetter, inputSetter: inputSetter, lockTimeSetter: lockTimeSetter, outputSetter: outputSetter, signer: self.signer!)
transactionFeeCalculator = TransactionFeeCalculator(recipientSetter: recipientSetter, inputSetter: inputSetter, addressConverter: addressConverter, publicKeyManager: publicKeyManager, changeScriptType: purpose.scriptType)
let transactionSendTimer = TransactionSendTimer(interval: 60)
let transactionSenderInstance = TransactionSender(transactionSyncer: pendingTransactionSyncer, initialBlockDownload: initialDownload, peerManager: peerManager, storage: storage, timer: transactionSendTimer, logger: logger)
Expand All @@ -317,7 +327,7 @@ public class BitcoinCoreBuilder {

transactionSendTimer.delegate = transactionSender

transactionCreator = TransactionCreator(transactionBuilder: transactionBuilder, transactionProcessor: pendingTransactionProcessor, transactionSender: transactionSenderInstance, bloomFilterManager: bloomFilterManager)
transactionCreator = TransactionCreator(transactionBuilder: transactionBuilder, transactionProcessor: pendingTransactionProcessor, transactionSender: transactionSenderInstance, bloomFilterManager: bloomFilterManager, signer: self.signer!)
}
let mempoolTransactions = MempoolTransactions(transactionSyncer: pendingTransactionSyncer, transactionSender: transactionSender)

Expand Down
8 changes: 4 additions & 4 deletions Sources/BitcoinCore/Classes/Core/Protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ public protocol ITransactionCreator {
}

protocol ITransactionBuilder {
func buildTransaction(toAddress: String, memo: String?, value: Int, feeRate: Int, senderPay: Bool, sortType: TransactionDataSortType, unspentOutputs: [UnspentOutput]?, pluginData: [UInt8: IPluginData]) throws -> FullTransaction
func buildTransaction(from: UnspentOutput, toAddress: String, memo: String?, feeRate: Int, sortType: TransactionDataSortType) throws -> FullTransaction
func buildTransaction(toAddress: String, memo: String?, value: Int, feeRate: Int, senderPay: Bool, sortType: TransactionDataSortType, unspentOutputs: [UnspentOutput]?, pluginData: [UInt8: IPluginData], signer: ITransactionSigner) throws -> FullTransaction
func buildTransaction(from: UnspentOutput, toAddress: String, memo: String?, feeRate: Int, sortType: TransactionDataSortType, signer: ITransactionSigner) throws -> FullTransaction
}

protocol ITransactionFeeCalculator {
Expand All @@ -401,7 +401,7 @@ public protocol IBlockchainDataListener: AnyObject {
func onInsert(block: Block)
}

protocol IInputSigner {
public protocol IInputSigner {
func sigScriptData(transaction: Transaction, inputsToSign: [InputToSign], outputs: [Output], index: Int) throws -> [Data]
}

Expand Down Expand Up @@ -647,7 +647,7 @@ protocol ILockTimeSetter {
func setLockTime(to mutableTransaction: MutableTransaction)
}

protocol ITransactionSigner {
public protocol ITransactionSigner {
func sign(mutableTransaction: MutableTransaction) throws
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@ class TransactionBuilder {
private let inputSetter: IInputSetter
private let lockTimeSetter: ILockTimeSetter
private let outputSetter: IOutputSetter
private let signer: TransactionSigner

init(recipientSetter: IRecipientSetter, inputSetter: IInputSetter, lockTimeSetter: ILockTimeSetter, outputSetter: IOutputSetter, signer: TransactionSigner) {
init(recipientSetter: IRecipientSetter, inputSetter: IInputSetter, lockTimeSetter: ILockTimeSetter, outputSetter: IOutputSetter, signer: ITransactionSigner) {
self.recipientSetter = recipientSetter
self.inputSetter = inputSetter
self.lockTimeSetter = lockTimeSetter
self.outputSetter = outputSetter
self.signer = signer
}
}

extension TransactionBuilder: ITransactionBuilder {
func buildTransaction(toAddress: String, memo: String?, value: Int, feeRate: Int, senderPay: Bool, sortType: TransactionDataSortType, unspentOutputs: [UnspentOutput]?, pluginData: [UInt8: IPluginData]) throws -> FullTransaction {
func buildTransaction(toAddress: String, memo: String?, value: Int, feeRate: Int, senderPay: Bool, sortType: TransactionDataSortType, unspentOutputs: [UnspentOutput]?, pluginData: [UInt8: IPluginData], signer: ITransactionSigner) throws -> FullTransaction {
let mutableTransaction = MutableTransaction()

try recipientSetter.setRecipient(to: mutableTransaction, toAddress: toAddress, memo: memo, value: value, pluginData: pluginData, skipChecks: false)
Expand All @@ -28,7 +26,7 @@ extension TransactionBuilder: ITransactionBuilder {
return mutableTransaction.build()
}

func buildTransaction(from unspentOutput: UnspentOutput, toAddress: String, memo: String?, feeRate: Int, sortType: TransactionDataSortType) throws -> FullTransaction {
func buildTransaction(from unspentOutput: UnspentOutput, toAddress: String, memo: String?, feeRate: Int, sortType: TransactionDataSortType, signer: ITransactionSigner) throws -> FullTransaction {
let mutableTransaction = MutableTransaction(outgoing: false)

try recipientSetter.setRecipient(to: mutableTransaction, toAddress: toAddress, memo: memo, value: unspentOutput.output.value, pluginData: [:], skipChecks: false)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

class TransactionSigner {
public class TransactionSigner {
enum SignError: Error {
case notSupportedScriptType
case noRedeemScript
Expand Down Expand Up @@ -79,7 +79,7 @@ class TransactionSigner {
}

extension TransactionSigner: ITransactionSigner {
func sign(mutableTransaction: MutableTransaction) throws {
public func sign(mutableTransaction: MutableTransaction) throws {
for (index, inputToSign) in mutableTransaction.inputsToSign.enumerated() {
if inputToSign.previousOutput.scriptType == .p2tr {
try schnorrSign(index: index, mutableTransaction: mutableTransaction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class TransactionCreator {
private let transactionProcessor: IPendingTransactionProcessor
private let transactionSender: ITransactionSender
private let bloomFilterManager: IBloomFilterManager
private let signer: ITransactionSigner

init(transactionBuilder: ITransactionBuilder, transactionProcessor: IPendingTransactionProcessor, transactionSender: ITransactionSender, bloomFilterManager: IBloomFilterManager) {
init(transactionBuilder: ITransactionBuilder, transactionProcessor: IPendingTransactionProcessor, transactionSender: ITransactionSender, bloomFilterManager: IBloomFilterManager, signer: ITransactionSigner) {
self.transactionBuilder = transactionBuilder
self.transactionProcessor = transactionProcessor
self.transactionSender = transactionSender
self.bloomFilterManager = bloomFilterManager
self.signer = signer
}

private func processAndSend(transaction: FullTransaction) throws {
Expand All @@ -40,7 +42,8 @@ extension TransactionCreator: ITransactionCreator {
senderPay: senderPay,
sortType: sortType,
unspentOutputs: unspentOutputs,
pluginData: pluginData
pluginData: pluginData,
signer: signer
)

try processAndSend(transaction: transaction)
Expand All @@ -53,7 +56,8 @@ extension TransactionCreator: ITransactionCreator {
toAddress: address,
memo: memo,
feeRate: feeRate,
sortType: sortType
sortType: sortType,
signer: self.signer
)

try processAndSend(transaction: transaction)
Expand All @@ -69,7 +73,8 @@ extension TransactionCreator: ITransactionCreator {
senderPay: senderPay,
sortType: sortType,
unspentOutputs: unspentOutputs,
pluginData: pluginData
pluginData: pluginData,
signer: self.signer
)

return TransactionSerializer.serialize(transaction: transaction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
XCTAssertEqual(calculator.transactionSize(previousOutputs: outputs(withScriptTypes: [.p2wpkhSh]), outputScriptTypes: [.p2pkh]), 136) // 1-in 1-out (sh) witness tx
XCTAssertEqual(calculator.transactionSize(previousOutputs: outputs(withScriptTypes: [.p2wpkh, .p2pkh, .p2pkh, .p2pkh]), outputScriptTypes: [.p2pkh]), 558) // 4-in 1-out witness tx
}

func testTransactionSizeShInputsStandard() {
let redeemScript = Data(repeating: 0, count: 45)
let shOutput = Output(withValue: 0, index: 0, lockingScript: Data(), type: .p2sh, redeemScript: redeemScript)
Expand Down