Skip to content

Commit

Permalink
Init Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AlirezaMoseni committed May 31, 2024
1 parent ed819ac commit d37fec5
Show file tree
Hide file tree
Showing 19 changed files with 18,571 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Project 1/Task 1. Generating Wallet Address/Q1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import os
import bech32
import base58
import base64
import ecdsa
import hashlib


def address_generation():
private_key = os.urandom(32).hex()
sk = ecdsa.SigningKey.from_string(
bytes.fromhex(private_key), ecdsa.SECP256k1)
vk = sk.verifying_key
public_key = (b'\x04' + vk.to_string()).hex()
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(bytes.fromhex(public_key)).digest())
middle = b'\x6f' + ripemd160.digest()
checksum = hashlib.sha256(hashlib.sha256(middle).digest()).digest()[:4]
binary_addr = middle + checksum
addr = base58.b58encode(binary_addr)
return private_key, public_key, addr


def wif_formatter(private_key):
wif_private_key = b'\x80' + bytes.fromhex(private_key) + b'\x01'
checksum2 = hashlib.sha256(hashlib.sha256(
wif_private_key).digest()).digest()[:4]
wif_private_key = wif_private_key + checksum2
return wif_private_key


prv_key, pub_key, addr = address_generation()
print("BTC address: " + addr.decode("utf-8"))


wif_prv_key = wif_formatter(prv_key)
print("wif private key in base 58 : " +
base58.b58encode(wif_prv_key).decode("utf-8"))
39 changes: 39 additions & 0 deletions Project 1/Task 1. Generating Wallet Address/Q2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os
import bech32
import base58
import base64
import ecdsa
import hashlib


def address_generation():
private_key = os.urandom(32).hex()
sk = ecdsa.SigningKey.from_string(
bytes.fromhex(private_key), ecdsa.SECP256k1)
vk = sk.verifying_key
public_key = (b'\x04' + vk.to_string()).hex()
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(bytes.fromhex(public_key)).digest())
middle = b'\x6f' + ripemd160.digest()
checksum = hashlib.sha256(hashlib.sha256(middle).digest()).digest()[:4]
binary_addr = middle + checksum
addr = base58.b58encode(binary_addr)
return private_key, public_key, addr


def generate_vanuty_address(key):
while True:
prv_key, _, addr = address_generation()
vanitystring = addr.decode("utf-8")[1:4]
if vanitystring in key:
wif_private_key = b'\x80' + bytes.fromhex(prv_key) + b'\x01'
checksum2 = hashlib.sha256(hashlib.sha256(
wif_private_key).digest()).digest()[:4]
wif_private_key = wif_private_key + checksum2
return wif_private_key, addr


wif_prv_key, addr = generate_vanuty_address(key="moh")
print("found the address")
print("BTC address: " + addr.decode("utf-8"))
print("wif private key in base 58 : " + base58.b58encode(wif_prv_key).decode("utf-8"))
9 changes: 9 additions & 0 deletions Project 1/Task 1. Generating Wallet Address/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### **Task1: Generating Valid Bitcoin Addresses**

#### Q1: Test Network Address Generation

`Q1.py` will generate a Bitcoin address for the test network (testnet). The output is in Base58 format, along with the corresponding private key in WIF (Wallet Import Format).

#### Q2: Vanity Address Generation

`Q2.py` will generate a “vanity address.” A vanity address starts with specific characters of your choice. Given three input characters, the code produces an address where those characters appear in positions 2 to 4 (since the first character follows a specific Bitcoin format). The output is again in Base58 format, along with the corresponding private key in WIF.
75 changes: 75 additions & 0 deletions Project 1/Task 2. Bitcoin Transaction/Q1.P1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import bitcoin.wallet ,hashlib
from bitcoin.core import COIN, b2lx, serialize, x, lx, b2x
from utils import *
from Crypto.Hash import RIPEMD160

