Skip to content

Commit

Permalink
Python Tx Generator (#109)
Browse files Browse the repository at this point in the history
* generator checkpoint

* generator checkpoint

* bug fixes

* krc20 deploy comment

* .pyi

* rust 1.82

* krc20 deploy example cleanup
  • Loading branch information
smartgoo authored Oct 24, 2024
1 parent a1ab06f commit 399b698
Show file tree
Hide file tree
Showing 16 changed files with 943 additions and 30 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ mod panic_handler {
fn stack(error: &Error) -> String;
}

pub fn process(info: &std::panic::PanicInfo) -> String {
pub fn process(info: &std::panic::PanicHookInfo) -> String {
let mut msg = info.to_string();

// Add the error stack to our message.
Expand Down Expand Up @@ -1053,7 +1053,7 @@ mod panic_handler {
impl KaspaCli {
pub fn init_panic_hook(self: &Arc<Self>) {
let this = self.clone();
let handler = move |info: &std::panic::PanicInfo| {
let handler = move |info: &std::panic::PanicHookInfo| {
let msg = panic_handler::process(info);
this.term().writeln(msg.crlf());
panic_handler::console_error(msg);
Expand Down
4 changes: 4 additions & 0 deletions consensus/core/src/hashing/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use super::sighash_type::{self, SigHashType};
#[cfg(feature = "py-sdk")]
use pyo3::prelude::*;
use wasm_bindgen::prelude::*;

/// Kaspa Sighash types allowed by consensus
/// @category Consensus
#[cfg_attr(feature = "py-sdk", pyclass)]
#[wasm_bindgen]
#[derive(Clone, Copy)]
pub enum SighashType {
All,
None,
Expand Down
7 changes: 5 additions & 2 deletions crypto/txscript/src/python/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,13 @@ impl ScriptBuilder {

#[pyo3(name = "encode_pay_to_script_hash_signature_script")]
pub fn pay_to_script_hash_signature_script(&self, signature: String) -> Result<String> {
// PY-TODO use PyBinary
let mut signature_bytes = vec![0u8; signature.len() / 2];
faster_hex::hex_decode(signature.as_bytes(), &mut signature_bytes).unwrap();

let inner = self.inner();
let script = inner.script();
let signature = signature.as_bytes();
let generated_script = standard::pay_to_script_hash_signature_script(script.into(), signature.to_vec())?;
let generated_script = standard::pay_to_script_hash_signature_script(script.into(), signature_bytes)?;

Ok(generated_script.to_hex().into())
}
Expand Down
90 changes: 69 additions & 21 deletions python/examples/transactions/krc20_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,94 @@
RpcClient,
ScriptBuilder,
address_from_script_public_key,
create_transaction,
sign_transaction
create_transactions,
)


async def main():
private_key = PrivateKey("389840d7696e89c38856a066175e8e92697f0cf182b854c883237a50acaf1f69")
keypair = private_key.to_keypair()
address = keypair.to_address("kaspatest")
client = RpcClient(resolver=Resolver(), network='testnet', network_suffix=10)
await client.connect()

private_key = PrivateKey('389840d7696e89c38856a066175e8e92697f0cf182b854c883237a50acaf1f69')
public_key = private_key.to_public_key()
address = public_key.to_address('testnet')
print(f'Address: {address.to_string()}')
print(f'XOnly Pub Key: {public_key.to_x_only_public_key().to_string()}')

######################
# Commit tx

data = {
"p": "krc-20",
"op": "deploy",
"tick": "PYSDK",
"max": "112121115100107",
"lim":" 1000",
'p': 'krc-20',
'op': 'deploy',
'tick': 'TPYSDK',
'max': '112121115100107',
'lim': '1000',
}

script = ScriptBuilder()
script.add_data(keypair.public_key)
script.add_data(public_key.to_x_only_public_key().to_string())
script.add_op(Opcodes.OpCheckSig)
script.add_op(Opcodes.OpFalse)
script.add_op(Opcodes.OpIf)
script.add_data(b"kasplex")
script.add_data(b'kasplex')
script.add_i64(0)
script.add_data(json.dumps(data, separators=(',', ':')).encode('utf-8'))
script.add_op(Opcodes.OpEndIf)
print(f'Script: {script.to_string()}')

print(script.to_string())

p2sh_address = address_from_script_public_key(script.create_pay_to_script_hash_script(), "kaspatest")
print(p2sh_address.to_string())
p2sh_address = address_from_script_public_key(script.create_pay_to_script_hash_script(), 'kaspatest')
print(f'P2SH Address: {p2sh_address.to_string()}')

# TODO tx submission
utxos = await client.get_utxos_by_addresses(request={'addresses': [address]})

######################
commit_txs = create_transactions(
priority_entries=[],
entries=utxos["entries"],
outputs=[{ 'address': p2sh_address.to_string(), 'amount': 1 * 100_000_000 }],
change_address=address,
priority_fee=1 * 100_000_000,
network_id='testnet-10'
)

commit_tx_id = None
for transaction in commit_txs['transactions']:
transaction.sign([private_key], False)
commit_tx_id = await transaction.submit(client)
print('Commit TX ID:', commit_tx_id)

await asyncio.sleep(10)

#####################
# Reveal tx
# TODO

if __name__ == "__main__":
asyncio.run(main())
utxos = await client.get_utxos_by_addresses(request={'addresses': [address]})
reveal_utxos = await client.get_utxos_by_addresses(request={'addresses': [p2sh_address]})

for entry in reveal_utxos['entries']:
if entry['outpoint']['transactionId'] == commit_tx_id:
reveal_utxos = entry

reveal_txs = create_transactions(
priority_entries=[reveal_utxos],
entries=utxos['entries'],
outputs=[],
change_address=address,
priority_fee=1005 * 100_000_000,
network_id='testnet-10'
)

for transaction in reveal_txs['transactions']:
transaction.sign([private_key], False)

commit_output = next((i for i, input in enumerate(transaction.transaction.inputs)
if input.signature_script == ''), None)

if commit_output is not None:
sig = transaction.create_input_signature(commit_output, private_key)
transaction.fill_input(commit_output, script.encode_pay_to_script_hash_signature_script(sig))

print('Reveal TX ID:', await transaction.submit(client))

if __name__ == '__main__':
asyncio.run(main())
Loading

0 comments on commit 399b698

Please sign in to comment.