-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '82-bitcoin-abstract-network' into 'dev'
Resolve "Bitcoin: Abstract Network" Closes #82 See merge request ergo/rosen-bridge/rosen-chains!89
- Loading branch information
Showing
15 changed files
with
3,449 additions
and
1,168 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dist |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# @rosen-chains/bitcoin | ||
|
||
## Table of contents | ||
|
||
- [Introduction](#introduction) | ||
- [Installation](#installation) | ||
|
||
## Introduction | ||
|
||
this project contains bitcoin chain for Rosen-bridge | ||
|
||
## Installation | ||
|
||
npm: | ||
|
||
```sh | ||
npm i @rosen-chains/bitcoin | ||
``` | ||
|
||
yarn: | ||
|
||
```sh | ||
yarn add @rosen-chains/bitcoin | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
import { AbstractLogger } from '@rosen-bridge/logger-interface'; | ||
import { Fee } from '@rosen-bridge/minimum-fee'; | ||
import { | ||
AbstractUtxoChain, | ||
BoxInfo, | ||
ConfirmationStatus, | ||
EventTrigger, | ||
PaymentOrder, | ||
PaymentTransaction, | ||
SigningStatus, | ||
TransactionAssetBalance, | ||
TransactionType, | ||
} from '@rosen-chains/abstract-chain'; | ||
import AbstractBitcoinNetwork from './network/AbstractBitcoinNetwork'; | ||
import BitcoinTransaction from './BitcoinTransaction'; | ||
import { BitcoinConfigs, BitcoinUtxo } from './types'; | ||
|
||
class BitcoinChain extends AbstractUtxoChain<BitcoinUtxo> { | ||
declare network: AbstractBitcoinNetwork; | ||
declare configs: BitcoinConfigs; | ||
feeRatioDivisor: bigint; | ||
protected signFunction: (txHash: Uint8Array) => Promise<string>; | ||
|
||
constructor( | ||
network: AbstractBitcoinNetwork, | ||
configs: BitcoinConfigs, | ||
feeRatioDivisor: bigint, | ||
signFunction: (txHash: Uint8Array) => Promise<string>, | ||
logger?: AbstractLogger | ||
) { | ||
super(network, configs, logger); | ||
this.feeRatioDivisor = feeRatioDivisor; | ||
this.signFunction = signFunction; | ||
} | ||
|
||
/** | ||
* generates unsigned PaymentTransaction for payment order | ||
* @param eventId the id of event | ||
* @param txType transaction type | ||
* @param order the payment order (list of single payments) | ||
* @param unsignedTransactions ongoing unsigned PaymentTransactions (used for preventing double spend) | ||
* @param serializedSignedTransactions the serialized string of ongoing signed transactions (used for chaining transaction) | ||
* @returns the generated PaymentTransaction | ||
*/ | ||
generateTransaction = ( | ||
eventId: string, | ||
txType: TransactionType, | ||
order: PaymentOrder, | ||
unsignedTransactions: PaymentTransaction[], | ||
serializedSignedTransactions: string[], | ||
...extra: Array<any> | ||
): Promise<BitcoinTransaction> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* gets input and output assets of a PaymentTransaction | ||
* @param transaction the PaymentTransaction | ||
* @returns an object containing the amount of input and output assets | ||
*/ | ||
getTransactionAssets = ( | ||
transaction: PaymentTransaction | ||
): Promise<TransactionAssetBalance> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* extracts payment order of a PaymentTransaction | ||
* @param transaction the PaymentTransaction | ||
* @returns the transaction payment order (list of single payments) | ||
*/ | ||
extractTransactionOrder = (transaction: PaymentTransaction): PaymentOrder => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* verifies transaction fee for a PaymentTransaction | ||
* @param transaction the PaymentTransaction | ||
* @returns true if the transaction fee is verified | ||
*/ | ||
verifyTransactionFee = (transaction: PaymentTransaction): boolean => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* verifies no token burned in a PaymentTransaction | ||
* @param transaction the PaymentTransaction | ||
* @returns true if no token burned | ||
*/ | ||
verifyNoTokenBurned = async ( | ||
transaction: PaymentTransaction | ||
): Promise<boolean> => { | ||
// Bitcoin has no token and BTC cannot be burned | ||
return true; | ||
}; | ||
|
||
/** | ||
* verifies additional conditions for a PaymentTransaction | ||
* @param transaction the PaymentTransaction | ||
* @returns true if the transaction is verified | ||
*/ | ||
verifyTransactionExtraConditions = ( | ||
transaction: PaymentTransaction | ||
): boolean => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* verifies an event data with its corresponding lock transaction | ||
* @param event the event trigger model | ||
* @param feeConfig minimum fee and rsn ratio config for the event | ||
* @returns true if the event is verified | ||
*/ | ||
verifyEvent = (event: EventTrigger, feeConfig: Fee): Promise<boolean> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* checks if a transaction is still valid and can be sent to the network | ||
* @param transaction the transaction | ||
* @param signingStatus | ||
* @returns true if the transaction is still valid | ||
*/ | ||
isTxValid = ( | ||
transaction: PaymentTransaction, | ||
signingStatus: SigningStatus = SigningStatus.Signed | ||
): Promise<boolean> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* requests the corresponding signer service to sign the transaction | ||
* @param transaction the transaction | ||
* @param requiredSign the required number of sign | ||
* @returns the signed transaction | ||
*/ | ||
signTransaction = ( | ||
transaction: PaymentTransaction, | ||
requiredSign: number | ||
): Promise<PaymentTransaction> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* extracts confirmation status for a transaction | ||
* @param transactionId the transaction id | ||
* @param transactionType type of the transaction | ||
* @returns the transaction confirmation status | ||
*/ | ||
getTxConfirmationStatus = ( | ||
transactionId: string, | ||
transactionType: TransactionType | ||
): Promise<ConfirmationStatus> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* submits a transaction to the blockchain | ||
* @param transaction the transaction | ||
*/ | ||
submitTransaction = (transaction: PaymentTransaction): Promise<void> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* checks if a transaction is in mempool (returns false if the chain has no mempool) | ||
* @param transactionId the transaction id | ||
* @returns true if the transaction is in mempool | ||
*/ | ||
isTxInMempool = (transactionId: string): Promise<boolean> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* gets the minimum amount of native token for transferring asset | ||
* @returns the minimum amount | ||
*/ | ||
getMinimumNativeToken = (): bigint => this.configs.minBoxValue; | ||
|
||
/** | ||
* gets the RWT token id | ||
* @returns RWT token id | ||
*/ | ||
getRWTToken = (): string => this.configs.rwtId; | ||
|
||
/** | ||
* converts json representation of the payment transaction to PaymentTransaction | ||
* @returns PaymentTransaction object | ||
*/ | ||
PaymentTransactionFromJson = (jsonString: string): PaymentTransaction => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* generates PaymentTransaction object from raw tx json string | ||
* @param rawTxJsonString | ||
* @returns PaymentTransaction object | ||
*/ | ||
rawTxToPaymentTransaction = ( | ||
rawTxJsonString: string | ||
): Promise<PaymentTransaction> => { | ||
throw Error(`not implemented`); | ||
}; | ||
|
||
/** | ||
* generates mapping from input box id to serialized string of output box (filtered by address, containing the token) | ||
* @param address the address | ||
* @param tokenId the token id | ||
* @returns a Map from input box id to serialized string of output box | ||
*/ | ||
getMempoolBoxMapping = async ( | ||
address: string, | ||
tokenId?: string | ||
): Promise<Map<string, BitcoinUtxo | undefined>> => { | ||
// chaining transaction won't be done in BitcoinChain | ||
// due to heavy size of transaction in mempool | ||
return new Map<string, BitcoinUtxo | undefined>(); | ||
}; | ||
|
||
/** | ||
* extracts box id and assets of a box | ||
* @param box the box | ||
* @returns an object containing the box id and assets | ||
*/ | ||
protected getBoxInfo = (box: BitcoinUtxo): BoxInfo => { | ||
throw Error(`not implemented`); | ||
}; | ||
} | ||
|
||
export default BitcoinChain; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { | ||
PaymentTransaction, | ||
TransactionType, | ||
} from '@rosen-chains/abstract-chain'; | ||
import { BITCOIN_CHAIN } from './constants'; | ||
import { BitcoinTransactionJsonModel } from './types'; | ||
|
||
class BitcoinTransaction extends PaymentTransaction { | ||
inputUtxos: Array<string>; | ||
|
||
constructor( | ||
txId: string, | ||
eventId: string, | ||
txBytes: Uint8Array, | ||
txType: TransactionType, | ||
inputUtxos: Array<string> | ||
) { | ||
super(BITCOIN_CHAIN, txId, eventId, txBytes, txType); | ||
this.inputUtxos = inputUtxos; | ||
} | ||
|
||
/** | ||
* converts json representation of the payment transaction to BitcoinTransaction | ||
* @returns BitcoinTransaction object | ||
*/ | ||
static fromJson = (jsonString: string): BitcoinTransaction => { | ||
const obj = JSON.parse(jsonString) as BitcoinTransactionJsonModel; | ||
return new BitcoinTransaction( | ||
obj.txId, | ||
obj.eventId, | ||
Buffer.from(obj.txBytes, 'hex'), | ||
obj.txType as TransactionType, | ||
obj.inputUtxos | ||
); | ||
}; | ||
|
||
/** | ||
* converts BitcoinTransaction to json | ||
* @returns json representation of the payment transaction | ||
*/ | ||
toJson = (): string => { | ||
return JSON.stringify({ | ||
network: this.network, | ||
eventId: this.eventId, | ||
txBytes: this.getTxHexString(), | ||
txId: this.txId, | ||
txType: this.txType, | ||
inputUtxos: this.inputUtxos, | ||
}); | ||
}; | ||
|
||
/** | ||
* @returns transaction hex string | ||
*/ | ||
getTxHexString = () => { | ||
return Buffer.from(this.txBytes).toString('hex'); | ||
}; | ||
} | ||
|
||
export default BitcoinTransaction; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const BITCOIN_CHAIN = 'bitcoin'; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { default as BitcoinChain } from './BitcoinChain'; | ||
export { default as AbstractBitcoinNetwork } from './network/AbstractBitcoinNetwork'; | ||
export { default as BitcoinTransaction } from './BitcoinTransaction'; | ||
export * from './types'; | ||
export * from './constants'; |
38 changes: 38 additions & 0 deletions
38
packages/chains/bitcoin/lib/network/AbstractBitcoinNetwork.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { AbstractUtxoChainNetwork } from '@rosen-chains/abstract-chain'; | ||
import { Psbt } from 'bitcoinjs-lib'; | ||
import { BitcoinTx, BitcoinUtxo } from '../types'; | ||
|
||
abstract class AbstractBitcoinNetwork extends AbstractUtxoChainNetwork< | ||
BitcoinTx, | ||
BitcoinUtxo | ||
> { | ||
// TODO: uncomment this line (local:ergo/rosen-bridge/utils#169) | ||
// abstract extractor: BitcoinRosenExtractor; | ||
|
||
/** | ||
* submits a transaction | ||
* @param transaction the transaction | ||
*/ | ||
abstract submitTransaction: (transaction: Psbt) => Promise<void>; | ||
|
||
/** | ||
* gets a utxo from the network | ||
* @param boxId the id of Utxo (txId + . + index) | ||
* @returns the utxo in BitcoinUtxo format | ||
*/ | ||
abstract getUtxo: (boxId: string) => Promise<BitcoinUtxo>; | ||
|
||
/** | ||
* gets current fee ratio of the network | ||
* @returns | ||
*/ | ||
abstract getFeeRatio: () => Promise<bigint>; | ||
|
||
/** | ||
* gets id of transactions in mempool | ||
* @returns | ||
*/ | ||
abstract getMempoolTxIds: () => Promise<Array<string>>; | ||
} | ||
|
||
export default AbstractBitcoinNetwork; |
Oops, something went wrong.