bitcoin.SelectParams("testnet")
my_private_key = bitcoin.wallet.CBitcoinSecret("cS3Ykn28yDPagMXBgUNkrSdxzT3Hii5g2LgAQb2yN4kWJwWJ99Gg") # Private key in WIF format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
my_public_key = my_private_key.pub
my_address = bitcoin.wallet.P2PKHBitcoinAddress.from_pubkey(my_public_key)
# destination_address = bitcoin.wallet.CBitcoinAddress('') # Destination address (recipient of the money)
# destination_address2 = bitcoin.wallet.CBitcoinAddress('') # Destination address (recipient of the money)

def P2PKH_scriptPubKey(address):

return [ OP_DUP , OP_HASH160 ,address , OP_EQUALVERIFY ,OP_CHECKSIG]

def P2PKH_scriptPubKey_NOBODY():

return [OP_RETURN]

def P2PKH_scriptPubKey_EVERYBODY():

return []

def P2PKH_scriptSig(txin, txout, txin_scriptPubKey):

signature = create_OP_CHECKSIG_signature(txin, txout, txin_scriptPubKey, my_private_key)

return [signature , my_public_key]


def send_from_P2PKH_transaction(amount_to_send,amount_to_send2, txid_to_spend, utxo_index,
txout_scriptPubKey,txout_scriptPubKey2 ):
txout = create_txout(amount_to_send, txout_scriptPubKey)
txout2 = create_txout(amount_to_send2, txout_scriptPubKey2)
txin_scriptPubKey = P2PKH_scriptPubKey(my_address)
txin = create_txin(txid_to_spend, utxo_index)
txin_scriptSig = P2PKH_scriptSig(txin, [txout,txout2] , txin_scriptPubKey)
new_tx = create_signed_transaction(txin, [txout,txout2], txin_scriptPubKey,
txin_scriptSig)
return broadcast_transaction(new_tx)

def create_OP_CHECKSIG_signature(txin, txout, txin_scriptPubKey, seckey):
tx = CMutableTransaction([txin], [txout[0],txout[1]])
sighash = SignatureHash(CScript(txin_scriptPubKey), tx,
0, SIGHASH_ALL)
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
return sig


def create_signed_transaction(txin, txout, txin_scriptPubKey,txin_scriptSig):
tx = CMutableTransaction([txin], [txout[0],txout[1]])
txin.scriptSig = CScript(txin_scriptSig)
VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey),
tx, 0, (SCRIPT_VERIFY_P2SH,))
return tx

if __name__ == '__main__':
######################################################################
amount_to_send = 0.00002
amount_to_send2 = 0.00007
txid_to_spend = ('3d628c35a628f963b61c0c323da805ffacf2d8d5769f06cf47983abb637f37aa') # TxHash of UTXO
utxo_index = 1 # UTXO index among transaction outputs
######################################################################

print(my_address) # Prints your address in base58
print(my_public_key.hex()) # Print your public key in hex
print(my_private_key.hex()) # Print your private key in hex
txout_scriptPubKey = P2PKH_scriptPubKey_NOBODY()
txout_scriptPubKey2 = P2PKH_scriptPubKey_EVERYBODY()
response = send_from_P2PKH_transaction(amount_to_send,amount_to_send2, txid_to_spend, utxo_index,
txout_scriptPubKey,txout_scriptPubKey2)
print(response.status_code, response.reason)
print(response.text) # Report the hash of transaction which is printed in this section result

69 changes: 69 additions & 0 deletions Project 1/Task 2. Bitcoin Transaction/Q1.P2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import bitcoin.wallet
import hashlib
from bitcoin.core import COIN, b2lx, serialize, x, lx, b2x
from utils import *
from Crypto.Hash import RIPEMD160

bitcoin.SelectParams("testnet")
# Private key in WIF format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
my_private_key = bitcoin.wallet.CBitcoinSecret(
"cS3Ykn28yDPagMXBgUNkrSdxzT3Hii5g2LgAQb2yN4kWJwWJ99Gg")
my_public_key = my_private_key.pub
my_address = bitcoin.wallet.P2PKHBitcoinAddress.from_pubkey(my_public_key)
destination_address = bitcoin.wallet.CBitcoinAddress(
'mpNvmLAb9hYJ1q2BFcCbnsfKNNLGxVtW8o') # Destination address (recipient of the money)


