Skip to content

Commit 1e649f6

Browse files
authored
feat: add sign_bytes method to generate data that needs to be signed (#38)
1 parent 4351e46 commit 1e649f6

File tree

6 files changed

+51
-12
lines changed

6 files changed

+51
-12
lines changed

examples/example_get_node_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def main() -> None:
1010
# Creating a stub from channel
1111
stub = NetworkStub(channel)
1212

13-
# Initialize a request and call get consensus info method
13+
# Initialize a request and call get node info method
1414
req = GetNodeInfoRequest()
1515
res = stub.GetNodeInfo(req)
1616

examples/example_multisig.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from pactus.crypto.bls.signature import Signature
22

3+
34
def main() -> None:
45
sig1 = Signature.from_string(
56
"a628a8709fe00366d7150244447cc43e8637d76a20674b006b00f7a61109dab53ba5f1f66cd07219fd1e4a6bc7299d2d"

examples/example_transfer_transaction_bls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def main() -> None:
2222
tx = Transaction.create_transfer_tx(lock_time, sender, receiver, amount, fee, memo)
2323
signed_tx = tx.sign(sec)
2424

25-
print(f"Signed transaction hex: {signed_tx}")
25+
print(f"Signed transaction hex: {signed_tx.hex()}")
2626

2727

2828
if __name__ == "__main__":

examples/example_transfer_transaction_ed25519.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def main() -> None:
2222
tx = Transaction.create_transfer_tx(lock_time, sender, receiver, amount, fee, memo)
2323
signed_tx = tx.sign(sec)
2424

25-
print(f"Signed transaction hex: {signed_tx}")
25+
print(f"Signed transaction hex: {signed_tx.hex()}")
2626

2727

2828
if __name__ == "__main__":

pactus/transaction/transaction.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ def create_withdraw_tx(
7979
return cls(lock_time, fee, memo, payload)
8080

8181
def _get_unsigned_bytes(self, buf: bytes) -> bytes:
82-
"""Get unsigned bytes of the transaction, including the payload."""
82+
"""
83+
Generate the unsigned representation of the transaction,
84+
including flags and payload.
85+
86+
This method appends various transaction components to the buffer
87+
in a specific order, ensuring correct serialization.
88+
"""
8389
encoding.append_uint8(buf, self.flags)
8490
encoding.append_uint8(buf, self.version)
8591
encoding.append_uint32(buf, self.lock_time)
@@ -90,17 +96,37 @@ def _get_unsigned_bytes(self, buf: bytes) -> bytes:
9096

9197
return buf
9298

93-
def sign(self, private_key: PrivateKey) -> str:
94-
"""Make a raw transaction, sign it and return the signed bytes."""
99+
def sign_bytes(self) -> bytes:
100+
"""
101+
Generate the transaction data that needs to be signed.
102+
103+
The signature should be computed over this data, excluding the
104+
transaction flags, which are removed before returning.
105+
"""
106+
buf = bytearray()
107+
sign_bytes = self._get_unsigned_bytes(buf)
108+
109+
return sign_bytes[1:] # flags is not part of the sign bytes.
110+
111+
def sign(self, private_key: PrivateKey) -> bytes:
112+
"""
113+
Generate the signed representation of the transaction,
114+
including the flags, payload, and cryptographic signature.
115+
116+
This method first generates the data needs to be signed,
117+
signs it using the provided private key, and then appends
118+
both the signature and the corresponding public key to ensure
119+
verifiability.
120+
"""
95121
buf = bytearray()
96122

97123
sign_bytes = self._get_unsigned_bytes(buf)
98124
sig = private_key.sign(
99125
bytes(sign_bytes[1:]),
100-
) # flags is not part of the sign bytes.
126+
)
101127
pub = private_key.public_key()
102128

103129
encoding.append_fixed_bytes(buf, sig.raw_bytes())
104130
encoding.append_fixed_bytes(buf, pub.raw_bytes())
105131

106-
return buf.hex()
132+
return buf

tests/test_transaction.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ def test_sign_transfer(self):
2020
tx = Transaction.create_transfer_tx(
2121
lock_time, sender, receiver, amount, fee, memo
2222
)
23-
signed_data = tx.sign(prv)
2423

25-
expected_data = (
24+
signed_data = tx.sign(prv)
25+
expected_signed_data = (
2626
"00" # Flags
2727
"01" # Version
2828
"56341200" # LockTime
@@ -36,9 +36,21 @@ def test_sign_transfer(self):
3636
+ "af0f74917f5065af94727ae9541b0ddcfb5b828a9e016b02498f477ed37fb44d5d882495afb6fd4f9773e4ea9deee436" # Public Key
3737
+ "030c4d61c6e3a1151585e1d838cae1444a438d089ce77e10c492a55f6908125c5be9b236a246e4082d08de564e111e65"
3838
)
39-
4039
self.maxDiff = None
41-
self.assertEqual(expected_data, signed_data)
40+
self.assertEqual(expected_signed_data, signed_data.hex())
41+
42+
sign_bytes = tx.sign_bytes()
43+
expected_sign_bytes = (
44+
"01" # Version
45+
"56341200" # LockTime
46+
"c0843d" # Fee
47+
"0474657374" # Memo
48+
"01" # PayloadType
49+
+ "02a195d7fecba4c636832f1db0cd0ea14db6db8c71" # Sender
50+
+ "025e81869376b54f8a360f48930ea741e3b8771db2" # Receiver
51+
+ "8094ebdc03" # Amount
52+
)
53+
self.assertEqual(expected_sign_bytes, sign_bytes.hex())
4254

4355

4456
if __name__ == "__main__":

0 commit comments

Comments
 (0)