Skip to content

Commit daeccae

Browse files
committed
Merge branch 'yuji/ibc-ics20-transfer' (#625)
* yuji/ibc-ics20-transfer: [ci] wasm checksums update remove clone fix VP reads add denom.rs fix relay transfer
2 parents 780e8a6 + c4b369e commit daeccae

File tree

13 files changed

+696
-286
lines changed

13 files changed

+696
-286
lines changed

apps/src/lib/node/ledger/protocol/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,8 @@ where
336336
gas_meter = slash_fund.ctx.gas_meter.into_inner();
337337
result
338338
}
339-
InternalAddress::IbcEscrow(_)
339+
InternalAddress::IbcToken(_)
340+
| InternalAddress::IbcEscrow
340341
| InternalAddress::IbcBurn
341342
| InternalAddress::IbcMint => {
342343
// validate the transfer

shared/src/ledger/ibc/handler.rs

Lines changed: 181 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ pub enum Error {
115115
SendingToken(String),
116116
#[error("Receiving a token error: {0}")]
117117
ReceivingToken(String),
118+
#[error("IBC storage error: {0}")]
119+
IbcStorage(storage::Error),
118120
}
119121

120122
// This is needed to use `ibc::Handler::Error` with `IbcActions` in
@@ -161,9 +163,8 @@ pub trait IbcActions {
161163
/// Transfer token
162164
fn transfer_token(
163165
&mut self,
164-
src: &Address,
165-
dest: &Address,
166-
token: &Address,
166+
src: &Key,
167+
dest: &Key,
167168
amount: Amount,
168169
) -> std::result::Result<(), Self::Error>;
169170

@@ -934,51 +935,87 @@ pub trait IbcActions {
934935
&mut self,
935936
msg: &MsgTransfer,
936937
) -> std::result::Result<(), Self::Error> {
937-
let data = FungibleTokenPacketData::from(msg.clone());
938-
let source = Address::decode(data.sender.clone()).map_err(|e| {
939-
Error::SendingToken(format!(
940-
"Invalid sender address: sender {}, error {}",
941-
data.sender, e
942-
))
943-
})?;
944-
let token_str = data.denom.split('/').last().ok_or_else(|| {
945-
Error::SendingToken(format!(
946-
"No token was specified: {}",
947-
data.denom
948-
))
949-
})?;
950-
let token = Address::decode(token_str).map_err(|e| {
951-
Error::SendingToken(format!(
952-
"Invalid token address: token {}, error {}",
953-
token_str, e
954-
))
955-
})?;
938+
let mut data = FungibleTokenPacketData::from(msg.clone());
939+
if let Some(hash) = storage::token_hash_from_denom(&data.denom)
940+
.map_err(Error::IbcStorage)?
941+
{
942+
let denom_key = storage::ibc_denom_key(&hash);
943+
let denom_bytes =
944+
self.read_ibc_data(&denom_key)?.ok_or_else(|| {
945+
Error::SendingToken(format!(
946+
"No original denom: denom_key {}",
947+
denom_key
948+
))
949+
})?;
950+
let denom = std::str::from_utf8(&denom_bytes).map_err(|e| {
951+
Error::SendingToken(format!(
952+
"Decoding the denom failed: denom_key {}, error {}",
953+
denom_key, e
954+
))
955+
})?;
956+
data.denom = denom.to_string();
957+
}
958+
let token = storage::token(&data.denom).map_err(Error::IbcStorage)?;
956959
let amount = Amount::from_str(&data.amount).map_err(|e| {
957960
Error::SendingToken(format!(
958961
"Invalid amount: amount {}, error {}",
959962
data.amount, e
960963
))
961964
})?;
962965

963-
// check the denom field
966+
let source_addr = Address::decode(&data.sender).map_err(|e| {
967+
Error::SendingToken(format!(
968+
"Invalid sender address: sender {}, error {}",
969+
data.sender, e
970+
))
971+
})?;
972+
973+
// check the denomination field
964974
let prefix = format!(
965975
"{}/{}/",
966976
msg.source_port.clone(),
967977
msg.source_channel.clone()
968978
);
969-
if data.denom.starts_with(&prefix) {
970-
// sink zone
971-
let burn = Address::Internal(InternalAddress::IbcBurn);
972-
self.transfer_token(&source, &burn, &token, amount)?;
979+
let (source, target) = if data.denom.starts_with(&prefix) {
980+
// the receiver's chain was the source
981+
// transfer from the origin-specific account of the token
982+
let key_prefix = storage::ibc_token_prefix(&data.denom)
983+
.map_err(Error::IbcStorage)?;
984+
let src = token::multitoken_balance_key(&key_prefix, &source_addr);
985+
986+
let key_prefix = storage::ibc_account_prefix(
987+
&msg.source_port,
988+
&msg.source_channel,
989+
&token,
990+
);
991+
let burn = token::multitoken_balance_key(
992+
&key_prefix,
993+
&Address::Internal(InternalAddress::IbcBurn),
994+
);
995+
(src, burn)
973996
} else {
974-
// source zone
975-
let escrow =
976-
Address::Internal(InternalAddress::ibc_escrow_address(
977-
msg.source_port.to_string(),
978-
msg.source_channel.to_string(),
979-
));
980-
self.transfer_token(&source, &escrow, &token, amount)?;
981-
}
997+
// this chain is the source
998+
// escrow the amount of the token
999+
let src = if data.denom == token.to_string() {
1000+
token::balance_key(&token, &source_addr)
1001+
} else {
1002+
let key_prefix = storage::ibc_token_prefix(&data.denom)
1003+
.map_err(Error::IbcStorage)?;
1004+
token::multitoken_balance_key(&key_prefix, &source_addr)
1005+
};
1006+
1007+
let key_prefix = storage::ibc_account_prefix(
1008+
&msg.source_port,
1009+
&msg.source_channel,
1010+
&token,
1011+
);
1012+
let escrow = token::multitoken_balance_key(
1013+
&key_prefix,
1014+
&Address::Internal(InternalAddress::IbcEscrow),
1015+
);
1016+
(src, escrow)
1017+
};
1018+
self.transfer_token(&source, &target, amount)?;
9821019

9831020
// send a packet
9841021
let port_channel_id =
@@ -999,49 +1036,82 @@ pub trait IbcActions {
9991036
packet: &Packet,
10001037
data: &FungibleTokenPacketData,
10011038
) -> std::result::Result<(), Self::Error> {
1002-
let dest = Address::decode(data.receiver.clone()).map_err(|e| {
1003-
Error::ReceivingToken(format!(
1004-
"Invalid receiver address: receiver {}, error {}",
1005-
data.receiver, e
1006-
))
1007-
})?;
1008-
let token_str = data.denom.split('/').last().ok_or_else(|| {
1009-
Error::ReceivingToken(format!(
1010-
"No token was specified: {}",
1011-
data.denom
1012-
))
1013-
})?;
1014-
let token = Address::decode(token_str).map_err(|e| {
1015-
Error::ReceivingToken(format!(
1016-
"Invalid token address: token {}, error {}",
1017-
token_str, e
1018-
))
1019-
})?;
1039+
let token = storage::token(&data.denom).map_err(Error::IbcStorage)?;
10201040
let amount = Amount::from_str(&data.amount).map_err(|e| {
10211041
Error::ReceivingToken(format!(
10221042
"Invalid amount: amount {}, error {}",
10231043
data.amount, e
10241044
))
10251045
})?;
1046+
// The receiver should be an address because the origin-specific account
1047+
// key should be assigned internally
1048+
let dest_addr = Address::decode(&data.receiver).map_err(|e| {
1049+
Error::ReceivingToken(format!(
1050+
"Invalid receiver address: receiver {}, error {}",
1051+
data.receiver, e
1052+
))
1053+
})?;
10261054

10271055
let prefix = format!(
10281056
"{}/{}/",
10291057
packet.source_port.clone(),
10301058
packet.source_channel.clone()
10311059
);
1032-
if data.denom.starts_with(&prefix) {
1033-
// unescrow the token because this chain is the source
1034-
let escrow =
1035-
Address::Internal(InternalAddress::ibc_escrow_address(
1036-
packet.destination_port.to_string(),
1037-
packet.destination_channel.to_string(),
1038-
));
1039-
self.transfer_token(&escrow, &dest, &token, amount)?;
1040-
} else {
1041-
// mint the token because the sender chain is the source
1042-
let mint = Address::Internal(InternalAddress::IbcMint);
1043-
self.transfer_token(&mint, &dest, &token, amount)?;
1044-
}
1060+
let (source, target) = match data.denom.strip_prefix(&prefix) {
1061+
Some(denom) => {
1062+
// unescrow the token because this chain was the source
1063+
let escrow_prefix = storage::ibc_account_prefix(
1064+
&packet.destination_port,
1065+
&packet.destination_channel,
1066+
&token,
1067+
);
1068+
let escrow = token::multitoken_balance_key(
1069+
&escrow_prefix,
1070+
&Address::Internal(InternalAddress::IbcEscrow),
1071+
);
1072+
let dest = if denom == token.to_string() {
1073+
token::balance_key(&token, &dest_addr)
1074+
} else {
1075+
let key_prefix = storage::ibc_token_prefix(denom)
1076+
.map_err(Error::IbcStorage)?;
1077+
token::multitoken_balance_key(&key_prefix, &dest_addr)
1078+
};
1079+
(escrow, dest)
1080+
}
1081+
None => {
1082+
// mint the token because the sender chain is the source
1083+
let key_prefix = storage::ibc_account_prefix(
1084+
&packet.destination_port,
1085+
&packet.destination_channel,
1086+
&token,
1087+
);
1088+
let mint = token::multitoken_balance_key(
1089+
&key_prefix,
1090+
&Address::Internal(InternalAddress::IbcMint),
1091+
);
1092+
1093+
// prefix the denom with the this chain port and channel
1094+
let denom = format!(
1095+
"{}/{}/{}",
1096+
&packet.destination_port,
1097+
&packet.destination_channel,
1098+
&data.denom
1099+
);
1100+
let key_prefix = storage::ibc_token_prefix(&denom)
1101+
.map_err(Error::IbcStorage)?;
1102+
let dest =
1103+
token::multitoken_balance_key(&key_prefix, &dest_addr);
1104+
1105+
// store the prefixed denom
1106+
let token_hash = storage::calc_hash(&denom);
1107+
let denom_key = storage::ibc_denom_key(token_hash);
1108+
self.write_ibc_data(&denom_key, denom.as_bytes())?;
1109+
1110+
(mint, dest)
1111+
}
1112+
};
1113+
self.transfer_token(&source, &target, amount)?;
1114+
10451115
Ok(())
10461116
}
10471117

@@ -1051,49 +1121,64 @@ pub trait IbcActions {
10511121
packet: &Packet,
10521122
data: &FungibleTokenPacketData,
10531123
) -> std::result::Result<(), Self::Error> {
1054-
let dest = Address::decode(data.sender.clone()).map_err(|e| {
1055-
Error::ReceivingToken(format!(
1056-
"Invalid sender address: sender {}, error {}",
1057-
data.sender, e
1058-
))
1059-
})?;
1060-
let token_str = data.denom.split('/').last().ok_or_else(|| {
1061-
Error::ReceivingToken(format!(
1062-
"No token was specified: {}",
1063-
data.denom
1064-
))
1065-
})?;
1066-
let token = Address::decode(token_str).map_err(|e| {
1067-
Error::ReceivingToken(format!(
1068-
"Invalid token address: token {}, error {}",
1069-
token_str, e
1070-
))
1071-
})?;
1124+
let token = storage::token(&data.denom).map_err(Error::IbcStorage)?;
10721125
let amount = Amount::from_str(&data.amount).map_err(|e| {
10731126
Error::ReceivingToken(format!(
10741127
"Invalid amount: amount {}, error {}",
10751128
data.amount, e
10761129
))
10771130
})?;
10781131

1132+
let dest_addr = Address::decode(&data.sender).map_err(|e| {
1133+
Error::SendingToken(format!(
1134+
"Invalid sender address: sender {}, error {}",
1135+
data.sender, e
1136+
))
1137+
})?;
1138+
10791139
let prefix = format!(
10801140
"{}/{}/",
10811141
packet.source_port.clone(),
10821142
packet.source_channel.clone()
10831143
);
1084-
if data.denom.starts_with(&prefix) {
1085-
// mint the token because the sender chain is the sink zone
1086-
let mint = Address::Internal(InternalAddress::IbcMint);
1087-
self.transfer_token(&mint, &dest, &token, amount)?;
1144+
let (source, target) = if data.denom.starts_with(&prefix) {
1145+
// mint the token because the amount was burned
1146+
let key_prefix = storage::ibc_account_prefix(
1147+
&packet.source_port,
1148+
&packet.source_channel,
1149+
&token,
1150+
);
1151+
let mint = token::multitoken_balance_key(
1152+
&key_prefix,
1153+
&Address::Internal(InternalAddress::IbcMint),
1154+
);
1155+
let key_prefix = storage::ibc_token_prefix(&data.denom)
1156+
.map_err(Error::IbcStorage)?;
1157+
let dest = token::multitoken_balance_key(&key_prefix, &dest_addr);
1158+
(mint, dest)
10881159
} else {
1089-
// unescrow the token because the sender chain is the source zone
1090-
let escrow =
1091-
Address::Internal(InternalAddress::ibc_escrow_address(
1092-
packet.source_port.to_string(),
1093-
packet.source_channel.to_string(),
1094-
));
1095-
self.transfer_token(&escrow, &dest, &token, amount)?;
1096-
}
1160+
// unescrow the token because the acount was escrowed
1161+
let dest = if data.denom == token.to_string() {
1162+
token::balance_key(&token, &dest_addr)
1163+
} else {
1164+
let key_prefix = storage::ibc_token_prefix(&data.denom)
1165+
.map_err(Error::IbcStorage)?;
1166+
token::multitoken_balance_key(&key_prefix, &dest_addr)
1167+
};
1168+
1169+
let key_prefix = storage::ibc_account_prefix(
1170+
&packet.source_port,
1171+
&packet.source_channel,
1172+
&token,
1173+
);
1174+
let escrow = token::multitoken_balance_key(
1175+
&key_prefix,
1176+
&Address::Internal(InternalAddress::IbcEscrow),
1177+
);
1178+
(escrow, dest)
1179+
};
1180+
self.transfer_token(&source, &target, amount)?;
1181+
10971182
Ok(())
10981183
}
10991184
}

0 commit comments

Comments
 (0)