Skip to content

Commit 531ce23

Browse files
Merge pull request #175 from klever-io/develop
[MAIN] Update version 0.2.25
2 parents cbd1a98 + 8c47428 commit 531ce23

11 files changed

Lines changed: 1054 additions & 51 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ packages/.DS_Store
2626

2727
packages/kos/target
2828
packages/kos/Cargo.lock
29-
packages/kos/.idea
29+
packages/kos/.idea
30+
31+
packages/kos-mobile/.build_cache

Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ homepage = "https://klever.org/"
3636
license = "Apache-2.0"
3737
repository = "https://github.com/kleverio/kos-rs"
3838
rust-version = "1.69.0"
39-
version = "0.2.24"
39+
version = "0.2.25"
4040

4141
[workspace.dependencies]
4242
bech32 = "0.9.1"
@@ -77,7 +77,7 @@ serde_json = "1.0"
7777
thiserror = "1.0"
7878
kos-mobile = { version = "0.1.0", path = "./packages/kos-mobile", default-features = false }
7979
ecies = { version = "0.2.7", default-features = false, features = ["pure"] }
80-
kos = { version = "0.2.24", path = "./packages/kos", default-features = false, features = ["not-ksafe"] }
80+
kos = { version = "0.2.25", path = "./packages/kos", default-features = false, features = ["not-ksafe"] }
8181

8282
# lightning
8383
lwk_common = "0.9.0"

packages/kos-codec/src/chains/eth/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ pub fn encode_for_sign(mut transaction: Transaction) -> Result<Transaction, Chai
3333
Ok(transaction)
3434
}
3535