def P2PKH_scriptPubKey(address):

return [OP_DUP, OP_HASH160, address, OP_EQUALVERIFY, OP_CHECKSIG]


def P2PKH_scriptPubKey_EVERYBODY(address):

return []


def P2PKH_scriptSig_EVERYBODY():
return [OP_TRUE]


def P2PKH_scriptSig(txin, txout, txin_scriptPubKey):

signature = create_OP_CHECKSIG_signature(
txin, txout, txin_scriptPubKey, my_private_key)

return []


def send_from_P2PKH_transaction(amount_to_send, txid_to_spend, utxo_index,
txout_scriptPubKey):
txout = create_txout(amount_to_send, txout_scriptPubKey)
txin_scriptPubKey = P2PKH_scriptPubKey_EVERYBODY(my_address)
txin = create_txin(txid_to_spend, utxo_index)

txin_scriptSig = P2PKH_scriptSig_EVERYBODY()

new_tx = create_signed_transaction(txin, txout, txin_scriptPubKey,
txin_scriptSig)

return broadcast_transaction(new_tx)


if __name__ == '__main__':
######################################################################
amount_to_send = 0.00006
# TxHash of UTXO
txid_to_spend = ('a34d95fba359ef6a5359579157947e27450187004d742b4b67214df93d10d1a6')
utxo_index = 1 # UTXO index among transaction outputs
######################################################################

print(my_address) # Prints your address in base58
print(my_public_key.hex()) # Print your public key in hex
print(my_private_key.hex()) # Print your private key in hex
txout_scriptPubKey = P2PKH_scriptPubKey(destination_address)
response = send_from_P2PKH_transaction(amount_to_send, txid_to_spend, utxo_index,
txout_scriptPubKey)
print(response.status_code, response.reason)
# Report the hash of transaction which is printed in this section result
print(response.text)
57 changes: 57 additions & 0 deletions Project 1/Task 2. Bitcoin Transaction/Q2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import bitcoin.wallet ,hashlib
from bitcoin.core import COIN, b2lx, serialize, x, lx, b2x
from utils import *
from Crypto.Hash import RIPEMD160

bitcoin.SelectParams("testnet")
my_private_key = bitcoin.wallet.CBitcoinSecret("cS3Ykn28yDPagMXBgUNkrSdxzT3Hii5g2LgAQb2yN4kWJwWJ99Gg") # Private key in WIF format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
my_public_key = my_private_key.pub
my_address = bitcoin.wallet.P2PKHBitcoinAddress.from_pubkey(my_public_key)
destination_address1 = bitcoin.wallet.CBitcoinAddress('mrrJH8rfQswojwztr2pGNsdbdz6hELXg85') # Destination address (recipient of the money)
destination_address2 = bitcoin.wallet.CBitcoinAddress('mxg8CPu3UT1ZvfiaRBW12HKouoCW1oqAvp') # Destination address (recipient of the money)
destination_address3 = bitcoin.wallet.CBitcoinAddress('msgjfBCqVwSvTvzBiLpYQGD1MHXbfY5Ds5') # Destination address (recipient of the money)

def P2PKH_scriptPubKey(address):

return [ OP_DUP , OP_HASH160 ,address , OP_EQUALVERIFY ,OP_CHECKSIG]

def P2MS_scriptPubKey(pkey1, pkey2, pkey3):

return [OP_2, pkey1, pkey2, pkey3, OP_3 , OP_CHECKMULTISIG]


def P2PKH_scriptSig(txin, txout, txin_scriptPubKey):

signature = create_OP_CHECKSIG_signature(txin, txout, txin_scriptPubKey, my_private_key)

return [signature , my_public_key]


def send_from_P2PKH_transaction(amount_to_send, txid_to_spend, utxo_index,
txout_scriptPubKey ):
txout = create_txout(amount_to_send, txout_scriptPubKey)
txin_scriptPubKey = P2PKH_scriptPubKey(my_address)
txin = create_txin(txid_to_spend, utxo_index)
txin_scriptSig = P2PKH_scriptSig(txin, txout, txin_scriptPubKey)

