Compare commits

...

21 Commits

Author SHA1 Message Date
MoneroOcean fb0443bb96 Fixed extranonce location 2020-11-27 21:45:46 +00:00
MoneroOcean 12829ba280 Fixed DERO function name 2020-11-04 04:55:17 +00:00
MoneroOcean 24da9926bb Draft implementation of Ravencoin utils 2020-11-01 22:22:07 +00:00
MoneroOcean 444a39c27e Draft implementation of Ravencoin utils 2020-11-01 22:17:48 +00:00
MoneroOcean 6abe65f623 Draft implementation of Ravencoin utils 2020-11-01 21:48:05 +00:00
MoneroOcean 28e4c7a24a Draft implementation of Ravencoin utils 2020-10-31 05:52:24 +00:00
MoneroOcean 9e7b4fdd70 Draft implementation of Ravencoin utils 2020-10-31 05:43:33 +00:00
MoneroOcean b0acdf6a9d Draft implementation of Ravencoin utils 2020-10-31 05:41:52 +00:00
MoneroOcean dc04c5a0dd Draft implementation of Ravencoin utils 2020-10-31 01:53:33 +00:00
MoneroOcean f9c6b2c328 Draft implementation of Ravencoin utils 2020-10-31 00:36:22 +00:00
MoneroOcean d12493f9a9 Draft implementation of Ravencoin utils 2020-10-30 23:12:01 +00:00
MoneroOcean 310fcd9d4a Draft implementation of Ravencoin utils 2020-10-30 22:42:24 +00:00
MoneroOcean e8b9ff4a9f Draft implementation of Ravencoin utils 2020-10-30 22:42:21 +00:00
MoneroOcean 7ed6c83421 Bitcoin based utils 2020-10-30 20:14:17 +00:00
MoneroOcean b0b5d48233 Bitcoin based utils 2020-10-30 20:05:09 +00:00
MoneroOcean a47a2b28cb Added new c29i algo 2020-09-04 03:12:05 +00:00
MoneroOcean e0ca290f87 Merge pull request #15 from italocoin-project/master
add ITALO cycle48
2020-08-14 09:37:13 -07:00
italo 9ca10b3cde add ITALO cycle48 2020-08-14 05:40:29 -04:00
MoneroOcean 730f7d4a40 Fixed Haven ringct 2020-07-16 10:57:59 -07:00
MoneroOcean 067bf14985 Bug fix 2020-07-16 10:57:29 -07:00
MoneroOcean 1da9c8ea69 Haven patch 2020-07-16 10:02:26 -07:00
9 changed files with 602 additions and 162 deletions
+171 -1
View File
@@ -1 +1,171 @@
module.exports = require('bindings')('cryptoforknote.node')
module.exports = require('bindings')('cryptoforknote.node');
const SHA3 = require('sha3');
const bignum = require('bignum');
const bitcoin = require('bitcoinjs-lib');
const varuint = require('varuint-bitcoin');
const crypto = require('crypto');
const fastMerkleRoot = require('merkle-lib/fastRoot');
const promise = require('promise');
const merklebitcoin = promise.denodeify(require('merkle-bitcoin'));
function scriptCompile(addrHash) {
return bitcoin.script.compile([
bitcoin.opcodes.OP_DUP,
bitcoin.opcodes.OP_HASH160,
addrHash,
bitcoin.opcodes.OP_EQUALVERIFY,
bitcoin.opcodes.OP_CHECKSIG
]);
}
function reverseBuffer(buff) {
let reversed = new Buffer(buff.length);
for (var i = buff.length - 1; i >= 0; i--) reversed[buff.length - i - 1] = buff[i];
return reversed;
}
function getMerkleRoot(rpcData, generateTxRaw) {
hashes = [ reverseBuffer(new Buffer(generateTxRaw, 'hex')).toString('hex') ];
rpcData.transactions.forEach(function (value) {
hashes.push(value.txid ? value.txid : value.hash);
});
if (hashes.length === 1) return hashes[0];
return Object.values(merklebitcoin(hashes))[2].root;
}
function txesHaveWitnessCommit(transactions) {
return (
transactions instanceof Array &&
transactions[0] &&
transactions[0].ins &&
transactions[0].ins instanceof Array &&
transactions[0].ins[0] &&
transactions[0].ins[0].witness &&
transactions[0].ins[0].witness instanceof Array &&
transactions[0].ins[0].witness.length > 0
);
}
function getMerkleRoot2(transactions) {
if (transactions.length === 0) return null;
const forWitness = txesHaveWitnessCommit(transactions);
const hashes = transactions.map(transaction => transaction.getHash(forWitness));
const hash256 = function (buffer) { return crypto.createHash('sha256').update(buffer).digest(); };
const rootHash = fastMerkleRoot(hashes, hash256);
return forWitness ? hash256(Buffer.concat([rootHash, transactions[0].ins[0].witness[0]])) : rootHash;
}
let last_epoch_number;
let last_seed_hash;
const diff1 = 0x00000000ff000000000000000000000000000000000000000000000000000000;
module.exports.RavenBlockTemplate = function(rpcData, poolAddress) {
const poolAddrHash = bitcoin.address.fromBase58Check(poolAddress).hash;
let txCoinbase = new bitcoin.Transaction();
{ // input for coinbase tx
let blockHeightSerial = rpcData.height.toString(16).length % 2 === 0 ?
rpcData.height.toString(16) :
'0' + rpcData.height.toString(16);
const bytesHeight = Math.ceil((rpcData.height << 1).toString(2).length / 8);
const lengthDiff = blockHeightSerial.length/2 - bytesHeight;
for (let i = 0; i < lengthDiff; i++) blockHeightSerial = blockHeightSerial + '00';
const serializedBlockHeight = new Buffer.concat([
new Buffer('0' + bytesHeight, 'hex'),
reverseBuffer(new Buffer(blockHeightSerial, 'hex')),
new Buffer('00', 'hex') // OP_0
]);
txCoinbase.addInput(
// will be used for our reserved_offset extra_nonce
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
0xFFFFFFFF, 0xFFFFFFFF,
new Buffer.concat([serializedBlockHeight, Buffer('CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC', 'hex')]) // 17 bytes
);
txCoinbase.addOutput(scriptCompile(poolAddrHash), Math.floor(rpcData.coinbasevalue));
if (rpcData.default_witness_commitment) {
txCoinbase.addOutput(new Buffer(rpcData.default_witness_commitment, 'hex'), 0);
}
}
const merkleRoot = getMerkleRoot(rpcData, txCoinbase.getHash().toString('hex'));
let header = new Buffer(80);
{ let position = 0;
header.writeUInt32BE(rpcData.height, position, 4); // height 42-46
header.write(rpcData.bits, position += 4, 4, 'hex'); // bits 47-50
header.writeUInt32BE(rpcData.curtime, position += 4, 4, 'hex'); // nTime 51-54
header.write(merkleRoot, position += 4, 32, 'hex'); // merkelRoot 55-87
header.write(rpcData.previousblockhash, position += 32, 32, 'hex'); // prevblockhash 88-120
header.writeUInt32BE(rpcData.version, position += 32, 4); // version 121-153
header = reverseBuffer(header);
}
let blob = new Buffer.concat([
header, // 80 bytes
new Buffer('AAAAAAAAAAAAAAAA', 'hex'), // 8 bytes
new Buffer('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB', 'hex'), // 32 bytes
varuint.encode(rpcData.transactions.length + 1, new Buffer(varuint.encodingLength(rpcData.transactions.length + 1)), 0)
]);
const offset1 = blob.length;
blob = new Buffer.concat([ blob, new Buffer(txCoinbase.toHex(), 'hex') ]);
rpcData.transactions.forEach(function (value) {
blob = new Buffer.concat([ blob, new Buffer(value.data, 'hex') ]);
});
const EPOCH_LENGTH = 7500;
const epoch_number = Math.floor(rpcData.height / EPOCH_LENGTH);
if (last_epoch_number !== epoch_number) {
let sha3 = new SHA3.SHA3Hash(256);
if (last_epoch_number && last_epoch_number + 1 === epoch_number) {
last_seed_hash = sha3.update(last_seed_hash).digest();
} else {
last_seed_hash = new Buffer(32, 0);
for (let i = 0; i < epoch_number; i++) {
last_seed_hash = sha3.update(last_seed_hash).digest();
sha3.reset();
}
}
last_epoch_number = epoch_number;
}
const difficulty = parseFloat((diff1 / bignum(rpcData.target, 16).toNumber()).toFixed(9));
return {
blocktemplate_blob: blob.toString('hex'),
// reserved_offset to CCCCCC....
reserved_offset: offset1 + 4 /* txCoinbase.version */ + 1 /* vinLen */ + 32 /* hash */ + 4 /* index */ + 1 /* vScript len */,
seed_hash: last_seed_hash.toString('hex'),
difficulty: difficulty,
height: rpcData.height,
bits: rpcData.bits,
};
};
module.exports.convertRavenBlob = function(blobBuffer) {
let header = blobBuffer.slice(0, 80); // header
let offset = 80 + 8 + 32;
const nTransactions = varuint.decode(blobBuffer, offset);
offset += varuint.decode.bytes;
let transactions = [];
for (let i = 0; i < nTransactions; ++i) {
const tx = bitcoin.Transaction.fromBuffer(blobBuffer.slice(offset), true);
transactions.push(tx);
offset += tx.byteLength();
}
getMerkleRoot2(transactions).copy(header, 4 + 32);
return reverseBuffer(crypto.createHash('sha256').update(header).digest());
};
module.exports.constructNewRavenBlob = function(blockTemplate, nonceBuff, mixhashBuff) {
nonceBuff.copy (blockTemplate, 80, 0, 8);
mixhashBuff.copy(blockTemplate, 88, 0, 32);
return blockTemplate;
};
module.exports.constructNewDeroBlob = function(blockTemplate, nonceBuff) {
nonceBuff.copy(blockTemplate, 39, 0, 4);
return blockTemplate;
};
+8 -2
View File
@@ -1,6 +1,6 @@
{
"name": "cryptoforknote-util",
"version": "8.1.0",
"version": "9.0.2",
"main": "cryptoforknote-util",
"author": {
"name": "LucasJones",
@@ -11,8 +11,14 @@
"url": "https://github.com/MoneroOcean/node-cryptoforknote-util.git"
},
"dependencies": {
"promise": "*",
"bindings": "*",
"nan": "^2.0.0"
"nan": "^2.0.0",
"bignum": "^0.13.1",
"sha3": "*",
"varuint-bitcoin": "^1.0.4",
"bitcoinjs-lib": "git+https://github.com/bitcoinjs/bitcoinjs-lib.git#533d6c2e6d0aa4111f7948b1c12003cf6ef83137",
"merkle-bitcoin": "git+https://github.com/joshuayabut/merkle-bitcoin.git#ec00ae20ba60d444e150ead03c747695ddaa83a1"
},
"keywords": [
"cryptonight",
+4
View File
@@ -24,6 +24,10 @@ namespace crypto {
public:
uint32_t data[40];
};
POD_CLASS cycle48 {
public:
uint32_t data[48];
};
POD_CLASS hash {
char data[HASH_SIZE];
};
+1
View File
@@ -16,4 +16,5 @@ enum BLOB_TYPE {
BLOB_TYPE_CRYPTONOTE_XTNC = 9, // XTNC
BLOB_TYPE_CRYPTONOTE_TUBE = 10, // TUBE
BLOB_TYPE_CRYPTONOTE_XHV = 11, // Haven
BLOB_TYPE_CRYPTONOTE_XTA = 12, // ITALO
};
+4 -2
View File
@@ -426,7 +426,7 @@ namespace cryptonote
const uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x36, 0x78, 0x9e, 0x7a, 0x1e, 0x28, 0x14, 0x36, 0x46, 0x42, 0x29, 0x82, 0x8f, 0x81, 0x7d, 0x66, 0x12, 0xf7, 0xb4, 0x77, 0xd6, 0x65, 0x91, 0xff, 0x96, 0xa9, 0xe0, 0x64, 0xbc, 0xc9, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
blobdata blobdata((char*)data, sizeof(data));
const unsigned char* p = (unsigned char*)&miner_tx_hash;
for (int i = 0; i != HASH_SIZE; ++ i, ++ p) blobdata[i] = *p;
for (int i = 0; i != crypto::HASH_SIZE; ++ i, ++ p) blobdata[i] = *p;
get_blob_hash(blobdata, miner_tx_hash);
}
@@ -494,13 +494,14 @@ namespace cryptonote
offshore::pricing_record pricing_record;
crypto::cycle cycle;
crypto::cycle40 cycle40;
crypto::cycle48 cycle48;
BEGIN_SERIALIZE()
VARINT_FIELD(major_version)
VARINT_FIELD(minor_version)
if (blob_type != BLOB_TYPE_FORKNOTE2) VARINT_FIELD(timestamp)
FIELD(prev_id)
if (blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || blob_type == BLOB_TYPE_CRYPTONOTE_TUBE) FIELD(nonce8)
if (blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || blob_type == BLOB_TYPE_CRYPTONOTE_TUBE || blob_type == BLOB_TYPE_CRYPTONOTE_XTA) FIELD(nonce8)
if (blob_type != BLOB_TYPE_FORKNOTE2) {
if (blob_type == BLOB_TYPE_AEON) {
FIELD(nonce)
@@ -513,6 +514,7 @@ namespace cryptonote
}
if (blob_type == BLOB_TYPE_CRYPTONOTE_XTNC || blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO) FIELD(cycle)
if (blob_type == BLOB_TYPE_CRYPTONOTE_TUBE) FIELD(cycle40)
if (blob_type == BLOB_TYPE_CRYPTONOTE_XTA) FIELD(cycle48)
if (blob_type == BLOB_TYPE_CRYPTONOTE_XHV) FIELD(pricing_record)
END_SERIALIZE()
@@ -475,7 +475,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool get_block_hashing_blob(const block& b, blobdata& blob)
{
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_XTNC || b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE) {
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_XTNC || b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE || b.blob_type == BLOB_TYPE_CRYPTONOTE_XTA) {
blob = t_serializable_object_to_blob(b.major_version);
blob.append(reinterpret_cast<const char*>(&b.minor_version), sizeof(b.minor_version));
blob.append(reinterpret_cast<const char*>(&b.timestamp), sizeof(b.timestamp));
@@ -490,7 +490,7 @@ namespace cryptonote
if (b.blob_type == BLOB_TYPE_CRYPTONOTE3) {
blob.append(reinterpret_cast<const char*>(&b.uncle), sizeof(b.uncle));
}
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE) {
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE || b.blob_type == BLOB_TYPE_CRYPTONOTE_XTA) {
blob.append(reinterpret_cast<const char*>(&b.nonce8), sizeof(b.nonce8));
}
return true;
+6
View File
@@ -231,6 +231,12 @@ NAN_METHOD(construct_block_blob) { // (parentBlockTemplateBuffer, nonceBuffer, c
for (int i = 0; i < 40; i++ ) b.cycle40.data[i] = cycle->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->NumberValue(isolate->GetCurrentContext()).ToChecked();
}
if (blob_type == BLOB_TYPE_CRYPTONOTE_XTA) {
if (info.Length() != 4) return THROW_ERROR_EXCEPTION("You must provide 4 arguments.");
Local<Array> cycle = Local<Array>::Cast(info[3]);
for (int i = 0; i < 48; i++ ) b.cycle48.data[i] = cycle->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->NumberValue(isolate->GetCurrentContext()).ToChecked();
}
if (!block_to_blob(b, output)) return THROW_ERROR_EXCEPTION("Failed to convert block to blob");
v8::Local<v8::Value> returnValue = Nan::CopyBuffer((char*)output.data(), output.size()).ToLocalChecked();
+404 -155
View File
@@ -33,21 +33,22 @@
#define RCT_TYPES_H
#include <cstddef>
#include <mutex>
#include <vector>
#include <tuple>
#include <iostream>
#include <cinttypes>
#include <sodium/crypto_verify_32.h>
extern "C" {
#include "crypto/generic-ops.h"
#include "crypto/crypto-ops.h"
#include "crypto/random.h"
#include "crypto/keccak.h"
}
#include "crypto/generic-ops.h"
#include "crypto/crypto.h"
#include "serialization/serialization.h"
#include "hex.h"
#include "span.h"
#include "serialization/vector.h"
#include "serialization/debug_archive.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"
@@ -65,9 +66,6 @@ extern "C" {
//for printing large ints
using namespace std;
using namespace crypto;
//Namespace specifically for ring ct code
namespace rct {
//basic ops containers
@@ -84,11 +82,11 @@ namespace rct {
unsigned char operator[](int i) const {
return bytes[i];
}
bool operator==(const key &k) const { return !memcmp(bytes, k.bytes, sizeof(bytes)); }
bool operator==(const key &k) const { return !crypto_verify_32(bytes, k.bytes); }
unsigned char bytes[32];
};
typedef vector<key> keyV; //vector of keys
typedef vector<keyV> keyM; //matrix of keys (indexed by column first)
typedef std::vector<key> keyV; //vector of keys
typedef std::vector<keyV> keyM; //matrix of keys (indexed by column first)
//containers For CT operations
//if it's representing a private ctkey then "dest" contains the secret key of the address
@@ -99,24 +97,42 @@ namespace rct {
key dest;
key mask; //C here if public
};
typedef vector<ctkey> ctkeyV;
typedef vector<ctkeyV> ctkeyM;
typedef std::vector<ctkey> ctkeyV;
typedef std::vector<ctkeyV> ctkeyM;
//used for multisig data
struct multisig_kLRki {
key k;
key L;
key R;
key ki;
};
struct multisig_out {
std::vector<key> c; // for all inputs
std::vector<key> mu_p; // for all inputs
std::vector<key> c0; // for all inputs
BEGIN_SERIALIZE_OBJECT()
FIELD(c)
FIELD(mu_p)
if (!mu_p.empty() && mu_p.size() != c.size())
return false;
END_SERIALIZE()
};
//data for passing the amount to the receiver secretly
// If the pedersen commitment to an amount is C = aG + bH,
// "mask" contains a 32 byte key a
// "amount" contains a hex representation (in 32 bytes) of a 64 bit number
// "senderPk" is not the senders actual public key, but a one-time public key generated for
// the purpose of the ECDH exchange
struct ecdhTuple {
key mask;
key amount;
key senderPk;
BEGIN_SERIALIZE_OBJECT()
FIELD(mask)
FIELD(mask) // not saved from v2 BPs
FIELD(amount)
// FIELD(senderPk) // not serialized, as we do not use it in monero currently
END_SERIALIZE()
};
@@ -137,7 +153,7 @@ namespace rct {
};
//just contains the necessary keys to represent MLSAG sigs
//c.f. http://eprint.iacr.org/2015/1098
//c.f. https://eprint.iacr.org/2015/1098
struct mgSig {
keyM ss;
key cc;
@@ -149,6 +165,23 @@ namespace rct {
// FIELD(II) - not serialized, it can be reconstructed
END_SERIALIZE()
};
// CLSAG signature
struct clsag {
keyV s; // scalars
key c1;
key I; // signing key image
key D; // commitment key image
BEGIN_SERIALIZE_OBJECT()
FIELD(s)
FIELD(c1)
// FIELD(I) - not serialized, it can be reconstructed
FIELD(D)
END_SERIALIZE()
};
//contains the data for an Borromean sig
// also contains the "Ci" values such that
// \sum Ci = C
@@ -164,6 +197,49 @@ namespace rct {
FIELD(Ci)
END_SERIALIZE()
};
struct Bulletproof
{
rct::keyV V;
rct::key A, S, T1, T2;
rct::key taux, mu;
rct::keyV L, R;
rct::key a, b, t;
Bulletproof():
A({}), S({}), T1({}), T2({}), taux({}), mu({}), a({}), b({}), t({}) {}
Bulletproof(const rct::key &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t):
V({V}), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {}
Bulletproof(const rct::keyV &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t):
V(V), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {}
bool operator==(const Bulletproof &other) const { return V == other.V && A == other.A && S == other.S && T1 == other.T1 && T2 == other.T2 && taux == other.taux && mu == other.mu && L == other.L && R == other.R && a == other.a && b == other.b && t == other.t; }
BEGIN_SERIALIZE_OBJECT()
// Commitments aren't saved, they're restored via outPk
// FIELD(V)
FIELD(A)
FIELD(S)
FIELD(T1)
FIELD(T2)
FIELD(taux)
FIELD(mu)
FIELD(L)
FIELD(R)
FIELD(a)
FIELD(b)
FIELD(t)
if (L.empty() || L.size() != R.size())
return false;
END_SERIALIZE()
};
size_t n_bulletproof_amounts(const Bulletproof &proof);
size_t n_bulletproof_max_amounts(const Bulletproof &proof);
size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs);
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs);
//A container to hold all signatures necessary for RingCT
// rangeSigs holds all the rangeproof data of a transaction
// MG holds the MLSAG signature of a transaction
@@ -175,6 +251,14 @@ namespace rct {
RCTTypeNull = 0,
RCTTypeFull = 1,
RCTTypeSimple = 2,
RCTTypeBulletproof = 3,
RCTTypeBulletproof2 = 4,
RCTTypeCLSAG = 5,
};
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
struct RCTConfig {
RangeProofType range_proof_type;
int bp_version;
};
struct rctSigBase {
uint8_t type;
@@ -182,23 +266,37 @@ namespace rct {
ctkeyM mixRing; //the set of all pubkeys / copy
//pairs that you mix with
keyV pseudoOuts; //C - for simple rct
vector<ecdhTuple> ecdhInfo;
std::vector<ecdhTuple> ecdhInfo;
ctkeyV outPk;
ctkeyV outPk_usd;
xmr_amount txnFee; // contains b
xmr_amount txnFee_usd;
xmr_amount txnOffshoreFee;
xmr_amount txnOffshoreFee_usd;
template<bool W, template <bool> class Archive>
bool serialize_rctsig_base(Archive<W> &ar, size_t inputs, size_t outputs)
{
FIELD(type)
if (type == RCTTypeNull)
return true;
if (type != RCTTypeFull && type != RCTTypeSimple)
return ar.stream().good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG)
return false;
VARINT_FIELD(txnFee)
if (type == RCTTypeCLSAG)
{
VARINT_FIELD(txnFee_usd)
VARINT_FIELD(txnOffshoreFee)
VARINT_FIELD(txnOffshoreFee_usd)
} else {
txnFee_usd = 0;
txnOffshoreFee = 0;
txnOffshoreFee_usd = 0;
}
// inputs/outputs not saved, only here for serialization help
// FIELD(message) - not serialized, it can be reconstructed
// FIELD(mixRing) - not serialized, it can be reconstructed
if (type == RCTTypeSimple)
if (type == RCTTypeSimple) // moved to prunable with bulletproofs
{
ar.tag("pseudoOuts");
ar.begin_array();
@@ -221,7 +319,19 @@ namespace rct {
return false;
for (size_t i = 0; i < outputs; ++i)
{
FIELDS(ecdhInfo[i])
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
{
ar.begin_object();
if (!typename Archive<W>::is_saving())
memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes));
crypto::hash8 &amount = (crypto::hash8&)ecdhInfo[i].amount;
FIELD(amount);
ar.end_object();
}
else
{
FIELDS(ecdhInfo[i])
}
if (outputs - i > 1)
ar.delimit_array();
}
@@ -239,87 +349,201 @@ namespace rct {
ar.delimit_array();
}
ar.end_array();
return true;
}
if (type == RCTTypeCLSAG)
{
ar.tag("outPk_usd");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, outPk_usd);
if (outPk_usd.size() != outputs)
return false;
for (size_t i = 0; i < outputs; ++i)
{
FIELDS(outPk_usd[i].mask)
if (outputs - i > 1)
ar.delimit_array();
}
ar.end_array();
}
return ar.stream().good();
}
};
struct rctSigPrunable {
vector<rangeSig> rangeSigs;
vector<mgSig> MGs; // simple rct has N, full has 1
std::vector<rangeSig> rangeSigs;
std::vector<Bulletproof> bulletproofs;
std::vector<mgSig> MGs; // simple rct has N, full has 1
std::vector<clsag> CLSAGs;
keyV pseudoOuts; //C - for simple rct
// when changing this function, update cryptonote::get_pruned_transaction_weight
template<bool W, template <bool> class Archive>
bool serialize_rctsig_prunable(Archive<W> &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin)
{
if (type == RCTTypeNull)
return true;
if (type != RCTTypeFull && type != RCTTypeSimple)
return ar.stream().good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG)
return false;
ar.tag("rangeSigs");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, rangeSigs);
if (rangeSigs.size() != outputs)
return false;
for (size_t i = 0; i < outputs; ++i)
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
{
FIELDS(rangeSigs[i])
if (outputs - i > 1)
ar.delimit_array();
}
ar.end_array();
ar.tag("MGs");
ar.begin_array();
// we keep a byte for size of MGs, because we don't know whether this is
// a simple or full rct signature, and it's starting to annoy the hell out of me
size_t mg_elements = type == RCTTypeSimple ? inputs : 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
if (MGs.size() != mg_elements)
return false;
for (size_t i = 0; i < mg_elements; ++i)
{
// we save the MGs contents directly, because we want it to save its
// arrays and matrices without the size prefixes, and the load can't
// know what size to expect if it's not in the data
ar.begin_object();
ar.tag("ss");
uint32_t nbp = bulletproofs.size();
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
VARINT_FIELD(nbp)
else
FIELD(nbp)
ar.tag("bp");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, MGs[i].ss);
if (MGs[i].ss.size() != mixin + 1)
if (nbp > outputs)
return false;
for (size_t j = 0; j < mixin + 1; ++j)
PREPARE_CUSTOM_VECTOR_SERIALIZATION(nbp, bulletproofs);
for (size_t i = 0; i < nbp; ++i)
{
FIELDS(bulletproofs[i])
if (nbp - i > 1)
ar.delimit_array();
}
if (n_bulletproof_max_amounts(bulletproofs) < outputs)
return false;
ar.end_array();
}
else
{
ar.tag("rangeSigs");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, rangeSigs);
if (rangeSigs.size() != outputs)
return false;
for (size_t i = 0; i < outputs; ++i)
{
FIELDS(rangeSigs[i])
if (outputs - i > 1)
ar.delimit_array();
}
ar.end_array();
}
if (type == RCTTypeCLSAG)
{
ar.tag("CLSAGs");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(inputs, CLSAGs);
if (CLSAGs.size() != inputs)
return false;
for (size_t i = 0; i < inputs; ++i)
{
// we save the CLSAGs contents directly, because we want it to save its
// arrays without the size prefixes, and the load can't know what size
// to expect if it's not in the data
ar.begin_object();
ar.tag("s");
ar.begin_array();
size_t mg_ss2_elements = (type == RCTTypeSimple ? 1 : inputs) + 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
if (MGs[i].ss[j].size() != mg_ss2_elements)
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, CLSAGs[i].s);
if (CLSAGs[i].s.size() != mixin + 1)
return false;
for (size_t k = 0; k < mg_ss2_elements; ++k)
for (size_t j = 0; j <= mixin; ++j)
{
FIELDS(MGs[i].ss[j][k])
if (mg_ss2_elements - k > 1)
FIELDS(CLSAGs[i].s[j])
if (mixin + 1 - j > 1)
ar.delimit_array();
}
ar.end_array();
if (mixin + 1 - j > 1)
ar.tag("c1");
FIELDS(CLSAGs[i].c1)
// CLSAGs[i].I not saved, it can be reconstructed
ar.tag("D");
FIELDS(CLSAGs[i].D)
ar.end_object();
if (inputs - i > 1)
ar.delimit_array();
}
ar.end_array();
}
else
{
ar.tag("MGs");
ar.begin_array();
// we keep a byte for size of MGs, because we don't know whether this is
// a simple or full rct signature, and it's starting to annoy the hell out of me
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? inputs : 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
if (MGs.size() != mg_elements)
return false;
for (size_t i = 0; i < mg_elements; ++i)
{
// we save the MGs contents directly, because we want it to save its
// arrays and matrices without the size prefixes, and the load can't
// know what size to expect if it's not in the data
ar.begin_object();
ar.tag("ss");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, MGs[i].ss);
if (MGs[i].ss.size() != mixin + 1)
return false;
for (size_t j = 0; j < mixin + 1; ++j)
{
ar.begin_array();
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? 1 : inputs) + 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
if (MGs[i].ss[j].size() != mg_ss2_elements)
return false;
for (size_t k = 0; k < mg_ss2_elements; ++k)
{
FIELDS(MGs[i].ss[j][k])
if (mg_ss2_elements - k > 1)
ar.delimit_array();
}
ar.end_array();
if (mixin + 1 - j > 1)
ar.delimit_array();
}
ar.end_array();
ar.tag("cc");
FIELDS(MGs[i].cc)
// MGs[i].II not saved, it can be reconstructed
ar.end_object();
if (mg_elements - i > 1)
ar.delimit_array();
}
ar.end_array();
}
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG)
{
ar.tag("pseudoOuts");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(inputs, pseudoOuts);
if (pseudoOuts.size() != inputs)
return false;
for (size_t i = 0; i < inputs; ++i)
{
FIELDS(pseudoOuts[i])
if (inputs - i > 1)
ar.delimit_array();
}
ar.end_array();
ar.tag("cc");
FIELDS(MGs[i].cc)
// MGs[i].II not saved, it can be reconstructed
if (mg_elements - i > 1)
ar.delimit_array();
ar.end_object();
}
ar.end_array();
return true;
return ar.stream().good();
}
};
struct rctSig: public rctSigBase {
rctSigPrunable p;
keyV& get_pseudo_outs()
{
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG ? p.pseudoOuts : pseudoOuts;
}
keyV const& get_pseudo_outs() const
{
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG ? p.pseudoOuts : pseudoOuts;
}
};
//other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint
@@ -328,70 +552,70 @@ namespace rct {
//H2 contains 2^i H in each index, i.e. H, 2H, 4H, 8H, ...
//This is used for the range proofG
//You can regenerate this by running python2 Test.py HPow2 in the MiniNero repo
static const key64 H2 = {{0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94},
{0x8f, 0xaa, 0x44, 0x8a, 0xe4, 0xb3, 0xe2, 0xbb, 0x3d, 0x4d, 0x13, 0x09, 0x09, 0xf5, 0x5f, 0xcd, 0x79, 0x71, 0x1c, 0x1c, 0x83, 0xcd, 0xbc, 0xca, 0xdd, 0x42, 0xcb, 0xe1, 0x51, 0x5e, 0x87, 0x12},
{0x12, 0xa7, 0xd6, 0x2c, 0x77, 0x91, 0x65, 0x4a, 0x57, 0xf3, 0xe6, 0x76, 0x94, 0xed, 0x50, 0xb4, 0x9a, 0x7d, 0x9e, 0x3f, 0xc1, 0xe4, 0xc7, 0xa0, 0xbd, 0xe2, 0x9d, 0x18, 0x7e, 0x9c, 0xc7, 0x1d},
{0x78, 0x9a, 0xb9, 0x93, 0x4b, 0x49, 0xc4, 0xf9, 0xe6, 0x78, 0x5c, 0x6d, 0x57, 0xa4, 0x98, 0xb3, 0xea, 0xd4, 0x43, 0xf0, 0x4f, 0x13, 0xdf, 0x11, 0x0c, 0x54, 0x27, 0xb4, 0xf2, 0x14, 0xc7, 0x39},
{0x77, 0x1e, 0x92, 0x99, 0xd9, 0x4f, 0x02, 0xac, 0x72, 0xe3, 0x8e, 0x44, 0xde, 0x56, 0x8a, 0xc1, 0xdc, 0xb2, 0xed, 0xc6, 0xed, 0xb6, 0x1f, 0x83, 0xca, 0x41, 0x8e, 0x10, 0x77, 0xce, 0x3d, 0xe8},
{0x73, 0xb9, 0x6d, 0xb4, 0x30, 0x39, 0x81, 0x9b, 0xda, 0xf5, 0x68, 0x0e, 0x5c, 0x32, 0xd7, 0x41, 0x48, 0x88, 0x84, 0xd1, 0x8d, 0x93, 0x86, 0x6d, 0x40, 0x74, 0xa8, 0x49, 0x18, 0x2a, 0x8a, 0x64},
{0x8d, 0x45, 0x8e, 0x1c, 0x2f, 0x68, 0xeb, 0xeb, 0xcc, 0xd2, 0xfd, 0x5d, 0x37, 0x9f, 0x5e, 0x58, 0xf8, 0x13, 0x4d, 0xf3, 0xe0, 0xe8, 0x8c, 0xad, 0x3d, 0x46, 0x70, 0x10, 0x63, 0xa8, 0xd4, 0x12},
{0x09, 0x55, 0x1e, 0xdb, 0xe4, 0x94, 0x41, 0x8e, 0x81, 0x28, 0x44, 0x55, 0xd6, 0x4b, 0x35, 0xee, 0x8a, 0xc0, 0x93, 0x06, 0x8a, 0x5f, 0x16, 0x1f, 0xa6, 0x63, 0x75, 0x59, 0x17, 0x7e, 0xf4, 0x04},
{0xd0, 0x5a, 0x88, 0x66, 0xf4, 0xdf, 0x8c, 0xee, 0x1e, 0x26, 0x8b, 0x1d, 0x23, 0xa4, 0xc5, 0x8c, 0x92, 0xe7, 0x60, 0x30, 0x97, 0x86, 0xcd, 0xac, 0x0f, 0xed, 0xa1, 0xd2, 0x47, 0xa9, 0xc9, 0xa7},
{0x55, 0xcd, 0xaa, 0xd5, 0x18, 0xbd, 0x87, 0x1d, 0xd1, 0xeb, 0x7b, 0xc7, 0x02, 0x3e, 0x1d, 0xc0, 0xfd, 0xf3, 0x33, 0x98, 0x64, 0xf8, 0x8f, 0xdd, 0x2d, 0xe2, 0x69, 0xfe, 0x9e, 0xe1, 0x83, 0x2d},
{0xe7, 0x69, 0x7e, 0x95, 0x1a, 0x98, 0xcf, 0xd5, 0x71, 0x2b, 0x84, 0xbb, 0xe5, 0xf3, 0x4e, 0xd7, 0x33, 0xe9, 0x47, 0x3f, 0xcb, 0x68, 0xed, 0xa6, 0x6e, 0x37, 0x88, 0xdf, 0x19, 0x58, 0xc3, 0x06},
{0xf9, 0x2a, 0x97, 0x0b, 0xae, 0x72, 0x78, 0x29, 0x89, 0xbf, 0xc8, 0x3a, 0xdf, 0xaa, 0x92, 0xa4, 0xf4, 0x9c, 0x7e, 0x95, 0x91, 0x8b, 0x3b, 0xba, 0x3c, 0xdc, 0x7f, 0xe8, 0x8a, 0xcc, 0x8d, 0x47},
{0x1f, 0x66, 0xc2, 0xd4, 0x91, 0xd7, 0x5a, 0xf9, 0x15, 0xc8, 0xdb, 0x6a, 0x6d, 0x1c, 0xb0, 0xcd, 0x4f, 0x7d, 0xdc, 0xd5, 0xe6, 0x3d, 0x3b, 0xa9, 0xb8, 0x3c, 0x86, 0x6c, 0x39, 0xef, 0x3a, 0x2b},
{0x3e, 0xec, 0x98, 0x84, 0xb4, 0x3f, 0x58, 0xe9, 0x3e, 0xf8, 0xde, 0xea, 0x26, 0x00, 0x04, 0xef, 0xea, 0x2a, 0x46, 0x34, 0x4f, 0xc5, 0x96, 0x5b, 0x1a, 0x7d, 0xd5, 0xd1, 0x89, 0x97, 0xef, 0xa7},
{0xb2, 0x9f, 0x8f, 0x0c, 0xcb, 0x96, 0x97, 0x7f, 0xe7, 0x77, 0xd4, 0x89, 0xd6, 0xbe, 0x9e, 0x7e, 0xbc, 0x19, 0xc4, 0x09, 0xb5, 0x10, 0x35, 0x68, 0xf2, 0x77, 0x61, 0x1d, 0x7e, 0xa8, 0x48, 0x94},
{0x56, 0xb1, 0xf5, 0x12, 0x65, 0xb9, 0x55, 0x98, 0x76, 0xd5, 0x8d, 0x24, 0x9d, 0x0c, 0x14, 0x6d, 0x69, 0xa1, 0x03, 0x63, 0x66, 0x99, 0x87, 0x4d, 0x3f, 0x90, 0x47, 0x35, 0x50, 0xfe, 0x3f, 0x2c},
{0x1d, 0x7a, 0x36, 0x57, 0x5e, 0x22, 0xf5, 0xd1, 0x39, 0xff, 0x9c, 0xc5, 0x10, 0xfa, 0x13, 0x85, 0x05, 0x57, 0x6b, 0x63, 0x81, 0x5a, 0x94, 0xe4, 0xb0, 0x12, 0xbf, 0xd4, 0x57, 0xca, 0xaa, 0xda},
{0xd0, 0xac, 0x50, 0x7a, 0x86, 0x4e, 0xcd, 0x05, 0x93, 0xfa, 0x67, 0xbe, 0x7d, 0x23, 0x13, 0x43, 0x92, 0xd0, 0x0e, 0x40, 0x07, 0xe2, 0x53, 0x48, 0x78, 0xd9, 0xb2, 0x42, 0xe1, 0x0d, 0x76, 0x20},
{0xf6, 0xc6, 0x84, 0x0b, 0x9c, 0xf1, 0x45, 0xbb, 0x2d, 0xcc, 0xf8, 0x6e, 0x94, 0x0b, 0xe0, 0xfc, 0x09, 0x8e, 0x32, 0xe3, 0x10, 0x99, 0xd5, 0x6f, 0x7f, 0xe0, 0x87, 0xbd, 0x5d, 0xeb, 0x50, 0x94},
{0x28, 0x83, 0x1a, 0x33, 0x40, 0x07, 0x0e, 0xb1, 0xdb, 0x87, 0xc1, 0x2e, 0x05, 0x98, 0x0d, 0x5f, 0x33, 0xe9, 0xef, 0x90, 0xf8, 0x3a, 0x48, 0x17, 0xc9, 0xf4, 0xa0, 0xa3, 0x32, 0x27, 0xe1, 0x97},
{0x87, 0x63, 0x22, 0x73, 0xd6, 0x29, 0xcc, 0xb7, 0xe1, 0xed, 0x1a, 0x76, 0x8f, 0xa2, 0xeb, 0xd5, 0x17, 0x60, 0xf3, 0x2e, 0x1c, 0x0b, 0x86, 0x7a, 0x5d, 0x36, 0x8d, 0x52, 0x71, 0x05, 0x5c, 0x6e},
{0x5c, 0x7b, 0x29, 0x42, 0x43, 0x47, 0x96, 0x4d, 0x04, 0x27, 0x55, 0x17, 0xc5, 0xae, 0x14, 0xb6, 0xb5, 0xea, 0x27, 0x98, 0xb5, 0x73, 0xfc, 0x94, 0xe6, 0xe4, 0x4a, 0x53, 0x21, 0x60, 0x0c, 0xfb},
{0xe6, 0x94, 0x50, 0x42, 0xd7, 0x8b, 0xc2, 0xc3, 0xbd, 0x6e, 0xc5, 0x8c, 0x51, 0x1a, 0x9f, 0xe8, 0x59, 0xc0, 0xad, 0x63, 0xfd, 0xe4, 0x94, 0xf5, 0x03, 0x9e, 0x0e, 0x82, 0x32, 0x61, 0x2b, 0xd5},
{0x36, 0xd5, 0x69, 0x07, 0xe2, 0xec, 0x74, 0x5d, 0xb6, 0xe5, 0x4f, 0x0b, 0x2e, 0x1b, 0x23, 0x00, 0xab, 0xcb, 0x42, 0x2e, 0x71, 0x2d, 0xa5, 0x88, 0xa4, 0x0d, 0x3f, 0x1e, 0xbb, 0xbe, 0x02, 0xf6},
{0x34, 0xdb, 0x6e, 0xe4, 0xd0, 0x60, 0x8e, 0x5f, 0x78, 0x36, 0x50, 0x49, 0x5a, 0x3b, 0x2f, 0x52, 0x73, 0xc5, 0x13, 0x4e, 0x52, 0x84, 0xe4, 0xfd, 0xf9, 0x66, 0x27, 0xbb, 0x16, 0xe3, 0x1e, 0x6b},
{0x8e, 0x76, 0x59, 0xfb, 0x45, 0xa3, 0x78, 0x7d, 0x67, 0x4a, 0xe8, 0x67, 0x31, 0xfa, 0xa2, 0x53, 0x8e, 0xc0, 0xfd, 0xf4, 0x42, 0xab, 0x26, 0xe9, 0xc7, 0x91, 0xfa, 0xda, 0x08, 0x94, 0x67, 0xe9},
{0x30, 0x06, 0xcf, 0x19, 0x8b, 0x24, 0xf3, 0x1b, 0xb4, 0xc7, 0xe6, 0x34, 0x60, 0x00, 0xab, 0xc7, 0x01, 0xe8, 0x27, 0xcf, 0xbb, 0x5d, 0xf5, 0x2d, 0xcf, 0xa4, 0x2e, 0x9c, 0xa9, 0xff, 0x08, 0x02},
{0xf5, 0xfd, 0x40, 0x3c, 0xb6, 0xe8, 0xbe, 0x21, 0x47, 0x2e, 0x37, 0x7f, 0xfd, 0x80, 0x5a, 0x8c, 0x60, 0x83, 0xea, 0x48, 0x03, 0xb8, 0x48, 0x53, 0x89, 0xcc, 0x3e, 0xbc, 0x21, 0x5f, 0x00, 0x2a},
{0x37, 0x31, 0xb2, 0x60, 0xeb, 0x3f, 0x94, 0x82, 0xe4, 0x5f, 0x1c, 0x3f, 0x3b, 0x9d, 0xcf, 0x83, 0x4b, 0x75, 0xe6, 0xee, 0xf8, 0xc4, 0x0f, 0x46, 0x1e, 0xa2, 0x7e, 0x8b, 0x6e, 0xd9, 0x47, 0x3d},
{0x9f, 0x9d, 0xab, 0x09, 0xc3, 0xf5, 0xe4, 0x28, 0x55, 0xc2, 0xde, 0x97, 0x1b, 0x65, 0x93, 0x28, 0xa2, 0xdb, 0xc4, 0x54, 0x84, 0x5f, 0x39, 0x6f, 0xfc, 0x05, 0x3f, 0x0b, 0xb1, 0x92, 0xf8, 0xc3},
{0x5e, 0x05, 0x5d, 0x25, 0xf8, 0x5f, 0xdb, 0x98, 0xf2, 0x73, 0xe4, 0xaf, 0xe0, 0x84, 0x64, 0xc0, 0x03, 0xb7, 0x0f, 0x1e, 0xf0, 0x67, 0x7b, 0xb5, 0xe2, 0x57, 0x06, 0x40, 0x0b, 0xe6, 0x20, 0xa5},
{0x86, 0x8b, 0xcf, 0x36, 0x79, 0xcb, 0x6b, 0x50, 0x0b, 0x94, 0x41, 0x8c, 0x0b, 0x89, 0x25, 0xf9, 0x86, 0x55, 0x30, 0x30, 0x3a, 0xe4, 0xe4, 0xb2, 0x62, 0x59, 0x18, 0x65, 0x66, 0x6a, 0x45, 0x90},
{0xb3, 0xdb, 0x6b, 0xd3, 0x89, 0x7a, 0xfb, 0xd1, 0xdf, 0x3f, 0x96, 0x44, 0xab, 0x21, 0xc8, 0x05, 0x0e, 0x1f, 0x00, 0x38, 0xa5, 0x2f, 0x7c, 0xa9, 0x5a, 0xc0, 0xc3, 0xde, 0x75, 0x58, 0xcb, 0x7a},
{0x81, 0x19, 0xb3, 0xa0, 0x59, 0xff, 0x2c, 0xac, 0x48, 0x3e, 0x69, 0xbc, 0xd4, 0x1d, 0x6d, 0x27, 0x14, 0x94, 0x47, 0x91, 0x42, 0x88, 0xbb, 0xea, 0xee, 0x34, 0x13, 0xe6, 0xdc, 0xc6, 0xd1, 0xeb},
{0x10, 0xfc, 0x58, 0xf3, 0x5f, 0xc7, 0xfe, 0x7a, 0xe8, 0x75, 0x52, 0x4b, 0xb5, 0x85, 0x00, 0x03, 0x00, 0x5b, 0x7f, 0x97, 0x8c, 0x0c, 0x65, 0xe2, 0xa9, 0x65, 0x46, 0x4b, 0x6d, 0x00, 0x81, 0x9c},
{0x5a, 0xcd, 0x94, 0xeb, 0x3c, 0x57, 0x83, 0x79, 0xc1, 0xea, 0x58, 0xa3, 0x43, 0xec, 0x4f, 0xcf, 0xf9, 0x62, 0x77, 0x6f, 0xe3, 0x55, 0x21, 0xe4, 0x75, 0xa0, 0xe0, 0x6d, 0x88, 0x7b, 0x2d, 0xb9},
{0x33, 0xda, 0xf3, 0xa2, 0x14, 0xd6, 0xe0, 0xd4, 0x2d, 0x23, 0x00, 0xa7, 0xb4, 0x4b, 0x39, 0x29, 0x0d, 0xb8, 0x98, 0x9b, 0x42, 0x79, 0x74, 0xcd, 0x86, 0x5d, 0xb0, 0x11, 0x05, 0x5a, 0x29, 0x01},
{0xcf, 0xc6, 0x57, 0x2f, 0x29, 0xaf, 0xd1, 0x64, 0xa4, 0x94, 0xe6, 0x4e, 0x6f, 0x1a, 0xeb, 0x82, 0x0c, 0x3e, 0x7d, 0xa3, 0x55, 0x14, 0x4e, 0x51, 0x24, 0xa3, 0x91, 0xd0, 0x6e, 0x9f, 0x95, 0xea},
{0xd5, 0x31, 0x2a, 0x4b, 0x0e, 0xf6, 0x15, 0xa3, 0x31, 0xf6, 0x35, 0x2c, 0x2e, 0xd2, 0x1d, 0xac, 0x9e, 0x7c, 0x36, 0x39, 0x8b, 0x93, 0x9a, 0xec, 0x90, 0x1c, 0x25, 0x7f, 0x6c, 0xbc, 0x9e, 0x8e},
{0x55, 0x1d, 0x67, 0xfe, 0xfc, 0x7b, 0x5b, 0x9f, 0x9f, 0xdb, 0xf6, 0xaf, 0x57, 0xc9, 0x6c, 0x8a, 0x74, 0xd7, 0xe4, 0x5a, 0x00, 0x20, 0x78, 0xa7, 0xb5, 0xba, 0x45, 0xc6, 0xfd, 0xe9, 0x3e, 0x33},
{0xd5, 0x0a, 0xc7, 0xbd, 0x5c, 0xa5, 0x93, 0xc6, 0x56, 0x92, 0x8f, 0x38, 0x42, 0x80, 0x17, 0xfc, 0x7b, 0xa5, 0x02, 0x85, 0x4c, 0x43, 0xd8, 0x41, 0x49, 0x50, 0xe9, 0x6e, 0xcb, 0x40, 0x5d, 0xc3},
{0x07, 0x73, 0xe1, 0x8e, 0xa1, 0xbe, 0x44, 0xfe, 0x1a, 0x97, 0xe2, 0x39, 0x57, 0x3c, 0xfa, 0xe3, 0xe4, 0xe9, 0x5e, 0xf9, 0xaa, 0x9f, 0xaa, 0xbe, 0xac, 0x12, 0x74, 0xd3, 0xad, 0x26, 0x16, 0x04},
{0xe9, 0xaf, 0x0e, 0x7c, 0xa8, 0x93, 0x30, 0xd2, 0xb8, 0x61, 0x5d, 0x1b, 0x41, 0x37, 0xca, 0x61, 0x7e, 0x21, 0x29, 0x7f, 0x2f, 0x0d, 0xed, 0x8e, 0x31, 0xb7, 0xd2, 0xea, 0xd8, 0x71, 0x46, 0x60},
{0x7b, 0x12, 0x45, 0x83, 0x09, 0x7f, 0x10, 0x29, 0xa0, 0xc7, 0x41, 0x91, 0xfe, 0x73, 0x78, 0xc9, 0x10, 0x5a, 0xcc, 0x70, 0x66, 0x95, 0xed, 0x14, 0x93, 0xbb, 0x76, 0x03, 0x42, 0x26, 0xa5, 0x7b},
{0xec, 0x40, 0x05, 0x7b, 0x99, 0x54, 0x76, 0x65, 0x0b, 0x3d, 0xb9, 0x8e, 0x9d, 0xb7, 0x57, 0x38, 0xa8, 0xcd, 0x2f, 0x94, 0xd8, 0x63, 0xb9, 0x06, 0x15, 0x0c, 0x56, 0xaa, 0xc1, 0x9c, 0xaa, 0x6b},
{0x01, 0xd9, 0xff, 0x72, 0x9e, 0xfd, 0x39, 0xd8, 0x37, 0x84, 0xc0, 0xfe, 0x59, 0xc4, 0xae, 0x81, 0xa6, 0x70, 0x34, 0xcb, 0x53, 0xc9, 0x43, 0xfb, 0x81, 0x8b, 0x9d, 0x8a, 0xe7, 0xfc, 0x33, 0xe5},
{0x00, 0xdf, 0xb3, 0xc6, 0x96, 0x32, 0x8c, 0x76, 0x42, 0x45, 0x19, 0xa7, 0xbe, 0xfe, 0x8e, 0x0f, 0x6c, 0x76, 0xf9, 0x47, 0xb5, 0x27, 0x67, 0x91, 0x6d, 0x24, 0x82, 0x3f, 0x73, 0x5b, 0xaf, 0x2e},
{0x46, 0x1b, 0x79, 0x9b, 0x4d, 0x9c, 0xee, 0xa8, 0xd5, 0x80, 0xdc, 0xb7, 0x6d, 0x11, 0x15, 0x0d, 0x53, 0x5e, 0x16, 0x39, 0xd1, 0x60, 0x03, 0xc3, 0xfb, 0x7e, 0x9d, 0x1f, 0xd1, 0x30, 0x83, 0xa8},
{0xee, 0x03, 0x03, 0x94, 0x79, 0xe5, 0x22, 0x8f, 0xdc, 0x55, 0x1c, 0xbd, 0xe7, 0x07, 0x9d, 0x34, 0x12, 0xea, 0x18, 0x6a, 0x51, 0x7c, 0xcc, 0x63, 0xe4, 0x6e, 0x9f, 0xcc, 0xe4, 0xfe, 0x3a, 0x6c},
{0xa8, 0xcf, 0xb5, 0x43, 0x52, 0x4e, 0x7f, 0x02, 0xb9, 0xf0, 0x45, 0xac, 0xd5, 0x43, 0xc2, 0x1c, 0x37, 0x3b, 0x4c, 0x9b, 0x98, 0xac, 0x20, 0xce, 0xc4, 0x17, 0xa6, 0xdd, 0xb5, 0x74, 0x4e, 0x94},
{0x93, 0x2b, 0x79, 0x4b, 0xf8, 0x9c, 0x6e, 0xda, 0xf5, 0xd0, 0x65, 0x0c, 0x7c, 0x4b, 0xad, 0x92, 0x42, 0xb2, 0x56, 0x26, 0xe3, 0x7e, 0xad, 0x5a, 0xa7, 0x5e, 0xc8, 0xc6, 0x4e, 0x09, 0xdd, 0x4f},
{0x16, 0xb1, 0x0c, 0x77, 0x9c, 0xe5, 0xcf, 0xef, 0x59, 0xc7, 0x71, 0x0d, 0x2e, 0x68, 0x44, 0x1e, 0xa6, 0xfa, 0xcb, 0x68, 0xe9, 0xb5, 0xf7, 0xd5, 0x33, 0xae, 0x0b, 0xb7, 0x8e, 0x28, 0xbf, 0x57},
{0x0f, 0x77, 0xc7, 0x67, 0x43, 0xe7, 0x39, 0x6f, 0x99, 0x10, 0x13, 0x9f, 0x49, 0x37, 0xd8, 0x37, 0xae, 0x54, 0xe2, 0x10, 0x38, 0xac, 0x5c, 0x0b, 0x3f, 0xd6, 0xef, 0x17, 0x1a, 0x28, 0xa7, 0xe4},
{0xd7, 0xe5, 0x74, 0xb7, 0xb9, 0x52, 0xf2, 0x93, 0xe8, 0x0d, 0xde, 0x90, 0x5e, 0xb5, 0x09, 0x37, 0x3f, 0x3f, 0x6c, 0xd1, 0x09, 0xa0, 0x22, 0x08, 0xb3, 0xc1, 0xe9, 0x24, 0x08, 0x0a, 0x20, 0xca},
{0x45, 0x66, 0x6f, 0x8c, 0x38, 0x1e, 0x3d, 0xa6, 0x75, 0x56, 0x3f, 0xf8, 0xba, 0x23, 0xf8, 0x3b, 0xfa, 0xc3, 0x0c, 0x34, 0xab, 0xdd, 0xe6, 0xe5, 0xc0, 0x97, 0x5e, 0xf9, 0xfd, 0x70, 0x0c, 0xb9},
{0xb2, 0x46, 0x12, 0xe4, 0x54, 0x60, 0x7e, 0xb1, 0xab, 0xa4, 0x47, 0xf8, 0x16, 0xd1, 0xa4, 0x55, 0x1e, 0xf9, 0x5f, 0xa7, 0x24, 0x7f, 0xb7, 0xc1, 0xf5, 0x03, 0x02, 0x0a, 0x71, 0x77, 0xf0, 0xdd},
{0x7e, 0x20, 0x88, 0x61, 0x85, 0x6d, 0xa4, 0x2c, 0x8b, 0xb4, 0x6a, 0x75, 0x67, 0xf8, 0x12, 0x13, 0x62, 0xd9, 0xfb, 0x24, 0x96, 0xf1, 0x31, 0xa4, 0xaa, 0x90, 0x17, 0xcf, 0x36, 0x6c, 0xdf, 0xce},
{0x5b, 0x64, 0x6b, 0xff, 0x6a, 0xd1, 0x10, 0x01, 0x65, 0x03, 0x7a, 0x05, 0x56, 0x01, 0xea, 0x02, 0x35, 0x8c, 0x0f, 0x41, 0x05, 0x0f, 0x9d, 0xfe, 0x3c, 0x95, 0xdc, 0xcb, 0xd3, 0x08, 0x7b, 0xe0},
{0x74, 0x6d, 0x1d, 0xcc, 0xfe, 0xd2, 0xf0, 0xff, 0x1e, 0x13, 0xc5, 0x1e, 0x2d, 0x50, 0xd5, 0x32, 0x43, 0x75, 0xfb, 0xd5, 0xbf, 0x7c, 0xa8, 0x2a, 0x89, 0x31, 0x82, 0x8d, 0x80, 0x1d, 0x43, 0xab},
{0xcb, 0x98, 0x11, 0x0d, 0x4a, 0x6b, 0xb9, 0x7d, 0x22, 0xfe, 0xad, 0xbc, 0x6c, 0x0d, 0x89, 0x30, 0xc5, 0xf8, 0xfc, 0x50, 0x8b, 0x2f, 0xc5, 0xb3, 0x53, 0x28, 0xd2, 0x6b, 0x88, 0xdb, 0x19, 0xae},
{0x60, 0xb6, 0x26, 0xa0, 0x33, 0xb5, 0x5f, 0x27, 0xd7, 0x67, 0x6c, 0x40, 0x95, 0xea, 0xba, 0xbc, 0x7a, 0x2c, 0x7e, 0xde, 0x26, 0x24, 0xb4, 0x72, 0xe9, 0x7f, 0x64, 0xf9, 0x6b, 0x8c, 0xfc, 0x0e},
{0xe5, 0xb5, 0x2b, 0xc9, 0x27, 0x46, 0x8d, 0xf7, 0x18, 0x93, 0xeb, 0x81, 0x97, 0xef, 0x82, 0x0c, 0xf7, 0x6c, 0xb0, 0xaa, 0xf6, 0xe8, 0xe4, 0xfe, 0x93, 0xad, 0x62, 0xd8, 0x03, 0x98, 0x31, 0x04},
{0x05, 0x65, 0x41, 0xae, 0x5d, 0xa9, 0x96, 0x1b, 0xe2, 0xb0, 0xa5, 0xe8, 0x95, 0xe5, 0xc5, 0xba, 0x15, 0x3c, 0xbb, 0x62, 0xdd, 0x56, 0x1a, 0x42, 0x7b, 0xad, 0x0f, 0xfd, 0x41, 0x92, 0x31, 0x99},
{0xf8, 0xfe, 0xf0, 0x5a, 0x3f, 0xa5, 0xc9, 0xf3, 0xeb, 0xa4, 0x16, 0x38, 0xb2, 0x47, 0xb7, 0x11, 0xa9, 0x9f, 0x96, 0x0f, 0xe7, 0x3a, 0xa2, 0xf9, 0x01, 0x36, 0xae, 0xb2, 0x03, 0x29, 0xb8, 0x88}};
static const key64 H2 = {{{0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94}},
{{0x8f, 0xaa, 0x44, 0x8a, 0xe4, 0xb3, 0xe2, 0xbb, 0x3d, 0x4d, 0x13, 0x09, 0x09, 0xf5, 0x5f, 0xcd, 0x79, 0x71, 0x1c, 0x1c, 0x83, 0xcd, 0xbc, 0xca, 0xdd, 0x42, 0xcb, 0xe1, 0x51, 0x5e, 0x87, 0x12}},
{{0x12, 0xa7, 0xd6, 0x2c, 0x77, 0x91, 0x65, 0x4a, 0x57, 0xf3, 0xe6, 0x76, 0x94, 0xed, 0x50, 0xb4, 0x9a, 0x7d, 0x9e, 0x3f, 0xc1, 0xe4, 0xc7, 0xa0, 0xbd, 0xe2, 0x9d, 0x18, 0x7e, 0x9c, 0xc7, 0x1d}},
{{0x78, 0x9a, 0xb9, 0x93, 0x4b, 0x49, 0xc4, 0xf9, 0xe6, 0x78, 0x5c, 0x6d, 0x57, 0xa4, 0x98, 0xb3, 0xea, 0xd4, 0x43, 0xf0, 0x4f, 0x13, 0xdf, 0x11, 0x0c, 0x54, 0x27, 0xb4, 0xf2, 0x14, 0xc7, 0x39}},
{{0x77, 0x1e, 0x92, 0x99, 0xd9, 0x4f, 0x02, 0xac, 0x72, 0xe3, 0x8e, 0x44, 0xde, 0x56, 0x8a, 0xc1, 0xdc, 0xb2, 0xed, 0xc6, 0xed, 0xb6, 0x1f, 0x83, 0xca, 0x41, 0x8e, 0x10, 0x77, 0xce, 0x3d, 0xe8}},
{{0x73, 0xb9, 0x6d, 0xb4, 0x30, 0x39, 0x81, 0x9b, 0xda, 0xf5, 0x68, 0x0e, 0x5c, 0x32, 0xd7, 0x41, 0x48, 0x88, 0x84, 0xd1, 0x8d, 0x93, 0x86, 0x6d, 0x40, 0x74, 0xa8, 0x49, 0x18, 0x2a, 0x8a, 0x64}},
{{0x8d, 0x45, 0x8e, 0x1c, 0x2f, 0x68, 0xeb, 0xeb, 0xcc, 0xd2, 0xfd, 0x5d, 0x37, 0x9f, 0x5e, 0x58, 0xf8, 0x13, 0x4d, 0xf3, 0xe0, 0xe8, 0x8c, 0xad, 0x3d, 0x46, 0x70, 0x10, 0x63, 0xa8, 0xd4, 0x12}},
{{0x09, 0x55, 0x1e, 0xdb, 0xe4, 0x94, 0x41, 0x8e, 0x81, 0x28, 0x44, 0x55, 0xd6, 0x4b, 0x35, 0xee, 0x8a, 0xc0, 0x93, 0x06, 0x8a, 0x5f, 0x16, 0x1f, 0xa6, 0x63, 0x75, 0x59, 0x17, 0x7e, 0xf4, 0x04}},
{{0xd0, 0x5a, 0x88, 0x66, 0xf4, 0xdf, 0x8c, 0xee, 0x1e, 0x26, 0x8b, 0x1d, 0x23, 0xa4, 0xc5, 0x8c, 0x92, 0xe7, 0x60, 0x30, 0x97, 0x86, 0xcd, 0xac, 0x0f, 0xed, 0xa1, 0xd2, 0x47, 0xa9, 0xc9, 0xa7}},
{{0x55, 0xcd, 0xaa, 0xd5, 0x18, 0xbd, 0x87, 0x1d, 0xd1, 0xeb, 0x7b, 0xc7, 0x02, 0x3e, 0x1d, 0xc0, 0xfd, 0xf3, 0x33, 0x98, 0x64, 0xf8, 0x8f, 0xdd, 0x2d, 0xe2, 0x69, 0xfe, 0x9e, 0xe1, 0x83, 0x2d}},
{{0xe7, 0x69, 0x7e, 0x95, 0x1a, 0x98, 0xcf, 0xd5, 0x71, 0x2b, 0x84, 0xbb, 0xe5, 0xf3, 0x4e, 0xd7, 0x33, 0xe9, 0x47, 0x3f, 0xcb, 0x68, 0xed, 0xa6, 0x6e, 0x37, 0x88, 0xdf, 0x19, 0x58, 0xc3, 0x06}},
{{0xf9, 0x2a, 0x97, 0x0b, 0xae, 0x72, 0x78, 0x29, 0x89, 0xbf, 0xc8, 0x3a, 0xdf, 0xaa, 0x92, 0xa4, 0xf4, 0x9c, 0x7e, 0x95, 0x91, 0x8b, 0x3b, 0xba, 0x3c, 0xdc, 0x7f, 0xe8, 0x8a, 0xcc, 0x8d, 0x47}},
{{0x1f, 0x66, 0xc2, 0xd4, 0x91, 0xd7, 0x5a, 0xf9, 0x15, 0xc8, 0xdb, 0x6a, 0x6d, 0x1c, 0xb0, 0xcd, 0x4f, 0x7d, 0xdc, 0xd5, 0xe6, 0x3d, 0x3b, 0xa9, 0xb8, 0x3c, 0x86, 0x6c, 0x39, 0xef, 0x3a, 0x2b}},
{{0x3e, 0xec, 0x98, 0x84, 0xb4, 0x3f, 0x58, 0xe9, 0x3e, 0xf8, 0xde, 0xea, 0x26, 0x00, 0x04, 0xef, 0xea, 0x2a, 0x46, 0x34, 0x4f, 0xc5, 0x96, 0x5b, 0x1a, 0x7d, 0xd5, 0xd1, 0x89, 0x97, 0xef, 0xa7}},
{{0xb2, 0x9f, 0x8f, 0x0c, 0xcb, 0x96, 0x97, 0x7f, 0xe7, 0x77, 0xd4, 0x89, 0xd6, 0xbe, 0x9e, 0x7e, 0xbc, 0x19, 0xc4, 0x09, 0xb5, 0x10, 0x35, 0x68, 0xf2, 0x77, 0x61, 0x1d, 0x7e, 0xa8, 0x48, 0x94}},
{{0x56, 0xb1, 0xf5, 0x12, 0x65, 0xb9, 0x55, 0x98, 0x76, 0xd5, 0x8d, 0x24, 0x9d, 0x0c, 0x14, 0x6d, 0x69, 0xa1, 0x03, 0x63, 0x66, 0x99, 0x87, 0x4d, 0x3f, 0x90, 0x47, 0x35, 0x50, 0xfe, 0x3f, 0x2c}},
{{0x1d, 0x7a, 0x36, 0x57, 0x5e, 0x22, 0xf5, 0xd1, 0x39, 0xff, 0x9c, 0xc5, 0x10, 0xfa, 0x13, 0x85, 0x05, 0x57, 0x6b, 0x63, 0x81, 0x5a, 0x94, 0xe4, 0xb0, 0x12, 0xbf, 0xd4, 0x57, 0xca, 0xaa, 0xda}},
{{0xd0, 0xac, 0x50, 0x7a, 0x86, 0x4e, 0xcd, 0x05, 0x93, 0xfa, 0x67, 0xbe, 0x7d, 0x23, 0x13, 0x43, 0x92, 0xd0, 0x0e, 0x40, 0x07, 0xe2, 0x53, 0x48, 0x78, 0xd9, 0xb2, 0x42, 0xe1, 0x0d, 0x76, 0x20}},
{{0xf6, 0xc6, 0x84, 0x0b, 0x9c, 0xf1, 0x45, 0xbb, 0x2d, 0xcc, 0xf8, 0x6e, 0x94, 0x0b, 0xe0, 0xfc, 0x09, 0x8e, 0x32, 0xe3, 0x10, 0x99, 0xd5, 0x6f, 0x7f, 0xe0, 0x87, 0xbd, 0x5d, 0xeb, 0x50, 0x94}},
{{0x28, 0x83, 0x1a, 0x33, 0x40, 0x07, 0x0e, 0xb1, 0xdb, 0x87, 0xc1, 0x2e, 0x05, 0x98, 0x0d, 0x5f, 0x33, 0xe9, 0xef, 0x90, 0xf8, 0x3a, 0x48, 0x17, 0xc9, 0xf4, 0xa0, 0xa3, 0x32, 0x27, 0xe1, 0x97}},
{{0x87, 0x63, 0x22, 0x73, 0xd6, 0x29, 0xcc, 0xb7, 0xe1, 0xed, 0x1a, 0x76, 0x8f, 0xa2, 0xeb, 0xd5, 0x17, 0x60, 0xf3, 0x2e, 0x1c, 0x0b, 0x86, 0x7a, 0x5d, 0x36, 0x8d, 0x52, 0x71, 0x05, 0x5c, 0x6e}},
{{0x5c, 0x7b, 0x29, 0x42, 0x43, 0x47, 0x96, 0x4d, 0x04, 0x27, 0x55, 0x17, 0xc5, 0xae, 0x14, 0xb6, 0xb5, 0xea, 0x27, 0x98, 0xb5, 0x73, 0xfc, 0x94, 0xe6, 0xe4, 0x4a, 0x53, 0x21, 0x60, 0x0c, 0xfb}},
{{0xe6, 0x94, 0x50, 0x42, 0xd7, 0x8b, 0xc2, 0xc3, 0xbd, 0x6e, 0xc5, 0x8c, 0x51, 0x1a, 0x9f, 0xe8, 0x59, 0xc0, 0xad, 0x63, 0xfd, 0xe4, 0x94, 0xf5, 0x03, 0x9e, 0x0e, 0x82, 0x32, 0x61, 0x2b, 0xd5}},
{{0x36, 0xd5, 0x69, 0x07, 0xe2, 0xec, 0x74, 0x5d, 0xb6, 0xe5, 0x4f, 0x0b, 0x2e, 0x1b, 0x23, 0x00, 0xab, 0xcb, 0x42, 0x2e, 0x71, 0x2d, 0xa5, 0x88, 0xa4, 0x0d, 0x3f, 0x1e, 0xbb, 0xbe, 0x02, 0xf6}},
{{0x34, 0xdb, 0x6e, 0xe4, 0xd0, 0x60, 0x8e, 0x5f, 0x78, 0x36, 0x50, 0x49, 0x5a, 0x3b, 0x2f, 0x52, 0x73, 0xc5, 0x13, 0x4e, 0x52, 0x84, 0xe4, 0xfd, 0xf9, 0x66, 0x27, 0xbb, 0x16, 0xe3, 0x1e, 0x6b}},
{{0x8e, 0x76, 0x59, 0xfb, 0x45, 0xa3, 0x78, 0x7d, 0x67, 0x4a, 0xe8, 0x67, 0x31, 0xfa, 0xa2, 0x53, 0x8e, 0xc0, 0xfd, 0xf4, 0x42, 0xab, 0x26, 0xe9, 0xc7, 0x91, 0xfa, 0xda, 0x08, 0x94, 0x67, 0xe9}},
{{0x30, 0x06, 0xcf, 0x19, 0x8b, 0x24, 0xf3, 0x1b, 0xb4, 0xc7, 0xe6, 0x34, 0x60, 0x00, 0xab, 0xc7, 0x01, 0xe8, 0x27, 0xcf, 0xbb, 0x5d, 0xf5, 0x2d, 0xcf, 0xa4, 0x2e, 0x9c, 0xa9, 0xff, 0x08, 0x02}},
{{0xf5, 0xfd, 0x40, 0x3c, 0xb6, 0xe8, 0xbe, 0x21, 0x47, 0x2e, 0x37, 0x7f, 0xfd, 0x80, 0x5a, 0x8c, 0x60, 0x83, 0xea, 0x48, 0x03, 0xb8, 0x48, 0x53, 0x89, 0xcc, 0x3e, 0xbc, 0x21, 0x5f, 0x00, 0x2a}},
{{0x37, 0x31, 0xb2, 0x60, 0xeb, 0x3f, 0x94, 0x82, 0xe4, 0x5f, 0x1c, 0x3f, 0x3b, 0x9d, 0xcf, 0x83, 0x4b, 0x75, 0xe6, 0xee, 0xf8, 0xc4, 0x0f, 0x46, 0x1e, 0xa2, 0x7e, 0x8b, 0x6e, 0xd9, 0x47, 0x3d}},
{{0x9f, 0x9d, 0xab, 0x09, 0xc3, 0xf5, 0xe4, 0x28, 0x55, 0xc2, 0xde, 0x97, 0x1b, 0x65, 0x93, 0x28, 0xa2, 0xdb, 0xc4, 0x54, 0x84, 0x5f, 0x39, 0x6f, 0xfc, 0x05, 0x3f, 0x0b, 0xb1, 0x92, 0xf8, 0xc3}},
{{0x5e, 0x05, 0x5d, 0x25, 0xf8, 0x5f, 0xdb, 0x98, 0xf2, 0x73, 0xe4, 0xaf, 0xe0, 0x84, 0x64, 0xc0, 0x03, 0xb7, 0x0f, 0x1e, 0xf0, 0x67, 0x7b, 0xb5, 0xe2, 0x57, 0x06, 0x40, 0x0b, 0xe6, 0x20, 0xa5}},
{{0x86, 0x8b, 0xcf, 0x36, 0x79, 0xcb, 0x6b, 0x50, 0x0b, 0x94, 0x41, 0x8c, 0x0b, 0x89, 0x25, 0xf9, 0x86, 0x55, 0x30, 0x30, 0x3a, 0xe4, 0xe4, 0xb2, 0x62, 0x59, 0x18, 0x65, 0x66, 0x6a, 0x45, 0x90}},
{{0xb3, 0xdb, 0x6b, 0xd3, 0x89, 0x7a, 0xfb, 0xd1, 0xdf, 0x3f, 0x96, 0x44, 0xab, 0x21, 0xc8, 0x05, 0x0e, 0x1f, 0x00, 0x38, 0xa5, 0x2f, 0x7c, 0xa9, 0x5a, 0xc0, 0xc3, 0xde, 0x75, 0x58, 0xcb, 0x7a}},
{{0x81, 0x19, 0xb3, 0xa0, 0x59, 0xff, 0x2c, 0xac, 0x48, 0x3e, 0x69, 0xbc, 0xd4, 0x1d, 0x6d, 0x27, 0x14, 0x94, 0x47, 0x91, 0x42, 0x88, 0xbb, 0xea, 0xee, 0x34, 0x13, 0xe6, 0xdc, 0xc6, 0xd1, 0xeb}},
{{0x10, 0xfc, 0x58, 0xf3, 0x5f, 0xc7, 0xfe, 0x7a, 0xe8, 0x75, 0x52, 0x4b, 0xb5, 0x85, 0x00, 0x03, 0x00, 0x5b, 0x7f, 0x97, 0x8c, 0x0c, 0x65, 0xe2, 0xa9, 0x65, 0x46, 0x4b, 0x6d, 0x00, 0x81, 0x9c}},
{{0x5a, 0xcd, 0x94, 0xeb, 0x3c, 0x57, 0x83, 0x79, 0xc1, 0xea, 0x58, 0xa3, 0x43, 0xec, 0x4f, 0xcf, 0xf9, 0x62, 0x77, 0x6f, 0xe3, 0x55, 0x21, 0xe4, 0x75, 0xa0, 0xe0, 0x6d, 0x88, 0x7b, 0x2d, 0xb9}},
{{0x33, 0xda, 0xf3, 0xa2, 0x14, 0xd6, 0xe0, 0xd4, 0x2d, 0x23, 0x00, 0xa7, 0xb4, 0x4b, 0x39, 0x29, 0x0d, 0xb8, 0x98, 0x9b, 0x42, 0x79, 0x74, 0xcd, 0x86, 0x5d, 0xb0, 0x11, 0x05, 0x5a, 0x29, 0x01}},
{{0xcf, 0xc6, 0x57, 0x2f, 0x29, 0xaf, 0xd1, 0x64, 0xa4, 0x94, 0xe6, 0x4e, 0x6f, 0x1a, 0xeb, 0x82, 0x0c, 0x3e, 0x7d, 0xa3, 0x55, 0x14, 0x4e, 0x51, 0x24, 0xa3, 0x91, 0xd0, 0x6e, 0x9f, 0x95, 0xea}},
{{0xd5, 0x31, 0x2a, 0x4b, 0x0e, 0xf6, 0x15, 0xa3, 0x31, 0xf6, 0x35, 0x2c, 0x2e, 0xd2, 0x1d, 0xac, 0x9e, 0x7c, 0x36, 0x39, 0x8b, 0x93, 0x9a, 0xec, 0x90, 0x1c, 0x25, 0x7f, 0x6c, 0xbc, 0x9e, 0x8e}},
{{0x55, 0x1d, 0x67, 0xfe, 0xfc, 0x7b, 0x5b, 0x9f, 0x9f, 0xdb, 0xf6, 0xaf, 0x57, 0xc9, 0x6c, 0x8a, 0x74, 0xd7, 0xe4, 0x5a, 0x00, 0x20, 0x78, 0xa7, 0xb5, 0xba, 0x45, 0xc6, 0xfd, 0xe9, 0x3e, 0x33}},
{{0xd5, 0x0a, 0xc7, 0xbd, 0x5c, 0xa5, 0x93, 0xc6, 0x56, 0x92, 0x8f, 0x38, 0x42, 0x80, 0x17, 0xfc, 0x7b, 0xa5, 0x02, 0x85, 0x4c, 0x43, 0xd8, 0x41, 0x49, 0x50, 0xe9, 0x6e, 0xcb, 0x40, 0x5d, 0xc3}},
{{0x07, 0x73, 0xe1, 0x8e, 0xa1, 0xbe, 0x44, 0xfe, 0x1a, 0x97, 0xe2, 0x39, 0x57, 0x3c, 0xfa, 0xe3, 0xe4, 0xe9, 0x5e, 0xf9, 0xaa, 0x9f, 0xaa, 0xbe, 0xac, 0x12, 0x74, 0xd3, 0xad, 0x26, 0x16, 0x04}},
{{0xe9, 0xaf, 0x0e, 0x7c, 0xa8, 0x93, 0x30, 0xd2, 0xb8, 0x61, 0x5d, 0x1b, 0x41, 0x37, 0xca, 0x61, 0x7e, 0x21, 0x29, 0x7f, 0x2f, 0x0d, 0xed, 0x8e, 0x31, 0xb7, 0xd2, 0xea, 0xd8, 0x71, 0x46, 0x60}},
{{0x7b, 0x12, 0x45, 0x83, 0x09, 0x7f, 0x10, 0x29, 0xa0, 0xc7, 0x41, 0x91, 0xfe, 0x73, 0x78, 0xc9, 0x10, 0x5a, 0xcc, 0x70, 0x66, 0x95, 0xed, 0x14, 0x93, 0xbb, 0x76, 0x03, 0x42, 0x26, 0xa5, 0x7b}},
{{0xec, 0x40, 0x05, 0x7b, 0x99, 0x54, 0x76, 0x65, 0x0b, 0x3d, 0xb9, 0x8e, 0x9d, 0xb7, 0x57, 0x38, 0xa8, 0xcd, 0x2f, 0x94, 0xd8, 0x63, 0xb9, 0x06, 0x15, 0x0c, 0x56, 0xaa, 0xc1, 0x9c, 0xaa, 0x6b}},
{{0x01, 0xd9, 0xff, 0x72, 0x9e, 0xfd, 0x39, 0xd8, 0x37, 0x84, 0xc0, 0xfe, 0x59, 0xc4, 0xae, 0x81, 0xa6, 0x70, 0x34, 0xcb, 0x53, 0xc9, 0x43, 0xfb, 0x81, 0x8b, 0x9d, 0x8a, 0xe7, 0xfc, 0x33, 0xe5}},
{{0x00, 0xdf, 0xb3, 0xc6, 0x96, 0x32, 0x8c, 0x76, 0x42, 0x45, 0x19, 0xa7, 0xbe, 0xfe, 0x8e, 0x0f, 0x6c, 0x76, 0xf9, 0x47, 0xb5, 0x27, 0x67, 0x91, 0x6d, 0x24, 0x82, 0x3f, 0x73, 0x5b, 0xaf, 0x2e}},
{{0x46, 0x1b, 0x79, 0x9b, 0x4d, 0x9c, 0xee, 0xa8, 0xd5, 0x80, 0xdc, 0xb7, 0x6d, 0x11, 0x15, 0x0d, 0x53, 0x5e, 0x16, 0x39, 0xd1, 0x60, 0x03, 0xc3, 0xfb, 0x7e, 0x9d, 0x1f, 0xd1, 0x30, 0x83, 0xa8}},
{{0xee, 0x03, 0x03, 0x94, 0x79, 0xe5, 0x22, 0x8f, 0xdc, 0x55, 0x1c, 0xbd, 0xe7, 0x07, 0x9d, 0x34, 0x12, 0xea, 0x18, 0x6a, 0x51, 0x7c, 0xcc, 0x63, 0xe4, 0x6e, 0x9f, 0xcc, 0xe4, 0xfe, 0x3a, 0x6c}},
{{0xa8, 0xcf, 0xb5, 0x43, 0x52, 0x4e, 0x7f, 0x02, 0xb9, 0xf0, 0x45, 0xac, 0xd5, 0x43, 0xc2, 0x1c, 0x37, 0x3b, 0x4c, 0x9b, 0x98, 0xac, 0x20, 0xce, 0xc4, 0x17, 0xa6, 0xdd, 0xb5, 0x74, 0x4e, 0x94}},
{{0x93, 0x2b, 0x79, 0x4b, 0xf8, 0x9c, 0x6e, 0xda, 0xf5, 0xd0, 0x65, 0x0c, 0x7c, 0x4b, 0xad, 0x92, 0x42, 0xb2, 0x56, 0x26, 0xe3, 0x7e, 0xad, 0x5a, 0xa7, 0x5e, 0xc8, 0xc6, 0x4e, 0x09, 0xdd, 0x4f}},
{{0x16, 0xb1, 0x0c, 0x77, 0x9c, 0xe5, 0xcf, 0xef, 0x59, 0xc7, 0x71, 0x0d, 0x2e, 0x68, 0x44, 0x1e, 0xa6, 0xfa, 0xcb, 0x68, 0xe9, 0xb5, 0xf7, 0xd5, 0x33, 0xae, 0x0b, 0xb7, 0x8e, 0x28, 0xbf, 0x57}},
{{0x0f, 0x77, 0xc7, 0x67, 0x43, 0xe7, 0x39, 0x6f, 0x99, 0x10, 0x13, 0x9f, 0x49, 0x37, 0xd8, 0x37, 0xae, 0x54, 0xe2, 0x10, 0x38, 0xac, 0x5c, 0x0b, 0x3f, 0xd6, 0xef, 0x17, 0x1a, 0x28, 0xa7, 0xe4}},
{{0xd7, 0xe5, 0x74, 0xb7, 0xb9, 0x52, 0xf2, 0x93, 0xe8, 0x0d, 0xde, 0x90, 0x5e, 0xb5, 0x09, 0x37, 0x3f, 0x3f, 0x6c, 0xd1, 0x09, 0xa0, 0x22, 0x08, 0xb3, 0xc1, 0xe9, 0x24, 0x08, 0x0a, 0x20, 0xca}},
{{0x45, 0x66, 0x6f, 0x8c, 0x38, 0x1e, 0x3d, 0xa6, 0x75, 0x56, 0x3f, 0xf8, 0xba, 0x23, 0xf8, 0x3b, 0xfa, 0xc3, 0x0c, 0x34, 0xab, 0xdd, 0xe6, 0xe5, 0xc0, 0x97, 0x5e, 0xf9, 0xfd, 0x70, 0x0c, 0xb9}},
{{0xb2, 0x46, 0x12, 0xe4, 0x54, 0x60, 0x7e, 0xb1, 0xab, 0xa4, 0x47, 0xf8, 0x16, 0xd1, 0xa4, 0x55, 0x1e, 0xf9, 0x5f, 0xa7, 0x24, 0x7f, 0xb7, 0xc1, 0xf5, 0x03, 0x02, 0x0a, 0x71, 0x77, 0xf0, 0xdd}},
{{0x7e, 0x20, 0x88, 0x61, 0x85, 0x6d, 0xa4, 0x2c, 0x8b, 0xb4, 0x6a, 0x75, 0x67, 0xf8, 0x12, 0x13, 0x62, 0xd9, 0xfb, 0x24, 0x96, 0xf1, 0x31, 0xa4, 0xaa, 0x90, 0x17, 0xcf, 0x36, 0x6c, 0xdf, 0xce}},
{{0x5b, 0x64, 0x6b, 0xff, 0x6a, 0xd1, 0x10, 0x01, 0x65, 0x03, 0x7a, 0x05, 0x56, 0x01, 0xea, 0x02, 0x35, 0x8c, 0x0f, 0x41, 0x05, 0x0f, 0x9d, 0xfe, 0x3c, 0x95, 0xdc, 0xcb, 0xd3, 0x08, 0x7b, 0xe0}},
{{0x74, 0x6d, 0x1d, 0xcc, 0xfe, 0xd2, 0xf0, 0xff, 0x1e, 0x13, 0xc5, 0x1e, 0x2d, 0x50, 0xd5, 0x32, 0x43, 0x75, 0xfb, 0xd5, 0xbf, 0x7c, 0xa8, 0x2a, 0x89, 0x31, 0x82, 0x8d, 0x80, 0x1d, 0x43, 0xab}},
{{0xcb, 0x98, 0x11, 0x0d, 0x4a, 0x6b, 0xb9, 0x7d, 0x22, 0xfe, 0xad, 0xbc, 0x6c, 0x0d, 0x89, 0x30, 0xc5, 0xf8, 0xfc, 0x50, 0x8b, 0x2f, 0xc5, 0xb3, 0x53, 0x28, 0xd2, 0x6b, 0x88, 0xdb, 0x19, 0xae}},
{{0x60, 0xb6, 0x26, 0xa0, 0x33, 0xb5, 0x5f, 0x27, 0xd7, 0x67, 0x6c, 0x40, 0x95, 0xea, 0xba, 0xbc, 0x7a, 0x2c, 0x7e, 0xde, 0x26, 0x24, 0xb4, 0x72, 0xe9, 0x7f, 0x64, 0xf9, 0x6b, 0x8c, 0xfc, 0x0e}},
{{0xe5, 0xb5, 0x2b, 0xc9, 0x27, 0x46, 0x8d, 0xf7, 0x18, 0x93, 0xeb, 0x81, 0x97, 0xef, 0x82, 0x0c, 0xf7, 0x6c, 0xb0, 0xaa, 0xf6, 0xe8, 0xe4, 0xfe, 0x93, 0xad, 0x62, 0xd8, 0x03, 0x98, 0x31, 0x04}},
{{0x05, 0x65, 0x41, 0xae, 0x5d, 0xa9, 0x96, 0x1b, 0xe2, 0xb0, 0xa5, 0xe8, 0x95, 0xe5, 0xc5, 0xba, 0x15, 0x3c, 0xbb, 0x62, 0xdd, 0x56, 0x1a, 0x42, 0x7b, 0xad, 0x0f, 0xfd, 0x41, 0x92, 0x31, 0x99}},
{{0xf8, 0xfe, 0xf0, 0x5a, 0x3f, 0xa5, 0xc9, 0xf3, 0xeb, 0xa4, 0x16, 0x38, 0xb2, 0x47, 0xb7, 0x11, 0xa9, 0x9f, 0x96, 0x0f, 0xe7, 0x3a, 0xa2, 0xf9, 0x01, 0x36, 0xae, 0xb2, 0x03, 0x29, 0xb8, 0x88}}};
//Debug printing for the above types
//Actually use DP(value) and #define DBG
@@ -423,33 +647,46 @@ namespace rct {
//int[64] to uint long long
xmr_amount b2d(bits amountb);
static inline const rct::key pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; }
static inline const rct::key sk2rct(const crypto::secret_key &sk) { return (const rct::key&)sk; }
static inline const rct::key ki2rct(const crypto::key_image &ki) { return (const rct::key&)ki; }
static inline const rct::key hash2rct(const crypto::hash &h) { return (const rct::key&)h; }
static inline const crypto::public_key rct2pk(const rct::key &k) { return (const crypto::public_key&)k; }
static inline const crypto::secret_key rct2sk(const rct::key &k) { return (const crypto::secret_key&)k; }
static inline const crypto::key_image rct2ki(const rct::key &k) { return (const crypto::key_image&)k; }
static inline const crypto::hash rct2hash(const rct::key &k) { return (const crypto::hash&)k; }
static inline bool operator==(const rct::key &k0, const crypto::public_key &k1) { return !memcmp(&k0, &k1, 32); }
static inline bool operator!=(const rct::key &k0, const crypto::public_key &k1) { return memcmp(&k0, &k1, 32); }
bool is_rct_simple(int type);
bool is_rct_bulletproof(int type);
bool is_rct_borromean(int type);
static inline const rct::key &pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; }
static inline const rct::key &sk2rct(const crypto::secret_key &sk) { return (const rct::key&)sk; }
static inline const rct::key &ki2rct(const crypto::key_image &ki) { return (const rct::key&)ki; }
static inline const rct::key &hash2rct(const crypto::hash &h) { return (const rct::key&)h; }
static inline const crypto::public_key &rct2pk(const rct::key &k) { return (const crypto::public_key&)k; }
static inline const crypto::secret_key &rct2sk(const rct::key &k) { return (const crypto::secret_key&)k; }
static inline const crypto::key_image &rct2ki(const rct::key &k) { return (const crypto::key_image&)k; }
static inline const crypto::hash &rct2hash(const rct::key &k) { return (const crypto::hash&)k; }
static inline bool operator==(const rct::key &k0, const crypto::public_key &k1) { return !crypto_verify_32(k0.bytes, (const unsigned char*)&k1); }
static inline bool operator!=(const rct::key &k0, const crypto::public_key &k1) { return crypto_verify_32(k0.bytes, (const unsigned char*)&k1); }
}
namespace cryptonote {
static inline bool operator==(const crypto::public_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); }
static inline bool operator!=(const crypto::public_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); }
static inline bool operator==(const crypto::secret_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); }
static inline bool operator!=(const crypto::secret_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); }
static inline bool operator==(const crypto::public_key &k0, const rct::key &k1) { return !crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
static inline bool operator!=(const crypto::public_key &k0, const rct::key &k1) { return crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
static inline bool operator==(const crypto::secret_key &k0, const rct::key &k1) { return !crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
static inline bool operator!=(const crypto::secret_key &k0, const rct::key &k1) { return crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
}
template<typename T> std::ostream &print256(std::ostream &o, const T &v);
inline std::ostream &operator <<(std::ostream &o, const rct::key &v) { return print256(o, v); }
namespace rct {
inline std::ostream &operator <<(std::ostream &o, const rct::key &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
}
}
namespace std
{
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return reinterpret_cast<const std::size_t&>(k); } };
}
BLOB_SERIALIZER(rct::key);
BLOB_SERIALIZER(rct::key64);
BLOB_SERIALIZER(rct::ctkey);
BLOB_SERIALIZER(rct::multisig_kLRki);
BLOB_SERIALIZER(rct::boroSig);
VARIANT_TAG(debug_archive, rct::key, "rct::key");
@@ -464,6 +701,10 @@ VARIANT_TAG(debug_archive, rct::mgSig, "rct::mgSig");
VARIANT_TAG(debug_archive, rct::rangeSig, "rct::rangeSig");
VARIANT_TAG(debug_archive, rct::boroSig, "rct::boroSig");
VARIANT_TAG(debug_archive, rct::rctSig, "rct::rctSig");
VARIANT_TAG(debug_archive, rct::Bulletproof, "rct::bulletproof");
VARIANT_TAG(debug_archive, rct::multisig_kLRki, "rct::multisig_kLRki");
VARIANT_TAG(debug_archive, rct::multisig_out, "rct::multisig_out");
VARIANT_TAG(debug_archive, rct::clsag, "rct::clsag");
VARIANT_TAG(binary_archive, rct::key, 0x90);
VARIANT_TAG(binary_archive, rct::key64, 0x91);
@@ -477,6 +718,10 @@ VARIANT_TAG(binary_archive, rct::mgSig, 0x98);
VARIANT_TAG(binary_archive, rct::rangeSig, 0x99);
VARIANT_TAG(binary_archive, rct::boroSig, 0x9a);
VARIANT_TAG(binary_archive, rct::rctSig, 0x9b);
VARIANT_TAG(binary_archive, rct::Bulletproof, 0x9c);
VARIANT_TAG(binary_archive, rct::multisig_kLRki, 0x9d);
VARIANT_TAG(binary_archive, rct::multisig_out, 0x9e);
VARIANT_TAG(binary_archive, rct::clsag, 0x9f);
VARIANT_TAG(json_archive, rct::key, "rct_key");
VARIANT_TAG(json_archive, rct::key64, "rct_key64");
@@ -490,5 +735,9 @@ VARIANT_TAG(json_archive, rct::mgSig, "rct_mgSig");
VARIANT_TAG(json_archive, rct::rangeSig, "rct_rangeSig");
VARIANT_TAG(json_archive, rct::boroSig, "rct_boroSig");
VARIANT_TAG(json_archive, rct::rctSig, "rct_rctSig");
VARIANT_TAG(json_archive, rct::Bulletproof, "rct_bulletproof");
VARIANT_TAG(json_archive, rct::multisig_kLRki, "rct_multisig_kLR");
VARIANT_TAG(json_archive, rct::multisig_out, "rct_multisig_out");
VARIANT_TAG(json_archive, rct::clsag, "rct_clsag");
#endif /* RCTTYPES_H */
+2
View File
@@ -55,6 +55,7 @@ BLOB_SERIALIZER(crypto::chacha8_iv);
BLOB_SERIALIZER(crypto::hash);
BLOB_SERIALIZER(crypto::cycle);
BLOB_SERIALIZER(crypto::cycle40);
BLOB_SERIALIZER(crypto::cycle48);
BLOB_SERIALIZER(crypto::hash8);
BLOB_SERIALIZER(crypto::public_key);
BLOB_SERIALIZER(crypto::secret_key);
@@ -63,6 +64,7 @@ BLOB_SERIALIZER(crypto::key_image);
BLOB_SERIALIZER(crypto::signature);
VARIANT_TAG(debug_archive, crypto::cycle, "cycle");
VARIANT_TAG(debug_archive, crypto::cycle40, "cycle40");
VARIANT_TAG(debug_archive, crypto::cycle48, "cycle48");
VARIANT_TAG(debug_archive, crypto::hash, "hash");
VARIANT_TAG(debug_archive, crypto::hash8, "hash8");
VARIANT_TAG(debug_archive, crypto::public_key, "public_key");