Skip to content

Instantly share code, notes, and snippets.

@narodnik
Created June 8, 2018 17:16
Show Gist options
  • Save narodnik/3e86a2e71badfa8c333b0931b63c1459 to your computer and use it in GitHub Desktop.
Save narodnik/3e86a2e71badfa8c333b0931b63c1459 to your computer and use it in GitHub Desktop.
#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