depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

commit b80fee7cc3a059eda7ae14d041d25e7b7b093733
parent 81f01ae261ec1c457f7b7b8b9a1f59383bb34a32
Author: Antoine A <>
Date:   Tue, 16 Nov 2021 16:00:30 +0100

Draft refund steps

Diffstat:
Mresearch.md | 12++++++++++++
Msrc/lib.rs | 128++++++++++++++++++++++++++++++++++++++++++-------------------------------------
2 files changed, 80 insertions(+), 60 deletions(-)

diff --git a/research.md b/research.md @@ -124,6 +124,18 @@ Bitcoin Metadata. Journal of Grid Computing. 10.1007/s10723-019-09473-3. OP_RETURN test +## Refund + +- get raw transaction details +- remove refund fee from sent amount +- filter out fake addresses and self address (the onde in 'details') +- send an equal part to each remaining addresses making them pay transactions + fees +- ignore insufficient_funds + +RPC error code : +https://github.com/bitcoin/bitcoin/blob/master/src/rpc/protocol.h + ## Ethereum - A transaction is from one address to another diff --git a/src/lib.rs b/src/lib.rs @@ -63,6 +63,67 @@ pub fn encode_segwit_key(hrp: &str, msg: &[u8; 32]) -> [String; 2] { ] } +#[derive(Debug, Clone)] +pub enum DecodeError { + TooManyAddress, + MissingSeqWitAddress, + MagicIdCollision, +} + +/// Decode a 32B key into from adresses +pub fn decode_segwit_msg(segwit_addrs: &[impl AsRef<str>]) -> Result<[u8; 32], DecodeError> { + if segwit_addrs.len() < 2 { + return Err(DecodeError::MissingSeqWitAddress); + } + + if segwit_addrs.len() > 4 { + return Err(DecodeError::TooManyAddress); + } + + // Extract parts from every addresses + let decoded: Vec<(bool, [u8; 4], [u8; 16])> = segwit_addrs + .into_iter() + .filter_map(|addr| { + bech32::decode(addr.as_ref()).ok().and_then(|(_, wp, _)| { + // Skip version + let pg: Vec<u8> = Vec::from_base32(&wp[1..]).unwrap(); + if pg.len() == 20 { + let mut magic_id: [u8; 4] = pg[..4].try_into().unwrap(); + let key_half: [u8; 16] = pg[4..].try_into().unwrap(); + let is_first = !pg[0] & 0b1000_0000 == 0; + // Clear first bit + magic_id[0] &= 0b0111_1111; + Some((is_first, magic_id, key_half)) + } else { + None + } + }) + }) + .collect(); + + if decoded.len() < 2 { + return Err(DecodeError::MissingSeqWitAddress); + } + // Keep only the addresses with duplicated magic id + let matches: Vec<&(bool, [u8; 4], [u8; 16])> = decoded + .iter() + .filter(|(_, magic, _)| { + decoded + .iter() + .filter(|(_, other, _)| other == magic) + .count() + > 1 + }) + .collect(); + assert_eq!(matches.len(), 2, "Magic ID collision"); + + let mut key = [0; 32]; + for (is_first, _, half) in matches { + key[*is_first as usize * 16..][..16].copy_from_slice(half); + } + Ok(key) +} + /// Send transaction to multiple recipients fn send_many(client: &Client, recipients: Vec<(String, Amount)>) -> bitcoincore_rpc::Result<Txid> { let amounts = Value::Object( @@ -88,6 +149,13 @@ fn send_many(client: &Client, recipients: Vec<(String, Amount)>) -> bitcoincore_ ) } +pub fn refund(rpc: &Client, id: &Txid) -> bitcoincore_rpc::Result<Txid> { + let tx = rpc.get_transaction(id, None)?; + //tx.details. + //assert!(tx) + Ok(*id) +} + /// An extended bitcoincore JSON-RPC api client who can send and retrieve metadata with their transaction pub trait ClientExtended { // TODO error handling for get functions @@ -213,66 +281,6 @@ impl ClientExtended for Client { } } -#[derive(Debug, Clone)] -pub enum DecodeError { - TooManyAddress, - MissingSeqWitAddress, - MagicIdCollision, -} - -pub fn decode_segwit_msg(segwit_addrs: &[impl AsRef<str>]) -> Result<[u8; 32], DecodeError> { - if segwit_addrs.len() < 2 { - return Err(DecodeError::MissingSeqWitAddress); - } - - if segwit_addrs.len() > 4 { - return Err(DecodeError::TooManyAddress); - } - - // Extract parts from every addresses - let decoded: Vec<(bool, [u8; 4], [u8; 16])> = segwit_addrs - .into_iter() - .filter_map(|addr| { - bech32::decode(addr.as_ref()).ok().and_then(|(_, wp, _)| { - // Skip version - let pg: Vec<u8> = Vec::from_base32(&wp[1..]).unwrap(); - if pg.len() == 20 { - let mut magic_id: [u8; 4] = pg[..4].try_into().unwrap(); - let key_half: [u8; 16] = pg[4..].try_into().unwrap(); - let is_first = !pg[0] & 0b1000_0000 == 0; - // Clear first bit - magic_id[0] &= 0b0111_1111; - Some((is_first, magic_id, key_half)) - } else { - None - } - }) - }) - .collect(); - - if decoded.len() < 2 { - return Err(DecodeError::MissingSeqWitAddress); - } - // Keep only the addresses with duplicated magic id - let matches: Vec<&(bool, [u8; 4], [u8; 16])> = decoded - .iter() - .filter(|(_, magic, _)| { - decoded - .iter() - .filter(|(_, other, _)| other == magic) - .count() - > 1 - }) - .collect(); - assert_eq!(matches.len(), 2, "Magic ID collision"); - - let mut key = [0; 32]; - for (is_first, _, half) in matches { - key[*is_first as usize * 16..][..16].copy_from_slice(half); - } - Ok(key) -} - pub mod utils { use crate::{encode_segwit_addr, encode_segwit_key};