/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. */ /** @file ICAP.cpp * @author Gav Wood <i@gavwood.com> * @date 2014 */ #include "ICAP.h" #include <boost/algorithm/string/case_conv.hpp> #include <libdevcore/Base64.h> #include <libdevcrypto/SHA3.h> #include "Exceptions.h" using namespace std; using namespace dev; using namespace dev::eth; namespace dev { namespace eth { string ICAP::iban(std::string _c, std::string _d) { boost::to_upper(_c); boost::to_upper(_d); auto totStr = _d + _c + "00"; bigint tot = 0; for (char x: totStr) if (x >= 'A') tot = tot * 100 + x - 'A' + 10; else tot = tot * 10 + x - '0'; unsigned check = (unsigned)(u256)(98 - tot % 97); ostringstream out; out << _c << setfill('0') << setw(2) << check << _d; return out.str(); } std::pair<string, string> ICAP::fromIBAN(std::string _iban) { if (_iban.size() < 4) return std::make_pair(string(), string()); boost::to_upper(_iban); std::string c = _iban.substr(0, 2); std::string d = _iban.substr(4); if (iban(c, d) != _iban) return std::make_pair(string(), string()); return make_pair(c, d); } ICAP ICAP::decoded(std::string const& _encoded) { ICAP ret; std::string country; std::string data; std::tie(country, data) = fromIBAN(_encoded); if (country != "XE") throw InvalidICAP(); if (data.size() == 30) { ret.m_type = Direct; // Direct ICAP ret.m_direct = fromBase36<Address::size>(data); } else if (data.size() == 16) { ret.m_type = Indirect; ret.m_asset = data.substr(0, 3); if (ret.m_asset == "XET") { ret.m_institution = data.substr(3, 4); ret.m_client = data.substr(7); } else if (ret.m_asset == "ETH") ret.m_client = data.substr(4); else throw InvalidICAP(); } else throw InvalidICAP(); return ret; } std::string ICAP::encoded() const { if (m_type == Direct) { if (!!m_direct[0]) return string(); std::string d = toBase36<Address::size>(m_direct); while (d.size() < 30) d = "0" + d; return iban("XE", d); } else if (m_type == Indirect) { if ( m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || m_asset.size() != 3 ) throw InvalidICAP(); if (boost::to_upper_copy(m_asset) == "XET") { if (m_institution.size() != 4 || m_client.size() != 9) throw InvalidICAP(); } else if (boost::to_upper_copy(m_asset) == "ETH") { if (m_client.size() != 13) throw InvalidICAP(); } else throw InvalidICAP(); return iban("XE", m_asset + m_institution + m_client); } else throw InvalidICAP(); } Address ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { (void)_call; (void)_reg; if (m_asset == "XET") { // TODO // _call(_reg, ); return Address(); } else if (m_asset == "ETH") { // TODO // return resolve(m_institution + "/" + m_client).primary(); return Address(); } else throw InterfaceNotSupported("ICAP::lookup(), non XET asset"); } } }