36-
pub fn encode_for_broadcast(transaction: Transaction) -> Result<Transaction, ChainError> {
36+
pub fn encode_for_broadcast(mut transaction: Transaction) -> Result<Transaction, ChainError> {
3737
let mut eth_tx = EthereumTransaction::decode(&transaction.raw_data)?;
3838

3939
let mut signature_bytes: [u8; 65] = [0; 65];
4040
signature_bytes.copy_from_slice(&transaction.signature[..]);
4141
eth_tx.signature = Some(signature_bytes);
4242

43+
transaction.raw_data = eth_tx.encode()?;
44+
4345
Ok(transaction)
4446
}
4547

@@ -87,6 +89,7 @@ mod test {
8789
hex::encode(result.tx_hash),
8890
"5ed21ed1618c98b5b1814565d8d7a63ebc6425997c75b2b857d8692f0b73a64f"
8991
);
92+
assert_eq!(hex::encode(result.raw_data), "b302f101819e84ae7937b285035f6cccc58252089498de4c83810b87f0e2cd92d80c9fac28c4ded4818568c696991f80c0808080");
9093

9194
tx.signature = vec![
9295
0x30, 0x45, 0x02, 0x21, 0x00, 0xd3, 0x8f, 0x71, 0x94, 0x7b, 0x2c, 0xf5, 0x43, 0x58,
@@ -98,7 +101,7 @@ mod test {
98101

99102
let signed_tx = encode_for_broadcast(tx.clone()).unwrap();
100103

101-
assert_eq!(hex::encode(signed_tx.raw_data), "b302f101819e84ae7937b285035f6cccc58252089498de4c83810b87f0e2cd92d80c9fac28c4ded4818568c696991f80c0808080");
104+
assert_eq!(hex::encode(signed_tx.raw_data), "02f87101819e84ae7937b285035f6cccc58252089498de4c83810b87f0e2cd92d80c9fac28c4ded4818568c696991f80c054a054ad49a590596b77452a01141de380dd50945843f52c7b94718fd30021024530a0ad49a590596b77452a01141de380dd50945843f52c7b94718fd3002102453007");
102105
assert_eq!(
103106
hex::encode(signed_tx.signature),
104107
"3045022100d38f71947b2cf543589450dd80e31d14012a45776b5990a549ad54073045022100d38f71947b2cf543589450dd80e31d14012a45776b5990a549ad54"
@@ -121,6 +124,7 @@ mod test {
121124
hex::encode(result.tx_hash),
122125
"8823151a6987f2625239f058e453f5850e3d800b31f1dd60951a7e36e0769c2e"
123126
);
127+
assert_eq!(hex::encode(result.raw_data), "b87602f8730182014f84147b7eeb85084ec9f83f8301450994dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000004cbeee256240c92a9ad920ea6f4d7df6466d2cdc000000000000000000000000000000000000000000000000000000000000000ac0808080");
124128

125129
tx.signature = vec![
126130
0x30, 0x45, 0x02, 0x21, 0x00, 0xd3, 0x8f, 0x71, 0x94, 0x7b, 0x2c, 0xf5, 0x43, 0x58,
@@ -132,7 +136,7 @@ mod test {
132136

133137
let signed_tx = encode_for_broadcast(tx.clone()).unwrap();
134138

135-
assert_eq!(hex::encode(signed_tx.raw_data), "b87602f8730182014f84147b7eeb85084ec9f83f8301450994dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000004cbeee256240c92a9ad920ea6f4d7df6466d2cdc000000000000000000000000000000000000000000000000000000000000000ac0808080");
139+
assert_eq!(hex::encode(signed_tx.raw_data), "02f8b30182014f84147b7eeb85084ec9f83f8301450994dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000004cbeee256240c92a9ad920ea6f4d7df6466d2cdc000000000000000000000000000000000000000000000000000000000000000ac054a054ad49a590596b77452a01141de380dd50945843f52c7b94718fd30021024530a0ad49a590596b77452a01141de380dd50945843f52c7b94718fd3002102453007");
136140
assert_eq!(
137141
hex::encode(signed_tx.signature),
138142
"3045022100d38f71947b2cf543589450dd80e31d14012a45776b5990a549ad54073045022100d38f71947b2cf543589450dd80e31d14012a45776b5990a549ad54"

packages/kos-codec/src/chains/eth/models.rs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl EthereumTransaction {
4040
self::EthereumTransaction::decode_eip155(rlp)
4141
}
4242

43-
pub fn encode_eip25519(&self) -> Result<RlpStream, DecoderError> {
43+
pub fn encode_eip1559(&self) -> Result<RlpStream, DecoderError> {
4444
let mut rlp = RlpStream::new();
4545
let list_size = if self.signature.is_some() { 12 } else { 9 };
4646
rlp.begin_list(list_size);
@@ -83,32 +83,59 @@ impl EthereumTransaction {
8383
pub fn encode_legacy(&self) -> Result<RlpStream, DecoderError> {
8484
let mut rlp = RlpStream::new();
8585
rlp.begin_list(9);
86+
8687
rlp.append(&self.nonce);
8788
rlp.append(&self.gas_price.clone().unwrap_or(U256([0; 32])));
8889
rlp.append(&self.gas);
89-
if self.to.is_some() {
90-
rlp.append(&self.to.clone().unwrap().as_slice());
90+
91+
if let Some(to_addr) = &self.to {
92+
rlp.append(&to_addr.as_slice());
9193
} else {
9294
rlp.append(&"");
9395
}
96+
9497
rlp.append(&self.value);
9598
rlp.append(&self.data);
96-
if self.chain_id.is_some() {
97-
let cid = self.chain_id.unwrap_or(0);
98-
if self.signature.is_some() {
99-
let sig = self.signature.unwrap_or([0; 65]);
100-
let mut r = U256([0; 32]);
101-
r.0.copy_from_slice(&sig[..32]);
102-
let mut s = U256([0; 32]);
103-
s.0.copy_from_slice(&sig[32..64]);
104-
let v = cid * 2 + 35 + (sig[64] as u64);
105-
rlp.append(&v);
106-
rlp.append(&r);
107-
rlp.append(&s);
99+
100+
// Handle signature fields (v, r, s) - always present in legacy transactions
101+
if let Some(sig) = &self.signature {
102+
if sig.len() != 65 {
103+
return Err(DecoderError::Custom("Invalid signature length"));
104+
}
105+
106+
// Parse r and s from signature (first 32 bytes = r, next 32 bytes = s)
107+
let mut r_bytes = [0u8; 32];
108+
let mut s_bytes = [0u8; 32];
109+
r_bytes.copy_from_slice(&sig[..32]);
110+
s_bytes.copy_from_slice(&sig[32..64]);
111+
112+
let r = U256(r_bytes);
113+
let s = U256(s_bytes);
114+
115+
// Calculate v based on chain_id (EIP-155) or legacy format
116+
let v = if let Some(chain_id) = self.chain_id {
117+
// EIP-155: v = chain_id * 2 + 35 + recovery_id
118+
chain_id * 2 + 35 + (sig[64] as u64)
119+
} else {
120+
// Pre-EIP-155: v = 27 + recovery_id
121+
27 + (sig[64] as u64)
122+
};
123+
124+
rlp.append(&v);
125+
rlp.append(&r);
126+
rlp.append(&s);
127+
} else {
128+
// Unsigned transaction - used for signing
129+
if let Some(chain_id) = self.chain_id {
130+
// EIP-155 unsigned transaction
131+
rlp.append(&chain_id);
132+
rlp.append(&U256([0; 32]));
133+
rlp.append(&U256([0; 32]));
108134
} else {
109-
rlp.append(&cid);
110-
rlp.append(&0u8);
111-
rlp.append(&0u8);
135+
// Pre-EIP-155 unsigned transaction
136+
rlp.append(&U256([0; 32]));
137+
rlp.append(&U256([0; 32]));
138+
rlp.append(&U256([0; 32]));
112139
}
113140
}
114141

@@ -123,7 +150,7 @@ impl EthereumTransaction {
123150
}
124151

125152
TransactionType::Eip155 => {
126-
let stream = self.encode_eip25519()?;
153+
let stream = self.encode_eip1559()?;
127154
Ok([&[2], stream.as_raw()].concat())
128155
}
129156
}

packages/kos-codec/src/chains/trx/mod.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,14 @@ pub fn encode_sign_message(message: Vec<u8>) -> Result<Vec<u8>, ChainError> {
5353

5454
pub fn decode_transaction(raw_tx: Vec<u8>) -> Result<protocol::Transaction, ChainError> {
5555
let tx = protocol::Transaction::decode(raw_tx.as_slice());
56+
// Try to decode the transaction
5657
if let Ok(t) = tx {
57-
return Ok(t);
58+
// Check if raw_data exists
59+
if let Some(ref raw_data) = t.raw_data {
60+
if !raw_data.contract.is_empty() {
61+
return Ok(t);
62+
}
63+
}
5864
}
5965

6066
let raw_tx = protocol::transaction::Raw::decode(raw_tx.as_slice())?;
@@ -74,7 +80,27 @@ mod test {
7480
#[test]
7581
fn test_encode_for_sign() {
7682
let raw_tx = hex::decode(
77-
"0a02487c22080608af18f6ec6c8340d8f8fae2e0315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541e825d52582eec346c839b4875376117904a76cbc12154120ab1300cf70c048e4cf5d5b1b33f59653ed6626180a708fb1f7e2e031"
83+
"0a0270592208dd5821dad87735a340f0e1b4b9f3325aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541da3a264b74539c2078206c60e025c673d35c04c0121541a614f803b6fd780986a42c78ec9c7f77e6ded13c2244a9059cbb00000000000000000000000079af4269d01fca9a32b476576ee384427a38b736000000000000000000000000000000000000000000000000000000000112a880709b90b1b9f332900180c2d72f"
84+
).unwrap();
85+
let tx = Transaction {
86+
raw_data: raw_tx.clone(),
87+
tx_hash: vec![],
88+
signature: vec![],
89+
options: None,
90+
};
91+
92+
let result = encode_for_sign(tx).unwrap();
93+
94+
assert_eq!(
95+
hex::encode(result.tx_hash),
96+
"bf9efe196a74dad03de5ebf46c07d17fe891549606c62f1a58edd3a58fc8712a"
97+
);
98+
}
99+
100+
#[test]
101+
fn test_encode_for_sign_transaction() {
102+
let raw_tx = hex::decode(
103+
"0ad3010a0270592208dd5821dad87735a340f0e1b4b9f3325aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541da3a264b74539c2078206c60e025c673d35c04c0121541a614f803b6fd780986a42c78ec9c7f77e6ded13c2244a9059cbb00000000000000000000000079af4269d01fca9a32b476576ee384427a38b736000000000000000000000000000000000000000000000000000000000112a880709b90b1b9f332900180c2d72f"
78104
).unwrap();
79105
let tx = Transaction {
80106
raw_data: raw_tx.clone(),
@@ -87,12 +113,13 @@ mod test {
87113

88114
assert_eq!(
89115
hex::encode(result.tx_hash),
90-
"96a09fd664f1a7abbbe8bca604ea40b80291119fed5283c71ba94882d5b3c8a5"
116+
"bf9efe196a74dad03de5ebf46c07d17fe891549606c62f1a58edd3a58fc8712a"
91117
);
92118
}
93119

94120
#[test]
95121
fn test_encode_for_broadcast() {
122+
// this tranasction will be decoded using protocol::Transaction::decode
96123
let raw_tx = hex::decode(
97124
"0a02487c22080608af18f6ec6c8340d8f8fae2e0315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a1541e825d52582eec346c839b4875376117904a76cbc12154120ab1300cf70c048e4cf5d5b1b33f59653ed6626180a708fb1f7e2e031"
98125
).unwrap();

0 commit comments

Comments
 (0)