Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9bc777cf7d | |||
| 66fd45fd11 | |||
| 6c09ba09fd | |||
| 90aac49c77 | |||
| e6ebe4d355 | |||
| 0e72d68d94 | |||
| 170d0c0ec9 | |||
| 5548c6de53 | |||
| 56ea8f3792 |
@@ -164,10 +164,14 @@ function update_merkle_root_hash(offset, payload, blob_in, blob_out) {
|
|||||||
getMerkleRoot(transactions).copy(blob_out, 4 + 32);
|
getMerkleRoot(transactions).copy(blob_out, 4 + 32);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.blockHashBuff = function(blobBuffer) {
|
||||||
|
return reverseBuffer(hash256(blobBuffer));
|
||||||
|
};
|
||||||
|
|
||||||
module.exports.convertRavenBlob = function(blobBuffer) {
|
module.exports.convertRavenBlob = function(blobBuffer) {
|
||||||
let header = blobBuffer.slice(0, 80);
|
let header = blobBuffer.slice(0, 80);
|
||||||
update_merkle_root_hash(80 + 8 + 32, false, blobBuffer, header);
|
update_merkle_root_hash(80 + 8 + 32, false, blobBuffer, header);
|
||||||
return reverseBuffer(hash256(header));
|
return module.exports.blockHashBuff(header);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.constructNewRavenBlob = function(blockTemplate, nonceBuff, mixhashBuff) {
|
module.exports.constructNewRavenBlob = function(blockTemplate, nonceBuff, mixhashBuff) {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cryptoforknote-util",
|
"name": "cryptoforknote-util",
|
||||||
"version": "11.0.0",
|
"version": "11.2.3",
|
||||||
"main": "cryptoforknote-util",
|
"main": "cryptoforknote-util",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "LucasJones",
|
"name": "LucasJones",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const bignum = require('bignum');
|
const bignum = require('bignum');
|
||||||
const base58 = require('base58-native');
|
const base58 = require('base58-native');
|
||||||
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
|
|
||||||
const diff1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
|
const diff1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
|
||||||
|
|
||||||
@@ -248,19 +249,38 @@ module.exports.RtmBlockTemplate = function(rpcData, poolAddress) {
|
|||||||
Buffer.from(rpcData.coinbase_payload, 'hex')
|
Buffer.from(rpcData.coinbase_payload, 'hex')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const prev_hash = reverseBuffer(Buffer.from(rpcData.previousblockhash, 'hex')).toString('hex');
|
||||||
const version = packInt32LE(rpcData.version).toString('hex');
|
const version = packInt32LE(rpcData.version).toString('hex');
|
||||||
const curtime = packUInt32LE(rpcData.curtime).toString('hex');
|
const curtime = packUInt32LE(rpcData.curtime).toString('hex');
|
||||||
let bits = Buffer.from(rpcData.bits, 'hex');
|
let bits = Buffer.from(rpcData.bits, 'hex');
|
||||||
bits.writeUInt32LE(bits.readUInt32BE());
|
bits.writeUInt32LE(bits.readUInt32BE());
|
||||||
const txn = varIntBuffer(rpcData.transactions.length + 1);
|
let txs = [];
|
||||||
|
// skip version 1 transaction because they contain some OP_RETURN(0x6A) opcode in the beginning of
|
||||||
|
// tx input scripts instead of size of script part so not sure how to parse them
|
||||||
|
// just drop them for now
|
||||||
|
// example: https://explorer.raptoreum.com/tx/1461d70fa8362b0896e2e9be6312521f2684f22c9b0f9152695f33f67d9f9d3f
|
||||||
|
rpcData.transactions.forEach(function(tx) {
|
||||||
|
if (tx.version != 1) {
|
||||||
|
try {
|
||||||
|
bitcoin.Transaction.fromBuffer(Buffer.from(tx.data, 'hex'), false, false);
|
||||||
|
} catch(err) {
|
||||||
|
console.error("Skip RTM tx due to parse error: " + tx.data);
|
||||||
|
return; // skip transaction if it is not parsed OK (varint coding seems to be different for RTM)
|
||||||
|
}
|
||||||
|
txs.push(tx);
|
||||||
|
} else {
|
||||||
|
console.error("Skip RTM v1 tx: " + tx.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const txn = varIntBuffer(txs.length + 1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
difficulty: parseFloat((diff1 / bignum(rpcData.target, 16).toNumber()).toFixed(9)),
|
difficulty: parseFloat((diff1 / bignum(rpcData.target, 16).toNumber()).toFixed(9)),
|
||||||
height: rpcData.height,
|
height: rpcData.height,
|
||||||
prev_hash: rpcData.previousblockhash,
|
prev_hash: prev_hash,
|
||||||
blocktemplate_blob: version + rpcData.previousblockhash + Buffer.alloc(32, 0).toString('hex') + curtime + bits.toString('hex') + Buffer.alloc(4, 0).toString('hex') +
|
blocktemplate_blob: version + prev_hash + Buffer.alloc(32, 0).toString('hex') + curtime + bits.toString('hex') + Buffer.alloc(4, 0).toString('hex') +
|
||||||
txn.toString('hex') + blob1.toString('hex') + Buffer.alloc(extraNoncePlaceholderLength, 0xCC).toString('hex') + blob2.toString('hex') +
|
txn.toString('hex') + blob1.toString('hex') + Buffer.alloc(extraNoncePlaceholderLength, 0xCC).toString('hex') + blob2.toString('hex') +
|
||||||
Buffer.concat(rpcData.transactions.map(function(tx) { return Buffer.from(tx.data, 'hex'); })).toString('hex'),
|
Buffer.concat(txs.map(function(tx) { return Buffer.from(tx.data, 'hex'); })).toString('hex'),
|
||||||
reserved_offset: 80 + txn.length + blob1.length
|
reserved_offset: 80 + txn.length + blob1.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define CURRENT_TRANSACTION_VERSION 1
|
#define CURRENT_TRANSACTION_VERSION 1
|
||||||
|
#define POU_TRANSACTION_VERSION 6
|
||||||
#define OFFSHORE_TRANSACTION_VERSION 3
|
#define OFFSHORE_TRANSACTION_VERSION 3
|
||||||
#define HF_VERSION_XASSET_FEES_V2 17
|
#define HF_VERSION_XASSET_FEES_V2 17
|
||||||
#define HF_VERSION_HAVEN2 18
|
#define HF_VERSION_HAVEN2 18
|
||||||
|
|
||||||
|
// UNLOCK TIMES
|
||||||
|
#define TX_V6_OFFSHORE_UNLOCK_BLOCKS 21*720 // 21 day unlock time
|
||||||
|
#define TX_V6_ONSHORE_UNLOCK_BLOCKS 360 // 12 hour unlock time
|
||||||
|
#define TX_V6_XASSET_UNLOCK_BLOCKS 1440 // 2 day unlock time
|
||||||
|
#define TX_V6_OFFSHORE_UNLOCK_BLOCKS_TESTNET 60 // 2 hour unlock time - FOR TESTING ONLY
|
||||||
|
#define TX_V6_ONSHORE_UNLOCK_BLOCKS_TESTNET 30 // 1 hour unlock time - FOR TESTING ONLY
|
||||||
|
#define TX_V6_XASSET_UNLOCK_BLOCKS_TESTNET 60 // 2 hour unlock time - FOR TESTING ONLY
|
||||||
|
|
||||||
|
#define PRICING_RECORD_VALID_TIME_DIFF_FROM_BLOCK 120 // seconds
|
||||||
|
|
||||||
enum BLOB_TYPE {
|
enum BLOB_TYPE {
|
||||||
BLOB_TYPE_CRYPTONOTE = 0,
|
BLOB_TYPE_CRYPTONOTE = 0,
|
||||||
BLOB_TYPE_FORKNOTE1 = 1,
|
BLOB_TYPE_FORKNOTE1 = 1,
|
||||||
|
|||||||
@@ -258,7 +258,8 @@ namespace cryptonote
|
|||||||
if (version == loki_version_3_per_output_unlock_times)
|
if (version == loki_version_3_per_output_unlock_times)
|
||||||
FIELD(is_deregister)
|
FIELD(is_deregister)
|
||||||
}
|
}
|
||||||
VARINT_FIELD(unlock_time)
|
if (blob_type != BLOB_TYPE_CRYPTONOTE_XHV || version < POU_TRANSACTION_VERSION)
|
||||||
|
VARINT_FIELD(unlock_time)
|
||||||
FIELD(vin)
|
FIELD(vin)
|
||||||
FIELD(vout)
|
FIELD(vout)
|
||||||
if (blob_type == BLOB_TYPE_CRYPTONOTE_LOKI || blob_type == BLOB_TYPE_CRYPTONOTE_XTNC)
|
if (blob_type == BLOB_TYPE_CRYPTONOTE_LOKI || blob_type == BLOB_TYPE_CRYPTONOTE_XTNC)
|
||||||
@@ -275,6 +276,11 @@ namespace cryptonote
|
|||||||
VARINT_FIELD(pricing_record_height)
|
VARINT_FIELD(pricing_record_height)
|
||||||
if (version < 5)
|
if (version < 5)
|
||||||
FIELD(offshore_data)
|
FIELD(offshore_data)
|
||||||
|
if (version >= POU_TRANSACTION_VERSION)
|
||||||
|
{
|
||||||
|
FIELD(output_unlock_times)
|
||||||
|
}
|
||||||
|
if (version >= POU_TRANSACTION_VERSION && vout.size() != output_unlock_times.size()) return false;
|
||||||
VARINT_FIELD(amount_burnt)
|
VARINT_FIELD(amount_burnt)
|
||||||
VARINT_FIELD(amount_minted)
|
VARINT_FIELD(amount_minted)
|
||||||
}
|
}
|
||||||
@@ -389,6 +395,7 @@ namespace cryptonote
|
|||||||
offshore_data.clear();
|
offshore_data.clear();
|
||||||
amount_burnt = 0;
|
amount_burnt = 0;
|
||||||
amount_minted = 0;
|
amount_minted = 0;
|
||||||
|
output_unlock_times.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ namespace cryptonote
|
|||||||
{
|
{
|
||||||
// This is the correct way to get the fee for Haven, because outs may be in different currencies to ins
|
// This is the correct way to get the fee for Haven, because outs may be in different currencies to ins
|
||||||
switch (tx.version) {
|
switch (tx.version) {
|
||||||
|
case 6:
|
||||||
case 5:
|
case 5:
|
||||||
fee = tx.rct_signatures.txnFee + tx.rct_signatures.txnOffshoreFee;
|
fee = tx.rct_signatures.txnFee + tx.rct_signatures.txnOffshoreFee;
|
||||||
break;
|
break;
|
||||||
@@ -282,6 +283,10 @@ namespace cryptonote
|
|||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
bool check_outs_valid(const transaction& tx)
|
bool check_outs_valid(const transaction& tx)
|
||||||
{
|
{
|
||||||
|
if (tx.blob_type == BLOB_TYPE_CRYPTONOTE_XHV && tx.version >= POU_TRANSACTION_VERSION)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(tx.vout.size() == tx.output_unlock_times.size(), false, "tx version 6+ must have equal number of output unlock times and outputs");
|
||||||
|
}
|
||||||
BOOST_FOREACH(const tx_out& out, tx.vout)
|
BOOST_FOREACH(const tx_out& out, tx.vout)
|
||||||
{
|
{
|
||||||
if (tx.blob_type != BLOB_TYPE_CRYPTONOTE_XHV) {
|
if (tx.blob_type != BLOB_TYPE_CRYPTONOTE_XHV) {
|
||||||
|
|||||||
@@ -33,10 +33,6 @@
|
|||||||
#include "storages/portable_storage.h"
|
#include "storages/portable_storage.h"
|
||||||
|
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
|
|
||||||
#define PRICING_RECORD_VALID_BLOCKS 10
|
|
||||||
#define PRICING_RECORD_VALID_TIME_DIFF_FROM_BLOCK 120 // seconds
|
|
||||||
|
|
||||||
namespace offshore
|
namespace offshore
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -262,27 +258,8 @@ namespace offshore
|
|||||||
return (*this).equal(empty_pr);
|
return (*this).equal(empty_pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pricing_record::verifySignature() const
|
bool pricing_record::verifySignature(const std::string& public_key) const
|
||||||
{
|
{
|
||||||
// Oracle public keys
|
|
||||||
std::string const mainnet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
|
||||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
|
|
||||||
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
|
|
||||||
"-----END PUBLIC KEY-----\n";
|
|
||||||
std::string const testnet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
|
||||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtWqvQh7OdXrdgXcDeBMRVfLWTW3F\n"
|
|
||||||
"wByeoVJFBfZymScJIJl46j66xG6ngnyj4ai4/QPFnSZ1I9jjMRlTWC4EPA==\n"
|
|
||||||
"-----END PUBLIC KEY-----\n";
|
|
||||||
std::string const stagenet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
|
||||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtWqvQh7OdXrdgXcDeBMRVfLWTW3F\n"
|
|
||||||
"wByeoVJFBfZymScJIJl46j66xG6ngnyj4ai4/QPFnSZ1I9jjMRlTWC4EPA==\n"
|
|
||||||
"-----END PUBLIC KEY-----\n";
|
|
||||||
|
|
||||||
// Comment out all but 1 of the following lines to select the correct Oracle PK
|
|
||||||
std::string const public_key = mainnet_public_key;
|
|
||||||
//std::string const public_key = testnet_public_key;
|
|
||||||
//std::string const public_key = stagenet_public_key;
|
|
||||||
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(!public_key.empty(), "Pricing record verification failed. NULL public key. PK Size: " << public_key.size()); // TODO: is this necessary or the one below already covers this case, meannin it will produce empty pubkey?
|
CHECK_AND_ASSERT_THROW_MES(!public_key.empty(), "Pricing record verification failed. NULL public key. PK Size: " << public_key.size()); // TODO: is this necessary or the one below already covers this case, meannin it will produce empty pubkey?
|
||||||
|
|
||||||
// extract the key
|
// extract the key
|
||||||
@@ -432,8 +409,27 @@ namespace offshore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Oracle public keys
|
||||||
|
std::string const mainnet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
||||||
|
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
|
||||||
|
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
|
||||||
|
"-----END PUBLIC KEY-----\n";
|
||||||
|
std::string const testnet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
||||||
|
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtWqvQh7OdXrdgXcDeBMRVfLWTW3F\n"
|
||||||
|
"wByeoVJFBfZymScJIJl46j66xG6ngnyj4ai4/QPFnSZ1I9jjMRlTWC4EPA==\n"
|
||||||
|
"-----END PUBLIC KEY-----\n";
|
||||||
|
std::string const stagenet_public_key = "-----BEGIN PUBLIC KEY-----\n"
|
||||||
|
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtWqvQh7OdXrdgXcDeBMRVfLWTW3F\n"
|
||||||
|
"wByeoVJFBfZymScJIJl46j66xG6ngnyj4ai4/QPFnSZ1I9jjMRlTWC4EPA==\n"
|
||||||
|
"-----END PUBLIC KEY-----\n";
|
||||||
|
|
||||||
|
// Comment out all but 1 of the following lines to select the correct Oracle PK
|
||||||
|
std::string const public_key = mainnet_public_key;
|
||||||
|
//std::string const public_key = testnet_public_key;
|
||||||
|
//std::string const public_key = stagenet_public_key;
|
||||||
|
|
||||||
// verify the signature
|
// verify the signature
|
||||||
if (!verifySignature()) {
|
if (!verifySignature(public_key)) {
|
||||||
LOG_ERROR("Invalid pricing record signature.");
|
LOG_ERROR("Invalid pricing record signature.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace offshore
|
|||||||
void set_for_height_821428();
|
void set_for_height_821428();
|
||||||
bool equal(const pricing_record& other) const noexcept;
|
bool equal(const pricing_record& other) const noexcept;
|
||||||
bool empty() const noexcept;
|
bool empty() const noexcept;
|
||||||
bool verifySignature() const;
|
bool verifySignature(const std::string& public_key) const;
|
||||||
bool valid(uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const;
|
bool valid(uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const;
|
||||||
|
|
||||||
pricing_record& operator=(const pricing_record& orig) noexcept;
|
pricing_record& operator=(const pricing_record& orig) noexcept;
|
||||||
|
|||||||
Reference in New Issue
Block a user