new_tx = create_signed_transaction(txin, txout ,txin_scriptPubKey,
txin_scriptSig)

return broadcast_transaction(new_tx)


if __name__ == '__main__':
######################################################################
amount_to_send = 0.0009
txid_to_spend = ('3b27769a29955c47fcc209445316dd38c40b9ac3d6cc214186465b7050a6fee1') # TxHash of UTXO
utxo_index = 0 # UTXO index among transaction outputs
######################################################################

print(my_address) # Prints your address in base58
print(my_public_key.hex()) # Print your public key in hex
print(my_private_key.hex()) # Print your private key in hex
txout_scriptPubKey = P2MS_scriptPubKey(destination_address1, destination_address2, destination_address3)
response = send_from_P2PKH_transaction(amount_to_send, txid_to_spend, utxo_index,
txout_scriptPubKey)
print(response.status_code, response.reason)
print(response.text) # Report the hash of transaction which is printed in this section result
13 changes: 13 additions & 0 deletions Project 1/Task 2. Bitcoin Transaction/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### **Task 2: Bitcoin Transaction Handling with bitcoinlib-python**

In this task, we utilize the `bitcoinlib-python` library to perform Bitcoin transactions on the test network (testnet). The library provides various functions for creating different types of transactions.

#### Q1: Creating a Simple Transaction

In part 1, we create a transaction with one input and two output which The first output cannot be spent by anyone and the second output can be spent by anyone.

In part 2, we spend the spendable output of this transaction in another transaction and return that to our original address as P2PKH output.

#### Q2: Multisig Transaction

in `Q2.py`, 3 addresses are generated first. Next, a transaction with one input and one output of P2MS type is generated which can be spent by 2 of the 3 generated addresses. Finally, using another transaction, this output is spent and the money is returned to the original address.
48 changes: 48 additions & 0 deletions Project 1/Task 2. Bitcoin Transaction/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import requests

from bitcoin.core import b2x, lx, COIN, COutPoint, CMutableTxOut, CMutableTxIn, CMutableTransaction, Hash160
from bitcoin.core.script import *
from bitcoin.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH


def send_from_custom_transaction(
amount_to_send, txid_to_spend, utxo_index,
txin_scriptPubKey, txin_scriptSig, txout_scriptPubKey):
txout = create_txout(amount_to_send, txout_scriptPubKey)
txin = create_txin(txid_to_spend, utxo_index)
new_tx = create_signed_transaction(txin, txout, txin_scriptPubKey,
txin_scriptSig)
return broadcast_transaction(new_tx)


def create_txin(txid, utxo_index):
return CMutableTxIn(COutPoint(lx(txid), utxo_index))


def create_txout(amount, scriptPubKey):
return CMutableTxOut(amount*COIN, CScript(scriptPubKey))


def create_OP_CHECKSIG_signature(txin, txout, txin_scriptPubKey, seckey):
tx = CMutableTransaction([txin], [txout])
sighash = SignatureHash(CScript(txin_scriptPubKey), tx,
0, SIGHASH_ALL)
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
return sig


def create_signed_transaction(txin, txout, txin_scriptPubKey,txin_scriptSig):
tx = CMutableTransaction([txin], [txout])
txin.scriptSig = CScript(txin_scriptSig)
VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey),
tx, 0, (SCRIPT_VERIFY_P2SH,))
return tx


def broadcast_transaction(tx):
raw_transaction = b2x(tx.serialize())
headers = {'content-type': 'application/x-www-form-urlencoded'}
return requests.post(
'https://api.blockcypher.com/v1/btc/test3/txs/push',
headers=headers,
data='{"tx": "%s"}' % raw_transaction)
3 changes: 3 additions & 0 deletions Project 1/Task 3. Mining Block/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### **Task 3: Mining a Bitcoin block**

In this task, a valid Bitcoin block is created locally.
Loading

0 comments on commit d37fec5

Please sign in to comment.