Created
June 8, 2018 17:16
-
-
Save narodnik/3e86a2e71badfa8c333b0931b63c1459 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bitcoin/bitcoin.hpp> | |
using namespace bc; | |
class ec_scalar | |
{ | |
public: | |
ec_scalar(); | |
ec_scalar(uint64_t value); | |
void reset(); | |
ec_scalar& operator=(uint64_t value); | |
bool is_zero() const; | |
bool is_valid() const; | |
operator bool() const; | |
ec_scalar operator-() const; | |
ec_scalar& operator+=(const ec_scalar& rhs); | |
ec_scalar& operator-=(const ec_scalar& rhs); | |
friend ec_scalar operator+(ec_scalar lhs, const ec_scalar& rhs); | |
friend ec_scalar operator-(ec_scalar lhs, const ec_scalar& rhs); | |
const ec_secret& secret() const; | |
operator ec_secret() const; | |
private: | |
void invalidate(); | |
bool valid_ = true; | |
ec_secret scalar_; | |
}; | |
ec_scalar::ec_scalar() | |
{ | |
} | |
ec_scalar::ec_scalar(uint64_t value) | |
{ | |
*this = value; | |
} | |
void ec_scalar::reset() | |
{ | |
std::fill(scalar_.begin(), scalar_.end(), 0); | |
} | |
void ec_scalar::invalidate() | |
{ | |
valid_ = false; | |
} | |
ec_scalar& ec_scalar::operator=(uint64_t value) | |
{ | |
reset(); | |
auto serial = bc::make_unsafe_serializer(scalar_.end() - 8); | |
serial.write_8_bytes_big_endian(static_cast<uint64_t>(value)); | |
return *this; | |
} | |
bool ec_scalar::is_zero() const | |
{ | |
return std::all_of(scalar_.begin(), scalar_.end(), | |
[](ec_secret::value_type value) | |
{ | |
return value == 0; | |
}); | |
} | |
bool ec_scalar::is_valid() const | |
{ | |
return valid_; | |
} | |
ec_scalar::operator bool() const | |
{ | |
return is_valid() && !is_zero(); | |
} | |
ec_scalar ec_scalar::operator-() const | |
{ | |
if (!valid_) | |
return *this; | |
auto result = *this; | |
bool rc = ec_negate(result.scalar_); | |
if (!rc) | |
result.invalidate(); | |
return result; | |
} | |
ec_scalar& ec_scalar::operator+=(const ec_scalar& rhs) | |
{ | |
if (!valid_) | |
return *this; | |
*this = *this + rhs; | |
return *this; | |
} | |
ec_scalar& ec_scalar::operator-=(const ec_scalar& rhs) | |
{ | |
if (!valid_) | |
return *this; | |
*this = *this - rhs; | |
return *this; | |
} | |
ec_scalar operator+(ec_scalar lhs, const ec_scalar& rhs) | |
{ | |
if (!lhs.valid_ || !rhs.valid_) | |
{ | |
lhs.invalidate(); | |
return lhs; | |
} | |
bool rc = ec_add(lhs.scalar_, rhs.scalar_); | |
if (!rc) | |
lhs.invalidate(); | |
return lhs; | |
} | |
ec_scalar operator-(ec_scalar lhs, const ec_scalar& rhs) | |
{ | |
if (!lhs.valid_ || !rhs.valid_) | |
{ | |
lhs.invalidate(); | |
return lhs; | |
} | |
const auto negative_rhs = -rhs; | |
if (!negative_rhs.valid_) | |
{ | |
lhs.invalidate(); | |
return lhs; | |
} | |
return lhs + negative_rhs; | |
} | |
const ec_secret& ec_scalar::secret() const | |
{ | |
return scalar_; | |
} | |
ec_scalar::operator ec_secret() const | |
{ | |
return secret(); | |
} | |
class ec_point | |
{ | |
public: | |
ec_point(); | |
ec_point(const std::string& hex); | |
void reset(); | |
bool is_valid() const; | |
operator bool() const; | |
friend ec_point operator*(ec_point lhs, const ec_scalar& rhs); | |
const ec_compressed& point() const; | |
operator ec_compressed() const; | |
private: | |
void invalidate(); | |
ec_compressed point_; | |
}; | |
ec_point::ec_point() | |
{ | |
} | |
ec_point::ec_point(const std::string& hex) | |
{ | |
} | |
void ec_point::invalidate() | |
{ | |
point_[0] = 0; | |
} | |
bool ec_point::is_valid() const | |
{ | |
return point_[0] == 2 || point_[0] == 3; | |
} | |
ec_point::operator bool() const | |
{ | |
return is_valid(); | |
} | |
ec_point operator*(ec_point lhs, const ec_scalar& rhs) | |
{ | |
bool rc = ec_multiply(lhs.point_, rhs.secret()); | |
if (rc) | |
{ | |
lhs.invalidate(); | |
return lhs; | |
} | |
return lhs; | |
} | |
const ec_compressed& ec_point::point() const | |
{ | |
return point_; | |
} | |
ec_point::operator ec_compressed() const | |
{ | |
return point(); | |
} | |
int main() | |
{ | |
ec_scalar s = 10; | |
if (!s) | |
return 1; | |
ec_scalar x = 10; | |
if (!x) | |
return 1; | |
std::cout << encode_base16(s.secret()) << std::endl; | |
std::cout << encode_base16(x.secret()) << std::endl; | |
const auto test = s + x; | |
std::cout << "test: " << encode_base16(test.secret()) << std::endl; | |
s += x; | |
std::cout << encode_base16(s.secret()) << std::endl; | |
s = s - x; | |
std::cout << encode_base16(s.secret()) << std::endl; | |
s -= x; | |
s = s - x; | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment