trustedpeer/CanonicalTrustCodec.cpp¶
Namespaces¶
| Name |
|---|
| sgns |
| sgns::trustedpeer |
Source code¶
#include "trustedpeer/CanonicalTrustCodec.hpp"
#include <algorithm>
#include <limits>
#include <unordered_set>
#include <utility>
#include "base/hexutil.hpp"
#include "crypto/sha/sha256.hpp"
namespace sgns::trustedpeer
{
void CanonicalTrustCodec::Writer::WriteU8( uint8_t value )
{
bytes_.push_back( value );
}
void CanonicalTrustCodec::Writer::WriteU16( uint16_t value )
{
bytes_.push_back( static_cast<uint8_t>( value >> 8U ) );
bytes_.push_back( static_cast<uint8_t>( value ) );
}
void CanonicalTrustCodec::Writer::WriteU32( uint32_t value )
{
bytes_.push_back( static_cast<uint8_t>( value >> 24U ) );
bytes_.push_back( static_cast<uint8_t>( value >> 16U ) );
bytes_.push_back( static_cast<uint8_t>( value >> 8U ) );
bytes_.push_back( static_cast<uint8_t>( value ) );
}
void CanonicalTrustCodec::Writer::WriteU64( uint64_t value )
{
for ( int shift = 56; shift >= 0; shift -= 8 )
{
bytes_.push_back( static_cast<uint8_t>( value >> static_cast<unsigned>( shift ) ) );
}
}
void CanonicalTrustCodec::Writer::WriteBytes( gsl::span<const uint8_t> bytes )
{
bytes_.insert( bytes_.end(), bytes.begin(), bytes.end() );
}
void CanonicalTrustCodec::Writer::WriteBytes( std::string_view bytes )
{
const auto *begin = reinterpret_cast<const uint8_t *>( bytes.data() ); // NOLINT
WriteBytes( gsl::span<const uint8_t>( begin, bytes.size() ) );
}
bool CanonicalTrustCodec::Writer::WriteLengthPrefixedBytes( gsl::span<const uint8_t> bytes )
{
if ( bytes.size() > std::numeric_limits<uint32_t>::max() )
{
return false;
}
WriteU32( static_cast<uint32_t>( bytes.size() ) );
WriteBytes( bytes );
return true;
}
std::vector<uint8_t> CanonicalTrustCodec::Writer::Take()
{
return std::move( bytes_ );
}
CanonicalTrustCodec::Reader::Reader( gsl::span<const uint8_t> bytes ) : bytes_( bytes )
{
}
std::optional<uint8_t> CanonicalTrustCodec::Reader::ReadU8()
{
const auto bytes = ReadBytes( 1 );
return bytes ? std::optional<uint8_t>( bytes->front() ) : std::nullopt;
}
std::optional<uint16_t> CanonicalTrustCodec::Reader::ReadU16()
{
const auto bytes = ReadBytes( 2 );
if ( !bytes )
{
return std::nullopt;
}
return static_cast<uint16_t>( static_cast<uint16_t>( ( *bytes )[0] ) << 8U |
static_cast<uint16_t>( ( *bytes )[1] ) );
}
std::optional<uint32_t> CanonicalTrustCodec::Reader::ReadU32()
{
const auto bytes = ReadBytes( 4 );
if ( !bytes )
{
return std::nullopt;
}
uint32_t value = 0;
for ( const auto byte : *bytes )
{
value = ( value << 8U ) | byte;
}
return value;
}
std::optional<uint64_t> CanonicalTrustCodec::Reader::ReadU64()
{
const auto bytes = ReadBytes( 8 );
if ( !bytes )
{
return std::nullopt;
}
uint64_t value = 0;
for ( const auto byte : *bytes )
{
value = ( value << 8U ) | byte;
}
return value;
}
std::optional<std::vector<uint8_t>> CanonicalTrustCodec::Reader::ReadBytes( size_t length )
{
const auto total_size = static_cast<size_t>( bytes_.size() );
if ( offset_ > total_size || length > total_size - offset_ )
{
return std::nullopt;
}
std::vector<uint8_t> result( bytes_.begin() + static_cast<ptrdiff_t>( offset_ ),
bytes_.begin() + static_cast<ptrdiff_t>( offset_ + length ) );
offset_ += length;
return result;
}
std::optional<std::vector<uint8_t>> CanonicalTrustCodec::Reader::ReadLengthPrefixedBytes( size_t maximum_length )
{
const auto length = ReadU32();
if ( !length || *length > maximum_length )
{
return std::nullopt;
}
return ReadBytes( *length );
}
bool CanonicalTrustCodec::Reader::Exhausted() const
{
return offset_ == static_cast<size_t>( bytes_.size() );
}
std::optional<std::vector<uint8_t>> CanonicalTrustCodec::DecodePublicKey( std::string_view public_key )
{
if ( public_key.size() != PUBLIC_KEY_BYTES * 2 )
{
return std::nullopt;
}
// unhex also strips a leading 0x, so re-check the decoded length.
const auto decoded = sgns::base::unhex( public_key );
if ( decoded.has_error() || decoded.value().size() != PUBLIC_KEY_BYTES )
{
return std::nullopt;
}
return std::move( decoded.value() );
}
std::string CanonicalTrustCodec::EncodePublicKey( gsl::span<const uint8_t> public_key )
{
if ( public_key.size() != PUBLIC_KEY_BYTES )
{
return {};
}
return sgns::base::hex_lower( public_key );
}
std::optional<std::vector<std::string>> CanonicalTrustCodec::NormalizePublicKeys(
const std::vector<std::string> &public_keys )
{
if ( public_keys.empty() || public_keys.size() > MAX_TRUSTED_PEERS )
{
return std::nullopt;
}
std::vector<std::string> normalized;
normalized.reserve( public_keys.size() );
std::unordered_set<std::string> unique;
for ( const auto &public_key : public_keys )
{
const auto decoded = DecodePublicKey( public_key );
if ( !decoded )
{
return std::nullopt;
}
const auto encoded = EncodePublicKey( gsl::span<const uint8_t>( decoded->data(), decoded->size() ) );
if ( encoded.empty() || !unique.insert( encoded ).second )
{
return std::nullopt;
}
normalized.push_back( encoded );
}
std::sort( normalized.begin(), normalized.end() );
return normalized;
}
std::string CanonicalTrustCodec::Sha256Hex( gsl::span<const uint8_t> canonical_bytes )
{
return sgns::crypto::sha256( canonical_bytes ).toHex();
}
} // namespace sgns::trustedpeer
Updated on 2026-09-25 at 15:46:12 +0000