-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Bitcoin/Rust] Calculate transaction fees (#3317)
- Loading branch information
Showing
17 changed files
with
386 additions
and
16 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
...d/app/src/androidTest/java/com/trustwallet/core/app/blockchains/bitcoin/TestBitcoinFee.kt
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,47 @@ | ||
package com.trustwallet.core.app.blockchains.bitcoin | ||
|
||
import com.trustwallet.core.app.utils.Numeric | ||
import com.trustwallet.core.app.utils.toHexBytes | ||
import org.junit.Assert.assertEquals | ||
import org.junit.Test | ||
import wallet.core.jni.BitcoinFee | ||
|
||
class TestBitcoinFee { | ||
|
||
init { | ||
System.loadLibrary("TrustWalletCore") | ||
} | ||
|
||
@Test | ||
fun P2pkhCalculateFee() { | ||
val satVb: Long = 10 | ||
val tx = Numeric.hexStringToByteArray("02000000017be4e642bb278018ab12277de9427773ad1c5f5b1d164a157e0d99aa48dc1c1e000000006a473044022078eda020d4b86fcb3af78ef919912e6d79b81164dbbb0b0b96da6ac58a2de4b102201a5fd8d48734d5a02371c4b5ee551a69dca3842edbf577d863cf8ae9fdbbd4590121036666dd712e05a487916384bfcd5973eb53e8038eccbbf97f7eed775b87389536ffffffff01c0aff629010000001976a9145eaaa4f458f9158f86afcba08dd7448d27045e3d88ac00000000") | ||
var fee = BitcoinFee.calculateFee(tx, satVb) | ||
|
||
assertEquals(fee, 191 * satVb) | ||
} | ||
|
||
@Test | ||
fun P2wpkhCalculateFee() { | ||
val satVb: Long = 12 | ||
val tx = Numeric.hexStringToByteArray("020000000111b9f62923af73e297abb69f749e7a1aa2735fbdfd32ac5f6aa89e5c96841c18000000006b483045022100df9ed0b662b759e68b89a42e7144cddf787782a7129d4df05642dd825930e6e6022051a08f577f11cc7390684bbad2951a6374072253ffcf2468d14035ed0d8cd6490121028d7dce6d72fb8f7af9566616c6436349c67ad379f2404dd66fe7085fe0fba28fffffffff01c0aff629010000001600140d0e1cec6c2babe8badde5e9b3dea667da90036d00000000") | ||
var fee = BitcoinFee.calculateFee(tx, satVb) | ||
|
||
assertEquals(fee, 189 * satVb) | ||
} | ||
|
||
@Test | ||
// Metadata can be observed live on: | ||
// https://www.blockchain.com/explorer/transactions/btc/797d17d47ae66e598341f9dfdea020b04d4017dcf9cc33f0e51f7a6082171fb1 | ||
// | ||
// Fee/VB 19.608 sat/vByte | ||
// Size 235 Bytes | ||
// Weight 610 | ||
fun Brc20TransferCommitCalculateFee() { | ||
val satVb: Long = 19 | ||
val tx = Numeric.hexStringToByteArray("02000000000101089098890d2653567b9e8df2d1fbe5c3c8bf1910ca7184e301db0ad3b495c88e0100000000ffffffff02581b000000000000225120e8b706a97732e705e22ae7710703e7f589ed13c636324461afa443016134cc051040000000000000160014e311b8d6ddff856ce8e9a4e03bc6d4fe5050a83d02483045022100a44aa28446a9a886b378a4a65e32ad9a3108870bd725dc6105160bed4f317097022069e9de36422e4ce2e42b39884aa5f626f8f94194d1013007d5a1ea9220a06dce0121030f209b6ada5edb42c77fd2bc64ad650ae38314c8f451f3e36d80bc8e26f132cb00000000") | ||
var fee = BitcoinFee.calculateFee(tx, satVb) | ||
|
||
assertEquals(fee, 153 * satVb) // 153 = ceil(610/4) | ||
} | ||
} |
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,19 @@ | ||
// Copyright © 2017-2023 Trust Wallet. | ||
// | ||
// This file is part of Trust. The full Trust copyright notice, including | ||
// terms governing use, modification, and redistribution, is contained in the | ||
// file LICENSE at the root of the source code distribution tree. | ||
|
||
#pragma once | ||
|
||
#include "TWData.h" | ||
|
||
TW_EXTERN_C_BEGIN | ||
|
||
TW_EXPORT_CLASS | ||
struct TWBitcoinFee; | ||
|
||
TW_EXPORT_STATIC_METHOD | ||
uint64_t TWBitcoinFeeCalculateFee(TWData* _Nonnull data, uint64_t satVb); | ||
|
||
TW_EXTERN_C_END |
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
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,104 @@ | ||
use crate::calculate_fee; | ||
use bitcoin::{consensus::Decodable, Transaction}; | ||
|
||
// 10 satoshis per virtual byte. | ||
const SAT_VB: u64 = 12; | ||
|
||
fn decode_tx(raw: &str) -> Transaction { | ||
let hex = tw_encoding::hex::decode(raw).unwrap(); | ||
Transaction::consensus_decode(&mut hex.as_slice()).unwrap() | ||
} | ||
|
||
#[test] | ||
fn p2pkh_fee() { | ||
let tx = decode_tx(super::p2pkh::TX_RAW); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 191); | ||
assert_eq!(fee, 191 * SAT_VB); | ||
} | ||
|
||
#[test] | ||
fn p2wpkh_fee() { | ||
let tx = decode_tx(super::p2wpkh::TX_RAW); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 189); | ||
assert_eq!(fee, 189 * SAT_VB); | ||
} | ||
|
||
#[test] | ||
fn brc20_commit_fee() { | ||
// Metadata can be observed live on: | ||
// https://www.blockchain.com/explorer/transactions/btc/797d17d47ae66e598341f9dfdea020b04d4017dcf9cc33f0e51f7a6082171fb1 | ||
// | ||
// Fee/VB 19.608 sat/vByte | ||
// Size 235 Bytes | ||
// Weight 610 | ||
|
||
// 19 satoshis per vbyte. | ||
const SAT_19_VB: u64 = 19; | ||
|
||
let tx = decode_tx(super::brc20_transfer::COMMIT_TX_RAW); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_19_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 153); // 153 = ceil(610/4) | ||
assert_eq!(fee, 153 * SAT_19_VB); | ||
} | ||
|
||
#[test] | ||
fn brc20_reveal_fee() { | ||
// Metadata can be observed live on: | ||
// https://www.blockchain.com/explorer/transactions/btc/7046dc2689a27e143ea2ad1039710885147e9485ab6453fa7e87464aa7dd3eca | ||
// | ||
// Fee/VB 49.267 sat/vByte | ||
// Size 276 Bytes | ||
// Weight 522 | ||
|
||
// 49 satoshis per vbyte (slightly overpaid here...) | ||
const SAT_49_VB: u64 = 49; | ||
|
||
let tx = decode_tx(super::brc20_transfer::REVEAL_TX_RAW); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_49_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 131); // 131 = ceil(522/4) | ||
assert_eq!(fee, 131 * SAT_49_VB); | ||
} | ||
|
||
#[test] | ||
fn ordinal_nft_commit_fee() { | ||
// Metadata can be observed live on: | ||
// https://www.blockchain.com/explorer/transactions/btc/f1e708e5c5847339e16accf8716c14b33717c14d6fe68f9db36627cecbde7117 | ||
// | ||
// Fee/VB 10.656 sat/vByte | ||
// Size 203 Bytes | ||
// Weight 485 | ||
|
||
// 19 satoshis per vbyte. | ||
const SAT_10_VB: u64 = 10; | ||
|
||
let tx = decode_tx(super::nft::COMMIT_RAW_TX); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_10_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 122); // 122 = ceil(485/4) | ||
assert_eq!(fee, 122 * SAT_10_VB); | ||
} | ||
|
||
#[test] | ||
fn ordinal_nft_reveal_fee() { | ||
// Metadata can be observed live on: | ||
// https://www.blockchain.com/explorer/transactions/btc/173f8350b722243d44cc8db5584de76b432eb6d0888d9e66e662db51584f44ac | ||
// | ||
// Fee/VB 15.133 sat/vByte | ||
// Size 7'829 Bytes | ||
// Weight 8'075 | ||
|
||
// 19 satoshis per vbyte. | ||
const SAT_15_VB: u64 = 15; | ||
|
||
let tx = decode_tx(super::nft::REVEAL_RAW_TX); | ||
|
||
let (weight, fee) = calculate_fee(&tx, SAT_15_VB); | ||
assert_eq!(weight.to_vbytes_ceil(), 2019); // 2019 = ceil(8_075/4) | ||
assert_eq!(fee, 2019 * SAT_15_VB); | ||
} |
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,48 @@ | ||
use crate::ffi::tw_bitcoin_calculate_transaction_fee; | ||
use tw_memory::ffi::c_result::CUInt64Result; | ||
|
||
/// Convenience wrapper. | ||
fn call_ffi_calculate_fee(hex: &str, sat_vb: u64) -> u64 { | ||
let hex = tw_encoding::hex::decode(hex).unwrap(); | ||
|
||
let res: CUInt64Result = | ||
unsafe { tw_bitcoin_calculate_transaction_fee(hex.as_ptr(), hex.len(), sat_vb) }; | ||
|
||
res.unwrap() | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_p2pkh_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::p2pkh::TX_RAW, 10); | ||
assert_eq!(fee, 191 * 10); | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_p2wpkh_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::p2wpkh::TX_RAW, 10); | ||
assert_eq!(fee, 189 * 10); | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_brc20_commit_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::brc20_transfer::COMMIT_TX_RAW, 19); | ||
assert_eq!(fee, 153 * 19); | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_brc20_reveal_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::brc20_transfer::REVEAL_TX_RAW, 49); | ||
assert_eq!(fee, 131 * 49); | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_ordinal_nft_commit_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::nft::COMMIT_RAW_TX, 10); | ||
assert_eq!(fee, 122 * 10); | ||
} | ||
|
||
#[test] | ||
fn ffi_calculate_ordinal_nft_reveal_fee() { | ||
let fee = call_ffi_calculate_fee(crate::tests::nft::REVEAL_RAW_TX, 15); | ||
assert_eq!(fee, 2019 * 15); | ||
} |
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 |
---|---|---|
@@ -1,4 +1,5 @@ | ||
mod brc20_transfer; | ||
mod fees; | ||
mod nft; | ||
mod scripts; | ||
mod transaction; | ||
|
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 |
---|---|---|
@@ -1,6 +1,7 @@ | ||
mod address; | ||
mod brc20_transfer; | ||
mod data; | ||
mod fee; | ||
mod ffi; | ||
mod nft; | ||
mod p2pkh; | ||
|
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
Oops, something went wrong.