diff --git a/build_msvc/common.init.vcxproj.in b/build_msvc/common.init.vcxproj.in
index b217762294316..8f35b058f5a16 100644
--- a/build_msvc/common.init.vcxproj.in
+++ b/build_msvc/common.init.vcxproj.in
@@ -54,6 +54,7 @@
Unicode
$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
$(Platform)\$(Configuration)\$(ProjectName)\
+ 1
diff --git a/src/Makefile.am b/src/Makefile.am
index 83d4d3c969dd3..fbd188a4488f2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -198,12 +198,18 @@ BLSCT_H = \
blsct/set_mem_proof/set_mem_proof_prover.h \
blsct/set_mem_proof/set_mem_proof_setup.h \
blsct/signature.h \
+ blsct/tokens/info.h \
+ blsct/tokens/predicate.h \
+ blsct/tokens/predicate_exec.h \
+ blsct/tokens/predicate_parser.h \
+ blsct/tokens/rpc.h \
blsct/wallet/address.h \
blsct/wallet/hdchain.h \
blsct/wallet/helpers.h \
blsct/wallet/import_wallet_type.h \
blsct/wallet/keyman.h \
blsct/wallet/keyring.h \
+ blsct/wallet/rpc.h \
blsct/wallet/txfactory.h \
blsct/wallet/txfactory_base.h \
blsct/wallet/txfactory_global.h \
@@ -250,6 +256,9 @@ BLSCT_CPP = \
blsct/set_mem_proof/set_mem_proof_prover.cpp \
blsct/set_mem_proof/set_mem_proof_setup.cpp \
blsct/signature.cpp \
+ blsct/tokens/info.cpp \
+ blsct/tokens/predicate_exec.cpp \
+ blsct/tokens/predicate_parser.cpp \
blsct/wallet/address.cpp \
blsct/wallet/helpers.cpp \
blsct/wallet/keyman.cpp \
@@ -568,6 +577,9 @@ libbitcoin_node_a_SOURCES = \
blsct/set_mem_proof/set_mem_proof.cpp \
blsct/set_mem_proof/set_mem_proof_setup.cpp \
blsct/set_mem_proof/set_mem_proof_prover.cpp \
+ blsct/tokens/info.cpp \
+ blsct/tokens/rpc.cpp \
+ blsct/wallet/rpc.cpp \
blsct/wallet/verification.cpp \
blsct/signature.cpp \
chain.cpp \
@@ -725,6 +737,7 @@ libbitcoin_wallet_a_SOURCES = \
blsct/wallet/helpers.cpp \
blsct/wallet/keyman.cpp \
blsct/wallet/keyring.cpp \
+ blsct/wallet/rpc.cpp \
blsct/wallet/txfactory.cpp \
blsct/wallet/txfactory_base.cpp \
blsct/wallet/txfactory_global.cpp \
@@ -877,13 +890,15 @@ libbitcoin_consensus_a_SOURCES = \
blsct/range_proof/bulletproofs/range_proof.cpp \
blsct/range_proof/bulletproofs/range_proof_logic.cpp \
blsct/range_proof/bulletproofs/range_proof_with_transcript.cpp \
+ blsct/range_proof/bulletproofs_plus/amount_recovery_result.cpp \
+ blsct/range_proof/bulletproofs_plus/amount_recovery_request.cpp \
blsct/range_proof/bulletproofs_plus/range_proof.cpp \
+ blsct/range_proof/bulletproofs_plus/range_proof_logic.cpp \
+ blsct/range_proof/bulletproofs_plus/range_proof_with_transcript.cpp \
blsct/range_proof/common.cpp \
blsct/range_proof/generators.cpp \
blsct/range_proof/proof_base.cpp \
blsct/range_proof/msg_amt_cipher.cpp \
- blsct/range_proof/bulletproofs/range_proof.cpp \
- blsct/range_proof/bulletproofs_plus/range_proof.cpp \
blsct/range_proof/bulletproofs_plus/util.cpp \
blsct/set_mem_proof/set_mem_proof.cpp \
blsct/set_mem_proof/set_mem_proof_setup.cpp \
@@ -966,6 +981,8 @@ libbitcoin_common_a_SOURCES = \
blsct/set_mem_proof/set_mem_proof_prover.cpp \
blsct/set_mem_proof/set_mem_proof_setup.cpp \
blsct/signature.cpp \
+ blsct/tokens/predicate_exec.cpp \
+ blsct/tokens/predicate_parser.cpp \
blsct/wallet/address.cpp \
blsct/wallet/txfactory_global.cpp \
chainparams.cpp \
@@ -1295,6 +1312,8 @@ libnaviokernel_la_SOURCES = \
blsct/set_mem_proof/set_mem_proof_prover.cpp \
blsct/set_mem_proof/set_mem_proof_setup.cpp \
blsct/signature.cpp \
+ blsct/tokens/predicate_exec.cpp \
+ blsct/tokens/predicate_parser.cpp \
blsct/wallet/txfactory_global.cpp \
blsct/wallet/verification.cpp \
chain.cpp \
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index ba3217d1ced53..e58b8410a1b40 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -54,6 +54,7 @@ libtest_util_a_SOURCES = \
blsct/public_key.cpp \
blsct/public_keys.cpp \
blsct/signature.cpp \
+ blsct/wallet/rpc.cpp \
blsct/wallet/txfactory_global.cpp \
test/util/blockfilter.cpp \
test/util/coins.cpp \
diff --git a/src/blsct/arith/mcl/mcl_g1point.cpp b/src/blsct/arith/mcl/mcl_g1point.cpp
index 6d5d1f167973d..1c4c968ebe46f 100644
--- a/src/blsct/arith/mcl/mcl_g1point.cpp
+++ b/src/blsct/arith/mcl/mcl_g1point.cpp
@@ -170,6 +170,8 @@ bool MclG1Point::IsValid() const
bool MclG1Point::IsZero() const
{
+ MclG1Point zero;
+ if (std::memcmp(&m_point, &zero.m_point, sizeof(MclG1Point::Underlying)) == 0) return true;
return mclBnG1_isZero(&m_point);
}
diff --git a/src/blsct/common.h b/src/blsct/common.h
index b688b481b8187..91d45e2c6ddc4 100644
--- a/src/blsct/common.h
+++ b/src/blsct/common.h
@@ -25,6 +25,15 @@ class Common
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0', '0', '0'};
+ inline static const std::vector BLSCTFEE = {
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ 'B', 'L', 'S', 'C', 'T', 'F', 'E', 'E', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0', '0', '0', '0'};
+
static std::vector DataStreamToVector(const DataStream& st);
/**
diff --git a/src/blsct/eip_2333/bls12_381_keygen.cpp b/src/blsct/eip_2333/bls12_381_keygen.cpp
index dc0220ceab594..3c2de3ff2cbc4 100644
--- a/src/blsct/eip_2333/bls12_381_keygen.cpp
+++ b/src/blsct/eip_2333/bls12_381_keygen.cpp
@@ -183,3 +183,19 @@ MclScalar BLS12_381_KeyGen::derive_child_SK(const MclScalar& parent_SK, const ui
auto SK = HKDF_mod_r(std::vector(comp_PK.cbegin(), comp_PK.cend()));
return SK;
}
+
+MclScalar BLS12_381_KeyGen::derive_child_SK_hash(const MclScalar& parent_SK, const uint256& hash)
+{
+ auto ret = parent_SK;
+ for (auto i = 0; i < 8; i++) {
+ const uint8_t* pos = hash.begin() + i * 4;
+ uint32_t index = (static_cast(pos[0]) << 24) |
+ (static_cast(pos[1]) << 16) |
+ (static_cast(pos[2]) << 8) |
+ (static_cast(pos[3]));
+
+ auto comp_PK = parent_SK_to_lamport_PK(ret, index);
+ ret = HKDF_mod_r(std::vector(comp_PK.cbegin(), comp_PK.cend()));
+ }
+ return ret;
+}
diff --git a/src/blsct/eip_2333/bls12_381_keygen.h b/src/blsct/eip_2333/bls12_381_keygen.h
index 4b592511f9420..8e583a9a9f22f 100644
--- a/src/blsct/eip_2333/bls12_381_keygen.h
+++ b/src/blsct/eip_2333/bls12_381_keygen.h
@@ -20,6 +20,7 @@ class BLS12_381_KeyGen
public:
static MclScalar derive_master_SK(const std::vector& seed);
static MclScalar derive_child_SK(const MclScalar& parent_SK, const uint32_t& index);
+ static MclScalar derive_child_SK_hash(const MclScalar& parent_SK, const uint256& hash);
#ifndef BOOST_UNIT_TEST
private:
@@ -27,20 +28,20 @@ class BLS12_381_KeyGen
inline static const uint32_t DigestSize = CSHA256::OUTPUT_SIZE;
inline static const uint32_t NumLamportChunks = 255;
- using LamportChunks = std::array,NumLamportChunks>;
+ using LamportChunks = std::array, NumLamportChunks>;
- static std::array HKDF_Extract(const std::vector& salt, const std::vector& IKM);
+ static std::array HKDF_Extract(const std::vector& salt, const std::vector& IKM);
template
- static std::array HKDF_Expand(const std::array& PRK, const std::vector& info);
+ static std::array HKDF_Expand(const std::array& PRK, const std::vector& info);
static std::vector I2OSP(const MclScalar& x, const size_t& xLen);
- static MclScalar OS2IP(const std::array& X);
+ static MclScalar OS2IP(const std::array& X);
static std::vector flip_bits(const std::vector& vec);
- static LamportChunks bytes_split(const std::array& octet_string);
+ static LamportChunks bytes_split(const std::array& octet_string);
static MclScalar HKDF_mod_r(const std::vector& IKM);
static LamportChunks IKM_to_lamport_SK(const std::vector& IKM, const std::vector& salt);
- static std::array parent_SK_to_lamport_PK(const MclScalar& parent_SK, const uint32_t& index);
+ static std::array parent_SK_to_lamport_PK(const MclScalar& parent_SK, const uint32_t& index);
};
#endif // NAVIO_BLSCT_EIP_2333_BLS12_381_KEYGEN_H
diff --git a/src/blsct/external_api/blsct.cpp b/src/blsct/external_api/blsct.cpp
index ab08097571d0f..b1ac51376d938 100644
--- a/src/blsct/external_api/blsct.cpp
+++ b/src/blsct/external_api/blsct.cpp
@@ -881,51 +881,58 @@ const BlsctPoint* get_tx_out_range_proof_A(const CTxOut* tx_out) {
return copy;
}
-const BlsctPoint* get_tx_out_range_proof_S(const CTxOut* tx_out) {
+const BlsctPoint* get_tx_out_range_proof_A_wip(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(POINT_SIZE));
- auto org = tx_out->blsctData.rangeProof.S.GetVch();
+ auto org = tx_out->blsctData.rangeProof.A_wip.GetVch();
std::memcpy(copy, &org[0], POINT_SIZE);
return copy;
}
-const BlsctPoint* get_tx_out_range_proof_T1(const CTxOut* tx_out) {
+const BlsctPoint* get_tx_out_range_proof_B(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(POINT_SIZE));
- auto org = tx_out->blsctData.rangeProof.T1.GetVch();
+ auto org = tx_out->blsctData.rangeProof.B.GetVch();
std::memcpy(copy, &org[0], POINT_SIZE);
return copy;
}
-const BlsctPoint* get_tx_out_range_proof_T2(const CTxOut* tx_out) {
- auto copy = static_cast(malloc(POINT_SIZE));
- auto org = tx_out->blsctData.rangeProof.T2.GetVch();
- std::memcpy(copy, &org[0], POINT_SIZE);
+const BlsctScalar* get_tx_out_range_proof_r_prime(const CTxOut* tx_out)
+{
+ auto copy = static_cast(malloc(SCALAR_SIZE));
+ auto org = tx_out->blsctData.rangeProof.r_prime.GetVch();
+ std::memcpy(copy, &org[0], SCALAR_SIZE);
return copy;
}
-const BlsctScalar* get_tx_out_range_proof_mu(const CTxOut* tx_out) {
+const BlsctScalar* get_tx_out_range_proof_s_prime(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(SCALAR_SIZE));
- auto org = tx_out->blsctData.rangeProof.mu.GetVch();
+ auto org = tx_out->blsctData.rangeProof.s_prime.GetVch();
std::memcpy(copy, &org[0], SCALAR_SIZE);
return copy;
}
-const BlsctScalar* get_tx_out_range_proof_a(const CTxOut* tx_out) {
+const BlsctScalar* get_tx_out_range_proof_delta_prime(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(SCALAR_SIZE));
- auto org = tx_out->blsctData.rangeProof.a.GetVch();
+ auto org = tx_out->blsctData.rangeProof.delta_prime.GetVch();
std::memcpy(copy, &org[0], SCALAR_SIZE);
return copy;
}
-const BlsctScalar* get_tx_out_range_proof_b(const CTxOut* tx_out) {
+const BlsctScalar* get_tx_out_range_proof_alpha_hat(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(SCALAR_SIZE));
- auto org = tx_out->blsctData.rangeProof.b.GetVch();
+ auto org = tx_out->blsctData.rangeProof.alpha_hat.GetVch();
std::memcpy(copy, &org[0], SCALAR_SIZE);
return copy;
}
-const BlsctScalar* get_tx_out_range_proof_t_hat(const CTxOut* tx_out) {
+const BlsctScalar* get_tx_out_range_proof_tau_x(const CTxOut* tx_out)
+{
auto copy = static_cast(malloc(SCALAR_SIZE));
- auto org = tx_out->blsctData.rangeProof.t_hat.GetVch();
+ auto org = tx_out->blsctData.rangeProof.tau_x.GetVch();
std::memcpy(copy, &org[0], SCALAR_SIZE);
return copy;
}
diff --git a/src/blsct/external_api/blsct.h b/src/blsct/external_api/blsct.h
index a418904eaccbb..f5b6881f7ade5 100644
--- a/src/blsct/external_api/blsct.h
+++ b/src/blsct/external_api/blsct.h
@@ -386,19 +386,13 @@ const BlsctPoint* get_tx_out_blinding_key(const CTxOut* tx_out);
uint16_t get_tx_out_view_tag(const CTxOut* tx_out);
const BlsctPoint* get_tx_out_range_proof_A(const CTxOut* tx_out);
-const BlsctPoint* get_tx_out_range_proof_S(const CTxOut* tx_out);
-const BlsctPoint* get_tx_out_range_proof_T1(const CTxOut* tx_out);
-const BlsctPoint* get_tx_out_range_proof_T2(const CTxOut* tx_out);
-
-const BlsctScalar* get_tx_out_range_proof_mu(const CTxOut* tx_out);
-const BlsctScalar* get_tx_out_range_proof_a(const CTxOut* tx_out);
-const BlsctScalar* get_tx_out_range_proof_b(const CTxOut* tx_out);
-const BlsctScalar* get_tx_out_range_proof_t_hat(const CTxOut* tx_out);
-
-const BlsctSignature* sign_message(
- const BlsctScalar* blsct_priv_key,
- const char* blsct_msg
-);
+const BlsctPoint* get_tx_out_range_proof_A_wip(const CTxOut* tx_out);
+const BlsctPoint* get_tx_out_range_proof_B(const CTxOut* tx_out);
+const BlsctScalar* get_tx_out_range_proof_r_prime(const CTxOut* tx_out);
+const BlsctScalar* get_tx_out_range_proof_s_prime(const CTxOut* tx_out);
+const BlsctScalar* get_tx_out_range_proof_delta_prime(const CTxOut* tx_out);
+const BlsctScalar* get_tx_out_range_proof_alpha_hat(const CTxOut* tx_out);
+const BlsctScalar* get_tx_out_range_proof_tau_x(const CTxOut* tx_out);
bool verify_msg_sig(
const BlsctPubKey* blsct_pub_key,
diff --git a/src/blsct/pos/helpers.cpp b/src/blsct/pos/helpers.cpp
index a9635fc4a5e8d..13f1b3b88c74c 100644
--- a/src/blsct/pos/helpers.cpp
+++ b/src/blsct/pos/helpers.cpp
@@ -9,11 +9,11 @@
namespace blsct {
uint256
-CalculateKernelHash(const uint32_t& prevTime, const uint64_t& stakeModifier, const MclG1Point& phi, const uint32_t& time)
+CalculateKernelHash(const uint32_t& prevTime, const uint64_t& stakeModifier, const uint32_t& time)
{
HashWriter ss{};
- ss << prevTime << stakeModifier << phi << time;
+ ss << prevTime << stakeModifier << time;
return ss.GetHash();
}
diff --git a/src/blsct/pos/helpers.h b/src/blsct/pos/helpers.h
index 92ee4146ca1ff..e248e83c09788 100644
--- a/src/blsct/pos/helpers.h
+++ b/src/blsct/pos/helpers.h
@@ -11,7 +11,7 @@
#define MODIFIER_INTERVAL_RATIO 3
namespace blsct {
-uint256 CalculateKernelHash(const uint32_t& prevTime, const uint64_t& stakeModifier, const MclG1Point& phi, const uint32_t& time);
+uint256 CalculateKernelHash(const uint32_t& prevTime, const uint64_t& stakeModifier, const uint32_t& time);
} // namespace blsct
#endif // BLSCT_POS_H
\ No newline at end of file
diff --git a/src/blsct/pos/pos.cpp b/src/blsct/pos/pos.cpp
index e61ab76a6545c..91103f08b593a 100644
--- a/src/blsct/pos/pos.cpp
+++ b/src/blsct/pos/pos.cpp
@@ -119,11 +119,11 @@ std::vector CalculateSetMemProofRandomness(const CBlockIndex* pin
blsct::Message
-CalculateSetMemProofGeneratorSeed(const CBlockIndex* pindexPrev)
+CalculateSetMemProofGeneratorSeed(const CBlockIndex* pindexPrev, const CBlock& block)
{
HashWriter ss{};
- ss << pindexPrev->nHeight << pindexPrev->nStakeModifier;
+ ss << pindexPrev->nHeight << pindexPrev->nStakeModifier << TX_NO_WITNESS(block.vtx);
auto hash = ss.GetHash();
@@ -132,6 +132,6 @@ CalculateSetMemProofGeneratorSeed(const CBlockIndex* pindexPrev)
uint256 CalculateKernelHash(const CBlockIndex* pindexPrev, const CBlock& block)
{
- return CalculateKernelHash(pindexPrev->nTime, pindexPrev->nStakeModifier, block.posProof.setMemProof.phi, block.nTime);
+ return CalculateKernelHash(pindexPrev->nTime, pindexPrev->nStakeModifier, block.nTime);
}
} // namespace blsct
\ No newline at end of file
diff --git a/src/blsct/pos/pos.h b/src/blsct/pos/pos.h
index cb692a451371a..7cf90d06a73e7 100644
--- a/src/blsct/pos/pos.h
+++ b/src/blsct/pos/pos.h
@@ -20,7 +20,7 @@ bool GetLastStakeModifier(const CBlockIndex* pindex, uint64_t& nStakeModifier, i
int64_t GetStakeModifierSelectionIntervalSection(int nSection, const Consensus::Params& params);
int64_t GetStakeModifierSelectionInterval(const Consensus::Params& params);
std::vector CalculateSetMemProofRandomness(const CBlockIndex* pindexPrev);
-blsct::Message CalculateSetMemProofGeneratorSeed(const CBlockIndex* pindexPrev);
+blsct::Message CalculateSetMemProofGeneratorSeed(const CBlockIndex* pindexPrev, const CBlock& block);
uint256 CalculateKernelHash(const CBlockIndex* pindexPrev, const CBlock& block);
} // namespace blsct
diff --git a/src/blsct/pos/proof.cpp b/src/blsct/pos/proof.cpp
index 17a44b4e7a246..d585aa493b0fa 100644
--- a/src/blsct/pos/proof.cpp
+++ b/src/blsct/pos/proof.cpp
@@ -11,8 +11,8 @@ using Point = Arith::Point;
using Scalar = Arith::Scalar;
using Points = Elements;
using Scalars = Elements;
-using RangeProof = bulletproofs::RangeProof;
-using RangeProver = bulletproofs::RangeProofLogic;
+using RangeProof = bulletproofs_plus::RangeProof;
+using RangeProver = bulletproofs_plus::RangeProofLogic;
using SetProof = SetMemProof;
using SetProver = SetMemProofProver;
@@ -35,7 +35,7 @@ ProofOfStake::ProofOfStake(const Points& staked_commitments, const Scalar& eta_f
setMemProof = SetProver::Prove(setup, staked_commitments, sigma, m, f, eta_fiat_shamir, eta_phi);
- auto kernel_hash = CalculateKernelHash(prev_time, stake_modifier, setMemProof.phi, time);
+ auto kernel_hash = CalculateKernelHash(prev_time, stake_modifier, time);
uint256 min_value = CalculateMinValue(kernel_hash, next_target);
range_proof::GammaSeed gamma_seed(Scalars({f}));
@@ -55,7 +55,7 @@ ProofOfStake::ProofOfStake(const Points& staked_commitments, const Scalar& eta_f
ProofOfStake::VerificationResult ProofOfStake::Verify(const Points& staked_commitments, const Scalar& eta_fiat_shamir, const blsct::Message& eta_phi, const uint32_t& prev_time, const uint64_t& stake_modifier, const uint32_t& time, const unsigned int& next_target) const
{
- return Verify(staked_commitments, eta_fiat_shamir, eta_phi, CalculateKernelHash(prev_time, stake_modifier, setMemProof.phi, time), next_target);
+ return Verify(staked_commitments, eta_fiat_shamir, eta_phi, CalculateKernelHash(prev_time, stake_modifier, time), next_target);
}
ProofOfStake::VerificationResult ProofOfStake::Verify(const Points& staked_commitments, const Scalar& eta_fiat_shamir, const blsct::Message& eta_phi, const uint256& kernel_hash, const unsigned int& next_target) const
@@ -106,8 +106,8 @@ bool ProofOfStake::VerifyKernelHash(const RangeProof& range_proof, const uint256
range_proof_with_value.Vs.Add(phi);
RangeProver rp;
- std::vector> proofs;
- bulletproofs::RangeProofWithSeed proof{range_proof_with_value, eta_phi, (CAmount)min_value.GetUint64(0)};
+ std::vector> proofs;
+ bulletproofs_plus::RangeProofWithSeed proof{range_proof_with_value, eta_phi, (CAmount)min_value.GetUint64(0)};
proofs.emplace_back(proof);
diff --git a/src/blsct/pos/proof.h b/src/blsct/pos/proof.h
index d6dcaeccf8f59..577b2729f2ec5 100644
--- a/src/blsct/pos/proof.h
+++ b/src/blsct/pos/proof.h
@@ -8,8 +8,8 @@
#include
#include
#include
-#include
-#include
+#include
+#include
#include
#include
#include
@@ -19,7 +19,7 @@ using Point = Arith::Point;
using Scalar = Arith::Scalar;
using Points = Elements;
using SetProof = SetMemProof;
-using RangeProof = bulletproofs::RangeProof;
+using RangeProof = bulletproofs_plus::RangeProof;
namespace blsct {
class ProofOfStake
diff --git a/src/blsct/pos/proof_logic.cpp b/src/blsct/pos/proof_logic.cpp
index 6bf41fe5116b9..4c506621719f8 100644
--- a/src/blsct/pos/proof_logic.cpp
+++ b/src/blsct/pos/proof_logic.cpp
@@ -18,7 +18,7 @@ ProofOfStake ProofOfStakeLogic::Create(const CCoinsViewCache& cache, const Scala
{
auto staked_commitments = cache.GetStakedCommitments().GetElements();
auto eta_fiat_shamir = blsct::CalculateSetMemProofRandomness(pindexPrev);
- auto eta_phi = blsct::CalculateSetMemProofGeneratorSeed(pindexPrev);
+ auto eta_phi = blsct::CalculateSetMemProofGeneratorSeed(pindexPrev, block);
auto next_target = blsct::GetNextTargetRequired(pindexPrev, &block, params);
@@ -37,7 +37,7 @@ bool ProofOfStakeLogic::Verify(const CCoinsViewCache& cache, const CBlockIndex*
}
auto eta_fiat_shamir = blsct::CalculateSetMemProofRandomness(pindexPrev);
- auto eta_phi = blsct::CalculateSetMemProofGeneratorSeed(pindexPrev);
+ auto eta_phi = blsct::CalculateSetMemProofGeneratorSeed(pindexPrev, block);
auto kernel_hash = blsct::CalculateKernelHash(pindexPrev, block);
auto next_target = blsct::GetNextTargetRequired(pindexPrev, &block, params);
diff --git a/src/blsct/private_key.cpp b/src/blsct/private_key.cpp
index 23bef42b4a160..3c2cfc9d1f916 100644
--- a/src/blsct/private_key.cpp
+++ b/src/blsct/private_key.cpp
@@ -67,6 +67,11 @@ Signature PrivateKey::SignBalance() const
return CoreSign(Common::BLSCTBALANCE);
}
+Signature PrivateKey::SignFee() const
+{
+ return CoreSign(Common::BLSCTFEE);
+}
+
Signature PrivateKey::Sign(const uint256& msg) const
{
return Sign(Message(msg.begin(), msg.end()));
diff --git a/src/blsct/private_key.h b/src/blsct/private_key.h
index 7c93b4ea1bb72..06263d933c2a2 100644
--- a/src/blsct/private_key.h
+++ b/src/blsct/private_key.h
@@ -50,6 +50,7 @@ class PrivateKey
// Basic scheme
Signature SignBalance() const;
+ Signature SignFee() const;
// Message augmentation scheme
Signature Sign(const uint256& msg) const;
diff --git a/src/blsct/public_keys.cpp b/src/blsct/public_keys.cpp
index af0d2c238956b..5be62af6405a3 100644
--- a/src/blsct/public_keys.cpp
+++ b/src/blsct/public_keys.cpp
@@ -76,7 +76,7 @@ bool PublicKeys::VerifyBatch(const std::vector& msgs, const
std::vector> aug_msgs;
auto msg = msgs.begin();
for (auto pk = m_pks.begin(), end = m_pks.end(); pk != end; ++pk, ++msg) {
- if (*msg == blsct::Common::BLSCTBALANCE && fVerifyTx) {
+ if ((*msg == blsct::Common::BLSCTBALANCE || *msg == blsct::Common::BLSCTFEE) && fVerifyTx) {
aug_msgs.push_back(*msg);
} else {
aug_msgs.push_back(pk->AugmentMessage(*msg));
diff --git a/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.cpp b/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.cpp
index 053fde9de6e57..75df597446a5f 100644
--- a/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.cpp
+++ b/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.cpp
@@ -9,13 +9,13 @@
namespace bulletproofs_plus {
template
-AmountRecoveryRequest AmountRecoveryRequest::of(RangeProof& proof, typename T::Point& nonce)
+AmountRecoveryRequest AmountRecoveryRequest::of(const RangeProofWithSeed& proof, const range_proof::GammaSeed& nonce, const size_t& id)
{
auto proof_with_transcript = RangeProofWithTranscript::Build(proof);
- AmountRecoveryRequest req {
- 1,
- proof.token_id,
+ AmountRecoveryRequest req{
+ id,
+ proof.seed,
proof_with_transcript.y,
proof_with_transcript.z,
proof.alpha_hat,
@@ -26,10 +26,10 @@ AmountRecoveryRequest AmountRecoveryRequest::of(RangeProof& proof, type
proof_with_transcript.m,
proof_with_transcript.n,
proof_with_transcript.mn,
- nonce
- };
+ nonce,
+ 0};
return req;
}
-template AmountRecoveryRequest AmountRecoveryRequest::of(RangeProof&, Mcl::Point&);
+template AmountRecoveryRequest AmountRecoveryRequest::of(const RangeProofWithSeed&, const range_proof::GammaSeed&, const size_t&);
} // namespace bulletproofs_plus
diff --git a/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.h b/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.h
index dbcab238aba8d..0f1d4afcd1d08 100644
--- a/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.h
+++ b/src/blsct/range_proof/bulletproofs_plus/amount_recovery_request.h
@@ -7,8 +7,10 @@
#include
#include
+#include
#include
+
namespace bulletproofs_plus {
template
@@ -19,7 +21,7 @@ struct AmountRecoveryRequest
using Points = Elements;
size_t id;
- TokenId token_id;
+ typename GeneratorDeriver::Seed seed;
Scalar y;
Scalar z;
Scalar alpha_hat;
@@ -30,9 +32,12 @@ struct AmountRecoveryRequest
size_t m;
size_t n;
size_t mn;
- Point nonce;
+ typename range_proof::GammaSeed nonce;
+ Scalar min_value;
- static AmountRecoveryRequest of(RangeProof& proof, Point& nonce);
+ static AmountRecoveryRequest of(const RangeProofWithSeed& proof,
+ const range_proof::GammaSeed& nonce,
+ const size_t& id = 0);
};
} // namespace bulletproofs_plus
diff --git a/src/blsct/range_proof/bulletproofs_plus/range_proof.cpp b/src/blsct/range_proof/bulletproofs_plus/range_proof.cpp
index 715535eae5f72..1ab3085a4873d 100644
--- a/src/blsct/range_proof/bulletproofs_plus/range_proof.cpp
+++ b/src/blsct/range_proof/bulletproofs_plus/range_proof.cpp
@@ -32,4 +32,23 @@ bool RangeProof::operator!=(const RangeProof& other) const
template
bool RangeProof::operator!=(const RangeProof& other) const;
+template
+bool RangeProofWithSeed::operator==(const RangeProofWithSeed& other) const
+{
+ using P = RangeProof;
+ auto this_parent = static_cast(*this);
+ auto other_parent = static_cast(other);
+
+ return this_parent == other_parent &&
+ seed == other.seed;
+}
+template bool RangeProofWithSeed::operator==(const RangeProofWithSeed& other) const;
+
+template
+bool RangeProofWithSeed::operator!=(const RangeProofWithSeed& other) const
+{
+ return !operator==(other);
+}
+template bool RangeProofWithSeed::operator!=(const RangeProofWithSeed& other) const;
+
} // namespace bulletproofs_plus
diff --git a/src/blsct/range_proof/bulletproofs_plus/range_proof.h b/src/blsct/range_proof/bulletproofs_plus/range_proof.h
index 39ff8221b46e3..df32e6d56883e 100644
--- a/src/blsct/range_proof/bulletproofs_plus/range_proof.h
+++ b/src/blsct/range_proof/bulletproofs_plus/range_proof.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -43,30 +44,80 @@ struct RangeProof: public range_proof::ProofBase {
void Serialize(Stream& s) const
{
range_proof::ProofBase::Serialize(s);
- ::Serialize(s, token_id);
- ::Serialize(s, A);
- ::Serialize(s, A_wip);
- ::Serialize(s, B);
- ::Serialize(s, r_prime);
- ::Serialize(s, s_prime);
- ::Serialize(s, delta_prime);
- ::Serialize(s, alpha_hat);
- ::Serialize(s, tau_x);
+ if (range_proof::ProofBase::Vs.Size() > 0) {
+ ::Serialize(s, A);
+ ::Serialize(s, A_wip);
+ ::Serialize(s, B);
+ ::Serialize(s, r_prime);
+ ::Serialize(s, s_prime);
+ ::Serialize(s, delta_prime);
+ ::Serialize(s, alpha_hat);
+ ::Serialize(s, tau_x);
+ }
}
template
void Unserialize(Stream& s)
{
range_proof::ProofBase::Unserialize(s);
- ::Unserialize(s, token_id);
- ::Unserialize(s, A);
- ::Unserialize(s, A_wip);
- ::Unserialize(s, B);
- ::Unserialize(s, r_prime);
- ::Unserialize(s, s_prime);
- ::Unserialize(s, delta_prime);
- ::Unserialize(s, alpha_hat);
- ::Unserialize(s, tau_x);
+ if (range_proof::ProofBase::Vs.Size() > 0) {
+ ::Unserialize(s, A);
+ ::Unserialize(s, A_wip);
+ ::Unserialize(s, B);
+ ::Unserialize(s, r_prime);
+ ::Unserialize(s, s_prime);
+ ::Unserialize(s, delta_prime);
+ ::Unserialize(s, alpha_hat);
+ ::Unserialize(s, tau_x);
+ }
+ }
+};
+
+template
+struct RangeProofWithSeed : public RangeProof {
+ RangeProofWithSeed(const RangeProof& proof, const typename GeneratorDeriver::Seed& seed, const typename T::Scalar& min_value) : RangeProof(proof), seed(seed), min_value(min_value){};
+
+ RangeProofWithSeed(const RangeProof& proof, const typename GeneratorDeriver::Seed& seed) : RangeProof(proof), seed(seed), min_value(0){};
+
+ RangeProofWithSeed(const RangeProof& proof) : RangeProof(proof), seed(TokenId()), min_value(0){};
+
+ RangeProofWithSeed(){};
+
+ bool operator==(const RangeProofWithSeed& other) const;
+ bool operator!=(const RangeProofWithSeed& other) const;
+
+ template
+ void Serialize(Stream& s) const
+ {
+ RangeProof::Serialize(s);
+ }
+
+ template
+ void Unserialize(Stream& s)
+ {
+ RangeProof::Unserialize(s);
+ }
+
+ // seed to derive generators
+ typename GeneratorDeriver::Seed seed;
+
+ // min value for proof verification
+ typename T::Scalar min_value;
+};
+
+template
+struct RangeProofWithoutVs {
+ FORMATTER_METHODS(RangeProof, obj)
+ {
+ READWRITE(Using>(obj), obj.A, obj.A_wip, obj.B, obj.r_prime, obj.s_prime, obj.delta_prime, obj.alpha_hat, obj.tau_x);
+ }
+};
+
+template
+struct RangeProofCompressedForRecovery {
+ FORMATTER_METHODS(RangeProof, obj)
+ {
+ READWRITE(Using>(obj), obj.A_wip, obj.B, obj.alpha_hat, obj.tau_x);
}
};
diff --git a/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.cpp b/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.cpp
index 91b37c52cfe17..2c2c3c364d505 100644
--- a/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.cpp
+++ b/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.cpp
@@ -6,13 +6,14 @@
#include
#include
#include
-#include
-#include
#include
+#include
+#include
#include
#include
#include
#include
+#include
#include
// Bulletproofs+ implementation based on
@@ -204,11 +205,12 @@ std::tuple<
template
RangeProof RangeProofLogic::Prove(
- Elements& vs,
- typename T::Point& nonce,
+ Elements vs,
+ const range_proof::GammaSeed& nonce,
const std::vector& message,
- const TokenId& token_id
-) {
+ const Seed& seed,
+ const typename T::Scalar& minValue)
+{
using Scalar = typename T::Scalar;
using Scalars = Elements;
@@ -218,26 +220,45 @@ RangeProof RangeProofLogic::Prove(
blsct::Common::GetFirstPowerOf2GreaterOrEqTo(vs.Size());
RangeProof proof;
- proof.token_id = token_id;
const size_t m = num_input_values_power_of_2;
const size_t n = range_proof::Setup::num_input_value_bits;
const size_t mn = m * n;
+ auto vsOriginal = vs;
+
+ // apply minValue
+ if (!minValue.IsZero()) {
+ for (size_t i = 0; i < vs.Size(); ++i) {
+ vs[i] = vs[i] - minValue;
+ }
+ }
+
// generate gammas
Scalars gammas;
- for (size_t i = 0; i < num_input_values_power_of_2; ++i) {
- auto hash = nonce.GetHashWithSalt(100 + i);
- gammas.Add(hash);
+ if (std::holds_alternative(nonce.seed)) {
+ for (size_t i = 0; i < num_input_values_power_of_2; ++i) {
+ auto hash = nonce.GetHashWithSalt(100 + i);
+ gammas.Add(hash);
+ }
+ } else if (std::holds_alternative(nonce.seed)) {
+ auto vec = std::get(nonce.seed);
+ if (vs.Size() != vec.Size()) {
+ throw std::runtime_error(strprintf("%s: size of vs does not match size of gammas", __func__));
+ }
+ for (size_t i = 0; i < vec.Size(); ++i) {
+ gammas.Add(vec[i]);
+ }
}
// make the number of input values a power of 2 w/ 0s if needed
while (vs.Size() < num_input_values_power_of_2) {
vs.Add(Scalar(0));
+ vsOriginal.Add(Scalar(0));
}
// get generators for the token_id
- range_proof::Generators gens = m_common.Gf().GetInstance(token_id);
+ range_proof::Generators gens = m_common.Gf().GetInstance(seed);
auto gs = gens.GetGiSubset(mn);
auto hs = gens.GetHiSubset(mn);
auto h = gens.H;
@@ -250,7 +271,7 @@ RangeProof RangeProofLogic::Prove(
// Calculate value commitments directly form the input values
for (size_t i = 0; i < vs.Size(); ++i) {
- auto V = (g * vs[i]) + (h * gammas[i]);
+ auto V = (g * vsOriginal[i]) + (h * gammas[i]);
proof.Vs.Add(V);
fiat_shamir << V;
}
@@ -260,7 +281,7 @@ RangeProof RangeProofLogic::Prove(
// Commitment to aL and aR (obfuscated with alpha)
Scalar nonce_alpha = nonce.GetHashWithSalt(1);
- Scalar alpha = range_proof::MsgAmtCipher::ComputeAlpha(message, vs[0], nonce_alpha);
+ Scalar alpha = range_proof::MsgAmtCipher::ComputeAlpha(message, vsOriginal[0], nonce_alpha);
Scalar tau1 = nonce.GetHashWithSalt(2);
Scalar tau2 = nonce.GetHashWithSalt(3);
@@ -371,137 +392,148 @@ RangeProof RangeProofLogic::Prove(
return proof;
}
template RangeProof RangeProofLogic::Prove(
- Elements&,
- Mcl::Point&,
+ Elements,
+ const range_proof::GammaSeed&,
const std::vector&,
- const TokenId&
-);
+ const Seed&,
+ const Mcl::Scalar&);
template
bool RangeProofLogic::VerifyProofs(
- const std::vector>& proof_transcripts,
- const size_t& max_mn
-) {
+ const std::vector>& proof_transcripts)
+{
using Scalar = typename T::Scalar;
using Scalars = Elements;
+ // Vector to hold future results from async tasks
+ std::vector> futures;
+
+ // Atomic flag to signal abort
+ std::atomic abort_flag(false);
+
+ futures.reserve(proof_transcripts.size());
+
for (const RangeProofWithTranscript& pt : proof_transcripts) {
- if (pt.proof.Ls.Size() != pt.proof.Rs.Size()) return false;
+ futures.emplace_back(std::async(std::launch::async, [this, &pt, &abort_flag]() -> bool {
+ if (abort_flag.load()) return false; // Early exit if another task has already failed
- range_proof::Generators gens = m_common.Gf().GetInstance(pt.proof.token_id);
+ if (pt.proof.Ls.Size() != pt.proof.Rs.Size()) return false;
- auto gs = gens.GetGiSubset(pt.mn);
- auto hs = gens.GetHiSubset(pt.mn);
- auto h = gens.H;
- auto g = gens.G;
+ range_proof::Generators gens = m_common.Gf().GetInstance(pt.proof.seed);
- auto [
- two_pows,
- y_asc_pows_mn,
- y_desc_pows_mn,
- z_asc_by_2_pows,
- y_to_mn_plus_1
- ] = RangeProofLogic::ComputePowers(pt.y, pt.z, pt.m, pt.n);
+ auto gs = gens.GetGiSubset(pt.mn);
+ auto hs = gens.GetHiSubset(pt.mn);
+ auto h = gens.H;
+ auto g = gens.G;
- // Compute: z^2 * 1, ..., z^2 * 2^n-1, z^4 * 1, ..., z^4 * 2^n-1, z^6 * 1, ...
- Scalars z_times_two_pows;
- {
- for (auto z_pow: z_asc_by_2_pows.m_vec) {
- for (auto two_pow: two_pows.m_vec) {
- z_times_two_pows.Add(z_pow * two_pow);
+ auto [two_pows,
+ y_asc_pows_mn,
+ y_desc_pows_mn,
+ z_asc_by_2_pows,
+ y_to_mn_plus_1] = RangeProofLogic::ComputePowers(pt.y, pt.z, pt.m, pt.n);
+
+ // Compute: z^2 * 1, ..., z^2 * 2^n-1, z^4 * 1, ..., z^4 * 2^n-1, z^6 * 1, ...
+ Scalars z_times_two_pows;
+ {
+ for (auto z_pow : z_asc_by_2_pows.m_vec) {
+ for (auto two_pow : two_pows.m_vec) {
+ z_times_two_pows.Add(z_pow * two_pow);
+ }
}
}
- }
- // Compute scalars for verification
- auto [
- e_squares,
- e_inv_squares,
- s_vec
- ] = RangeProofLogic::ComputeVeriScalars(pt.es, pt.mn);
-
- Scalars s_prime_vec = s_vec.Reverse();
- Scalar inv_final_e = pt.e_last_round.Invert();
- Scalar final_e_sq = pt.e_last_round.Square();
- Scalar inv_final_e_sq = final_e_sq.Invert();
- Scalar r_prime_inv_final_e_y = pt.proof.r_prime * inv_final_e * pt.y;
- Scalar s_prime_inv_final_e = pt.proof.s_prime * inv_final_e;
- Scalars inv_y_asc_pows_mn = Scalars::FirstNPow(pt.y.Invert(), pt.mn, 1); // skip first 1
-
- // Compute generator exponents
- Scalars gs_exp;
- {
- Scalar minus_z = pt.z.Negate();
- for (size_t i=0; i::ComputeVeriScalars(pt.es, pt.mn);
+
+ Scalars s_prime_vec = s_vec.Reverse();
+ Scalar inv_final_e = pt.e_last_round.Invert();
+ Scalar final_e_sq = pt.e_last_round.Square();
+ Scalar inv_final_e_sq = final_e_sq.Invert();
+ Scalar r_prime_inv_final_e_y = pt.proof.r_prime * inv_final_e * pt.y;
+ Scalar s_prime_inv_final_e = pt.proof.s_prime * inv_final_e;
+ Scalars inv_y_asc_pows_mn = Scalars::FirstNPow(pt.y.Invert(), pt.mn, 1); // skip first 1
+
+ // Compute generator exponents
+ Scalars gs_exp;
+ {
+ Scalar minus_z = pt.z.Negate();
+ for (size_t i = 0; i < pt.mn; ++i) {
+ Scalar s = s_vec[i];
+ Scalar inv_y_pow = inv_y_asc_pows_mn[i];
+ gs_exp.Add(minus_z + s.Negate() * inv_y_pow * r_prime_inv_final_e_y);
+ }
}
- }
- Scalars hs_exp;
- {
- Scalar neg_s_prime_inv_final_e = s_prime_inv_final_e.Negate();
- for (size_t i=0; i lp;
+ lp.Add(pt.proof.A);
+ lp.Add(pt.proof.A_wip, pt.e_last_round.Invert());
+ lp.Add(pt.proof.B, pt.e_last_round.Square().Invert());
+ lp.Add(g, g_exp);
+ lp.Add(h, h_exp);
+ lp.Add(pt.proof.Ls, static_cast(e_squares));
+ lp.Add(pt.proof.Rs, e_inv_squares);
+ lp.Add(gs, gs_exp);
+ lp.Add(hs, hs_exp);
+
+ for (size_t i = 0; i < pt.proof.Vs.Size(); ++i) {
+ lp.Add(LazyPoint(pt.proof.Vs[i] - (gens.G * pt.proof.min_value), vs_exp[i]));
+ }
+
+ if (!lp.Sum().IsZero()) {
+ abort_flag.store(true); // Signal abort if verification fails
+ return false;
}
- }
- LazyPoints lp;
- lp.Add(pt.proof.A);
- lp.Add(pt.proof.A_wip, pt.e_last_round.Invert());
- lp.Add(pt.proof.B, pt.e_last_round.Square().Invert());
- lp.Add(g, g_exp);
- lp.Add(h, h_exp);
- lp.Add(pt.proof.Ls, static_cast(e_squares));
- lp.Add(pt.proof.Rs, e_inv_squares);
- lp.Add(gs, gs_exp);
- lp.Add(hs, hs_exp);
- lp.Add(pt.proof.Vs, vs_exp);
-
- if (!lp.Sum().IsZero()) return false;
+ return true;
+ }));
+ }
+
+ // Wait for all threads to finish and collect results
+ for (auto& fut : futures) {
+ if (!fut.get()) return false;
}
return true;
}
template bool RangeProofLogic::VerifyProofs(
- const std::vector>&,
- const size_t&
+ const std::vector>&
);
template
bool RangeProofLogic::Verify(
- const std::vector>& proofs
-) {
+ const std::vector>& proofs)
+{
range_proof::Common::ValidateProofsBySizes(proofs);
std::vector> proof_transcripts;
size_t max_num_rounds = 0;
- for (const RangeProof& proof: proofs) {
+ for (const RangeProofWithSeed& proof : proofs) {
// update max # of rounds and sum of all V bits
max_num_rounds = std::max(max_num_rounds, proof.Ls.Size());
@@ -510,16 +542,12 @@ bool RangeProofLogic::Verify(
proof_transcripts.push_back(proof_transcript);
}
- const size_t max_mn = 1ull << max_num_rounds;
return VerifyProofs(
- proof_transcripts,
- max_mn
- );
+ proof_transcripts);
}
template bool RangeProofLogic::Verify(
- const std::vector>&
-);
+ const std::vector>&);
template
AmountRecoveryResult RangeProofLogic::RecoverAmounts(
@@ -532,7 +560,7 @@ AmountRecoveryResult RangeProofLogic::RecoverAmounts(
std::vector> xs;
for (const AmountRecoveryRequest& req: reqs) {
- range_proof::Generators gens = m_common.Gf().GetInstance(req.token_id);
+ range_proof::Generators gens = m_common.Gf().GetInstance(req.seed);
Point g = gens.G;
Point h = gens.H;
diff --git a/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.h b/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.h
index a45dddb68b23c..5b90388a6b4f3 100644
--- a/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.h
+++ b/src/blsct/range_proof/bulletproofs_plus/range_proof_logic.h
@@ -10,10 +10,11 @@
#include
#include
-#include
+#include
#include