From 879775a52d26ed6cae574cf458b33a747d674cf6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 13 Mar 2015 01:45:04 +0100 Subject: [PATCH] IBAN/Direct-ICAP integration. --- alethzero/MainWin.cpp | 85 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 3134f5534..6055ed8e5 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -478,10 +478,84 @@ QString Main::pretty(dev::Address _a) const return fromRaw(n); } + +template inline string toBase36(FixedHash const& _h) +{ + static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + typename FixedHash::Arith a = _h; + std::string ret; + for (; a > 0; a /= 36) + ret = c_alphabet[(unsigned)a % 36] + ret; + return ret; +} + +template inline FixedHash fromBase36(string const& _h) +{ + typename FixedHash::Arith ret = 0; + for (char c: _h) + ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10)); + return ret; +} + +static string 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(); +} + +static std::pair 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); +} + +static string directICAP(dev::Address _a) +{ + if (!!_a[0]) + return string(); + std::string d = toBase36(_a); + while (d.size() < 30) + d = "0" + d; + return iban("XT", d); +} + +static Address fromICAP(std::string const& _s) +{ + std::string country; + std::string data; + std::tie(country, data) = fromIban(_s); + if (country.empty()) + return Address(); + if (country == "XT" && data.size() == 30) + // Direct ICAP + return fromBase36(data); + // TODO: Indirect ICAP + return Address(); +} + QString Main::render(dev::Address _a) const { QString p = pretty(_a); - if (!p.isNull()) + if (!_a[0]) + p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(directICAP(_a)); + if (!p.isEmpty()) return p + " (" + QString::fromStdString(_a.abridged()) + ")"; return QString::fromStdString(_a.abridged()); } @@ -524,6 +598,8 @@ Address Main::fromString(QString const& _n) const return Address(); } } + else if (Address a = fromICAP(_n.toStdString())) + return a; else return Address(); } @@ -1719,9 +1795,9 @@ bool beginsWith(Address _a, bytes const& _b) void Main::on_newAccount_triggered() { bool ok = true; - enum { NoVanity = 0, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; - QStringList items = {"No vanity (instant)", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"}; - unsigned v = items.QList::indexOf(QInputDialog::getItem(this, "Vanity Key?", "Would you a vanity key? This could take several hours.", items, 0, false, &ok)); + enum { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; + QStringList items = {"No vanity (instant)", "Direct ICAP address", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"}; + unsigned v = items.QList::indexOf(QInputDialog::getItem(this, "Vanity Key?", "Would you a vanity key? This could take several hours.", items, 1, false, &ok)); if (!ok) return; @@ -1747,6 +1823,7 @@ void Main::on_newAccount_triggered() lp = KeyPair::create(); auto a = lp.address(); if (v == NoVanity || + (v == DirectICAP && !a[0]) || (v == FirstTwo && a[0] == a[1]) || (v == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) || (v == FirstThree && a[0] == a[1] && a[1] == a[2]) ||