profile
viewpoint

JeremyRubin/BTCSpark 30

A toolkit for using apache spark to efficiently query Bitcoin Blockchain data.

JeremyRubin/Graffiti-codes 7

Graffiti Codes is a project out of the MIT Media lab for the creation of QR-like gesture codes. It is a work in progress!

JeremyRubin/judge 7

An algorithm/Library for reducing multiple judge scores into meaningful rankings for hackathons or contests.

JeremyRubin/CTVSims 5

Simulations showing CTV is kickass

JeremyRubin/bitcoin 3

Bitcoin Core integration/staging tree

JeremyRubin/Junkyard-Jumbotron 3

The Junkyard Jumbotron is a web tool that makes it really easy to combine a bunch of random displays into a single, large virtual display. It works with laptops, tablets, smartphones -- anything that can run a web browser. And the magic is that all you need to do to configure one is take a photograph of all the screens. This fork is working on video support.

JeremyRubin/BatteryBalance 2

A script to battery pack organization based on IR values.

JeremyRubin/bips 2

Bitcoin Improvement Proposals

JeremyRubin/dragonchain 2

Dragonchain blockchain platform - simplified integration of advanced blockchain features

pull request commentbitcoin-core/secp256k1

ecdsa sign-to-contract module, with anti nonce covert chan util functions

I think we can merge this into -zkp soon. I have https://github.com/ElementsProject/secp256k1-zkp/pull/111. If you do your own rebase it might be easier to start from that since I did the work of combing the new unified ecdsa/recovery code with this PR's implementation of the same thing.

benma

comment created time in an hour

pull request commentbitcoin-core/secp256k1

Safegcd inverses, drop Jacobi symbols, remove libgmp

@peterdettman Had to make these additional changes to satisfy ubsan (they were actually invoking UB, I believe):

diff --git a/src/modinv32.h b/src/modinv32.h
index 74fc3fd8..d46447b1 100644
--- a/src/modinv32.h
+++ b/src/modinv32.h
@@ -22,7 +22,7 @@ typedef struct {
     secp256k1_modinv32_signed30 modulus;
 
     /* modulus^{-1} mod 2^30 */
-    int32_t modulus_inv30;
+    uint32_t modulus_inv30;
 } secp256k1_modinv32_modinfo;
 
 static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo);
diff --git a/src/modinv32_impl.h b/src/modinv32_impl.h
index 2cd65557..a15bd2f9 100644
--- a/src/modinv32_impl.h
+++ b/src/modinv32_impl.h
@@ -201,8 +201,8 @@ static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp
      * the range (-2.P, P), consistent with the input constraint.
      */
 
-    md -= (modinfo->modulus_inv30 * (int32_t)cd + md) & M30;
-    me -= (modinfo->modulus_inv30 * (int32_t)ce + me) & M30;
+    md -= (modinfo->modulus_inv30 * (uint32_t)cd + md) & M30;
+    me -= (modinfo->modulus_inv30 * (uint32_t)ce + me) & M30;
 
     /* The modulus has to be odd, so we can assume it is nonzero. */
     cd += (int64_t)modinfo->modulus.v[0] * md;
@@ -380,8 +380,8 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256
         cond |= gn ^ (gn >> 31);
 
         if (cond == 0) {
-            f.v[len - 2] |= fn << 30;
-            g.v[len - 2] |= gn << 30;
+            f.v[len - 2] |= (uint32_t)fn << 30;
+            g.v[len - 2] |= (uint32_t)gn << 30;
             --len;
         }
     }
diff --git a/src/modinv64.h b/src/modinv64.h
index caff6f5a..6fea9651 100644
--- a/src/modinv64.h
+++ b/src/modinv64.h
@@ -26,7 +26,7 @@ typedef struct {
     secp256k1_modinv64_signed62 modulus;
 
     /* modulus^{-1} mod 2^62 */
-    int64_t modulus_inv62;
+    uint64_t modulus_inv62;
 } secp256k1_modinv64_modinfo;
 
 static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo);
diff --git a/src/modinv64_impl.h b/src/modinv64_impl.h
index ebf1fe7f..7ce6c909 100644
--- a/src/modinv64_impl.h
+++ b/src/modinv64_impl.h
@@ -177,8 +177,8 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
      * the range (-2.P, P), consistent with the input constraint.
...skipping...
index 2cd65557..a15bd2f9 100644
--- a/src/modinv32_impl.h
+++ b/src/modinv32_impl.h
@@ -201,8 +201,8 @@ static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp
      * the range (-2.P, P), consistent with the input constraint.
      */
 
-    md -= (modinfo->modulus_inv30 * (int32_t)cd + md) & M30;
-    me -= (modinfo->modulus_inv30 * (int32_t)ce + me) & M30;
+    md -= (modinfo->modulus_inv30 * (uint32_t)cd + md) & M30;
+    me -= (modinfo->modulus_inv30 * (uint32_t)ce + me) & M30;
 
     /* The modulus has to be odd, so we can assume it is nonzero. */
     cd += (int64_t)modinfo->modulus.v[0] * md;
@@ -380,8 +380,8 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256
         cond |= gn ^ (gn >> 31);
 
         if (cond == 0) {
-            f.v[len - 2] |= fn << 30;
-            g.v[len - 2] |= gn << 30;
+            f.v[len - 2] |= (uint32_t)fn << 30;
+            g.v[len - 2] |= (uint32_t)gn << 30;
             --len;
         }
     }
diff --git a/src/modinv64.h b/src/modinv64.h
index caff6f5a..6fea9651 100644
--- a/src/modinv64.h
+++ b/src/modinv64.h
@@ -26,7 +26,7 @@ typedef struct {
     secp256k1_modinv64_signed62 modulus;
 
     /* modulus^{-1} mod 2^62 */
-    int64_t modulus_inv62;
+    uint64_t modulus_inv62;
 } secp256k1_modinv64_modinfo;
 
 static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo);
diff --git a/src/modinv64_impl.h b/src/modinv64_impl.h
index ebf1fe7f..7ce6c909 100644
--- a/src/modinv64_impl.h
+++ b/src/modinv64_impl.h
@@ -177,8 +177,8 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
      * the range (-2.P, P), consistent with the input constraint.
      */
 
-    md -= (modinfo->modulus_inv62 * (int64_t)cd + md) & M62;
-    me -= (modinfo->modulus_inv62 * (int64_t)ce + me) & M62;
+    md -= (modinfo->modulus_inv62 * (uint64_t)cd + md) & M62;
+    me -= (modinfo->modulus_inv62 * (uint64_t)ce + me) & M62;
 
     /* The modulus has to be odd, so we can assume it is nonzero. */
     cd += (int128_t)modinfo->modulus.v[0] * md;
@@ -388,8 +388,8 @@ static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256
         cond |= gn ^ (gn >> 63);
 
         if (cond == 0) {
-            f.v[len - 2] |= fn << 62;
-            g.v[len - 2] |= gn << 62;
+            f.v[len - 2] |= (uint64_t)fn << 62;
+            g.v[len - 2] |= (uint64_t)gn << 62;
             --len;
         }
     }
sipa

comment created time in an hour

MemberEvent

pull request commentbitcoin/bitcoin

rpc: Add min_conf option to fund transaction calls

While looking for this functionability I found this PR, and I also had the same concerns as @gmaxwell regarding the trusted/untrusted. However could we use instead m_min_depth_mine & m_min_depth_theirs similar to

https://github.com/bitcoin/bitcoin/blob/e2ff5e7b35d71195278d2a2ed9485f141de33d7a/src/wallet/coinselection.cpp#L331-L336

and implement it at either AvailableCoins or passing it to coin_selection_params which eventually calls EligibleForSpending. This way we can set 0 || 1 for own transactions, and 3+ for untrusted txs (since node already marks eligible with 1 confirmation, but that's not enough for a third party tx)

I'm interested in submitting a PR in case the proposed resolution is correct.

promag

comment created time in 2 hours

PR closed bitcoin/bitcoin

IGNORE: Testing appveyor build time on Bitcoin Core account

Another test to see how much of an improvement can be made to the appveyor build time by tweaking the build settings and using pre-built dependencies.

+40 -47

0 comment

5 changed files

sipsorcery

pr closed time in 2 hours

Pull request review commentbitcoin/bitcoin

fuzz: Add fuzzing harness for LoadMempool(...) and DumpMempool(...)

+// Copyright (c) 2020 The Bitcoin Core developers+// Distributed under the MIT software license, see the accompanying+// file COPYING or http://www.opensource.org/licenses/mit-license.php.++#include <chainparamsbase.h>+#include <test/fuzz/FuzzedDataProvider.h>+#include <test/fuzz/fuzz.h>+#include <test/fuzz/util.h>+#include <test/util/setup_common.h>+#include <txmempool.h>+#include <validation.h>++#include <cstdint>+#include <vector>++namespace {+FuzzedFileProvider* fuzzed_file_provider_ptr = nullptr;++FILE* fuzzed_fopen(const fs::path&, const char*)+{+    return fuzzed_file_provider_ptr->open();+}+} // namespace++void initialize()+{+    static TestingSetup setup{CBaseChainParams::REGTEST, {"-nodebuglogfile"}};+}++void test_one_input(const std::vector<uint8_t>& buffer)+{+    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};+    FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);+    fuzzed_file_provider_ptr = &fuzzed_file_provider;++    CTxMemPool pool;+    (void)LoadMempool(pool, fuzzed_fopen);

Time could be mocked since in LoadMempool there is a call to GetTime.

practicalswift

comment created time in 2 hours

startedbazelbuild/rules_k8s

started time in 3 hours

startedtwitter/scoot

started time in 3 hours

startedbazelbuild/bazel-buildfarm

started time in 3 hours

startedGBKS/bitcoin-design

started time in 3 hours

pull request commentbitcoin/bitcoin

RPC/Wallet: unloadwallet: Allow specifying wallet_name param matching RPC endpoint wallet

ACK 89bdad5b25ae4ac03a486f729a5b58ae6f21946d

luke-jr

comment created time in 3 hours

startedjhuangtw/xg2xg

started time in 3 hours

pull request commentbitcoin/bitcoin

Well-defined CAddress disk serialization, and addrv2 anchors.dat

Indeed, there is probably no hurry, unless we want to support torv3 anchors in 0.21.

sipa

comment created time in 3 hours

issue commentmimblewimble/grin-wallet

List of Changes in 4.0.0

our pool (2Miners.com) is fully anonymous not having any sort of a client area or secure page where the miner could potentially grab these Slatepack Messages for a direct manual deposit

You're already maintaining some anonymous miner credentials, like an address to send mining proceeds to. By maintaining a grin wallet address for each grin miner, you can let them exchange slatepacks for payout to their claimed grin wallet in an anonymous client area. Only the true owner of the grin wallet address is able to send valid slatepacks, so no further authentication is required?!

yeastplume

comment created time in 3 hours

pull request commentbitcoin/bitcoin

Well-defined CAddress disk serialization, and addrv2 anchors.dat

Concept ACK.

From the PR description and quick code reading it follows that there is no hurry to backport these changes into 0.21, right?

sipa

comment created time in 3 hours

PR opened bitcoin/bitcoin

IGNORE: Testing appveyor build time on Bitcoin Core account

Another test to see how much of an improvement can be made to the appveyor build time by tweaking the build settings and using pre-built dependencies.

+40 -47

0 comment

5 changed files

pr created time in 3 hours

pull request commentbitcoin/bitcoin

Well-defined CAddress disk serialization, and addrv2 anchors.dat

I merged the anchors.dat addrv2 support from #20514 into this PR, as doing it correctly requires changes the Cservice serialization from stream version based to stored version based.

sipa

comment created time in 4 hours

PR closed bitcoin/bitcoin

Reviewers
Use addrv2 serialization in anchors.dat Needs backport (0.21)

This changes anchors.dat to use ADDRV2_FORMAT, so its CAddress entries can use v2 serialization.

This solves #20511, but is incompatible with #20509.

This should be compatible with (v1) addresses stored by 0.21.0rc{1,2} as well, as it uses the client version stored in the CAddress records to decide which deserializer to use.

+7 -7

12 comments

1 changed file

sipa

pr closed time in 4 hours

pull request commentbitcoin/bitcoin

Use addrv2 serialization in anchors.dat

If I'm right, then I don't think we necessarily need to fix this for 0.21. We didn't have anchor connections or torv3 before, so the fact that they don't work together isn't a regression and can always be fixed up later

That's fair, and you've shown that this PR as-is actually makes things worse, as it'll fail to deserialize the CService object.

To fix it, we'll either need @vasild's patch from https://github.com/bitcoin/bitcoin/pull/20514#issuecomment-734783860, or doing it on top of #20516. I'm going to close this PR, and take the functionality there.

sipa

comment created time in 4 hours

Pull request review commentbitcoin/bitcoin

[tests] Allow outbound & block-relay-only connections in functional tests.

 static RPCHelpMan addnode()     }; } +static RPCHelpMan addconnection()+{+    return RPCHelpMan{"addconnection",+        "\nOpen an outbound connection to a specified node. This RPC is for testing only.\n",+        {+            {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address and port to attempt connecting to."},+            {"connectiontype", RPCArg::Type::STR, RPCArg::Optional::NO, "'outbound' or 'blockrelay'."},+        },+        RPCResult{+            RPCResult::Type::OBJ, "", "",+            {+                { RPCResult::Type::STR, "address", "Address of newly added connection." },+                { RPCResult::Type::STR, "connectiontype", "Type of connection opened." },+            }},+        RPCExamples{+            HelpExampleCli("addconnection", "\"192.168.0.6:8333\" \"outbound\"")+            + HelpExampleRpc("addconnection", "\"192.168.0.6:8333\" \"outbound\"")+        },+        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue+{+    if (!Params().IsMockableChain()) {+        throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");+    }++    RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VSTR});+    const std::string address = request.params[0].get_str();+    const std::string conn_type_in = request.params[1].get_str();+    ConnectionType conn_type{};+    if (conn_type_in == "outbound") {+        conn_type = ConnectionType::OUTBOUND_FULL_RELAY;+    } else if (conn_type_in == "blockrelay") {+        conn_type = ConnectionType::BLOCK_RELAY;+    } else {+        throw std::runtime_error(self.ToString());+    }++    NodeContext& context = EnsureNodeContext(request.context);+    if (!context.connman) {+        throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled.");+    }++    const bool success = context.connman->AddConnection(address, conn_type);+    if (!success) {+        throw JSONRPCError(RPC_CLIENT_NODE_CAPACITY_REACHED, "Error: Already at capacity for specified connection type.");+    }++    UniValue info(UniValue::VOBJ);+    info.pushKV("address", address);+    info.pushKV("connectiontype", conn_type_in);+

okay, I'm going to resolve this comment. we can revisit once there are specific use cases

amitiuttarwar

comment created time in 4 hours

issue commentbitcoin/bitcoin

Strange state (Timestamps wrong) after importing a priv key.

Nov27-100942

I think I'm hitting this issue? or is this something else? I just did a rescan on latest master as of yesterday and the dates seem wrong at a certain point (after 2017). this is a descriptor wallet.

kollokollo

comment created time in 5 hours

PR opened bitcoin/bitcoin

ci, depends: Do not force Precompiled Headers (PCH) when building Qt

On CentOS 8 (Cirrus CI job) the forced '-pch' option breaks Qt build.

Removing '-pch' option does not affect build time for other systems:

  • master (e2ff5e7b35d71195278d2a2ed9485f141de33d7a):
$ time make -j 9 -C depends/ qt
...
Caching qt...
make: Leaving directory '/home/hebasto/guix/GitHub/bitcoin/depends'

real	4m22,359s
user	18m3,719s
sys     1m24,769s
  • this PR:
$ time make -j 9 -C depends/ qt
...
Caching qt...
make: Leaving directory '/home/hebasto/guix/GitHub/bitcoin/depends'

real	4m14,862s
user	18m3,355s
sys 	1m24,506s

Qt docs: https://doc.qt.io/qt-5/qmake-precompiledheaders.html

Fixes #20423

+1 -3

0 comment

2 changed files

pr created time in 5 hours

pull request commentbitcoin/bitcoin

wallet: introduce setfeerate (an improved settxfee, in sat/vB)

Rebased and updated per the plan outlined in https://github.com/bitcoin/bitcoin/pull/20484#issuecomment-734786305.

jonatack

comment created time in 5 hours

Pull request review commentbitcoin/bitcoin

wallet: upgradewallet fixes, improvements, test coverage

 static RPCHelpMan upgradewallet()         version = request.params[0].get_int();     }     bilingual_str error;-    if (!pwallet->UpgradeWallet(version, error)) {-        throw JSONRPCError(RPC_WALLET_ERROR, error.original);+    const int previous_version{pwallet->GetVersion()};+    const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};+    const int current_version{pwallet->GetVersion()};+    std::string result;++    if (wallet_upgraded) {+        if (previous_version == current_version) {+            result = "Already at latest version. Wallet version unchanged.";+        } else {+            result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);+        }     }+     UniValue obj(UniValue::VOBJ);-    if (!error.empty()) {+    obj.pushKV("wallet_name", pwallet->GetName());+    obj.pushKV("previous_version", previous_version);+    obj.pushKV("current_version", current_version);+    if (!result.empty()) {+        obj.pushKV("result", result);+    } else {+        CHECK_NONFATAL(!error.empty());

Done in e915a2a2c87dad5beb68a175b21a07136bcc21ca

jonatack

comment created time in 5 hours

Pull request review commentbitcoin/bitcoin

wallet: upgradewallet fixes, improvements, test coverage

 def dumb_sync_blocks(self):             v16_3_node.submitblock(b)         assert_equal(v16_3_node.getblockcount(), to_height) +    def test_upgradewallet(self, wallet, previous_version, requested_version=None, expected_version=None):

Done in e915a2a2c87dad5beb68a175b21a07136bcc21ca

jonatack

comment created time in 5 hours

Pull request review commentbitcoin/bitcoin

wallet: introduce setfeerate (an improved settxfee, in sat/vB)

 static RPCHelpMan settxfee()     }; } +static RPCHelpMan setfeerate()+{+    return RPCHelpMan{+        "setfeerate",+        "\nSet the transaction fee rate in " + CURRENCY_ATOM + "/vB for this wallet. Overrides the global -paytxfee configuration option.\n"+        "Can be deactivated by passing 0 as the fee rate, in which case automatic fee selection will be used by default.\n",+        {+            {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee rate in " + CURRENCY_ATOM + "/vB to set (0 to unset)"},+        },+        RPCResult{+            RPCResult::Type::OBJ, "", "",+            {+                {RPCResult::Type::STR, "wallet_name", "Name of the wallet the fee rate setting applies to"},+                {RPCResult::Type::NUM, "fee_rate", "Fee rate after this operation"},+                {RPCResult::Type::STR, "result", /* optional */ true, "Description of result, if successful"},+                {RPCResult::Type::STR, "error", /* optional */ true, "Description of error, if any"},+            },+        },+        RPCExamples{+            ""+            "\nSet a fee rate of 1 " + CURRENCY_ATOM + "/vB\n"+            + HelpExampleCli("setfeerate", "1") ++            "\nSet a fee rate of 3.141 " + CURRENCY_ATOM + "/vB\n"+            + HelpExampleCli("setfeerate", "3.141") ++            "\nSet a fee rate of 7.75 " + CURRENCY_ATOM + "/vB with named arguments\n"+            + HelpExampleCli("-named setfeerate", "amount=7.75") ++            "\nSet a fee rate of 25 " + CURRENCY_ATOM + "/vB with the RPC\n"+            + HelpExampleRpc("setfeerate", "25")+        },+        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {+            std::shared_ptr<CWallet> const rpc_wallet{GetWalletForJSONRPCRequest(request)};+            if (!rpc_wallet) return NullUniValue;+            CWallet& wallet = *rpc_wallet;++            LOCK(wallet.cs_wallet);++            CFeeRate amount{AmountFromValue(request.params[0]), COIN};+            std::string amount_str{amount.ToString(FeeEstimateMode::SAT_B)};+            std::string current_amount_str{wallet.m_pay_tx_fee.ToString(FeeEstimateMode::SAT_B)};+            CFeeRate relay_min_feerate(wallet.chain().relayMinFee().GetFeePerK());+            CFeeRate wallet_min_feerate(wallet.m_min_fee.GetFeePerK());+            CFeeRate wallet_max_feerate(wallet.m_default_max_tx_fee, 1000);+            std::string result, error;++            if (amount == CFeeRate(0)) {+                wallet.m_pay_tx_fee = amount;+                result = "Fee rate for transactions with this wallet successfully unset. By default, automatic fee selection will be used.";+            } else if (amount < relay_min_feerate) {+                error = strprintf("The requested fee rate of %s cannot be less than the minimum relay fee rate of %s. The current setting of %s for this wallet remains unchanged.", amount_str, relay_min_feerate.ToString(FeeEstimateMode::SAT_B), current_amount_str);+            } else if (amount < wallet_min_feerate) {+                error = strprintf("The requested fee rate of %s cannot be less than the wallet min fee rate of %s. The current setting of %s for this wallet remains unchanged.", amount_str, wallet_min_feerate.ToString(FeeEstimateMode::SAT_B), current_amount_str);+            } else if (amount > wallet_max_feerate) {+                error = strprintf("The requested fee rate of %s cannot be greater than the wallet max fee rate of %s. The current setting of %s for this wallet remains unchanged.", amount_str, wallet_max_feerate.ToString(FeeEstimateMode::SAT_B), current_amount_str);+            } else {+                wallet.m_pay_tx_fee = amount;+                result = "Fee rate for transactions with this wallet successfully set to " + amount_str;+            }++            UniValue obj(UniValue::VOBJ);+            obj.pushKV("wallet_name", wallet.GetName());+            obj.pushKV("fee_rate", UniValue(UniValue::VNUM, wallet.m_pay_tx_fee.SatsToString()));

Maybe rebase this on top of 8798383

Pulled 8798383 in as commit 0e2c3ace86b8aa

jonatack

comment created time in 5 hours

pull request commentbitcoin/bitcoin

Use addrv2 serialization in anchors.dat

@jnewbery Oops, yes, that is only true when combined with #20516, or with @vasild's patch above.

sipa

comment created time in 6 hours

pull request commentbitcoin/bitcoin

Use addrv2 serialization in anchors.dat

@vasild Did you see #20516?

sipa

comment created time in 6 hours

pull request commentbitcoin-core/secp256k1

Add sage script for generating scalar_split_lambda constants

Another check to add is that lambda*P = <beta*P.x, y>. Checking for P=G is probably sufficient. The point is that the two roots of X^2+X+1 in Zn and Zp need to be matched up in accordance to the group operation on the secp256k1 curve.

real-or-random

comment created time in 6 hours

Pull request review commentbitcoin-core/secp256k1

Safegcd inverses, drop Jacobi symbols, remove libgmp

+/**********************************************************************+ * Copyright (c) 2020 Peter Dettman                                   *+ * Distributed under the MIT software license, see the accompanying   *+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*+ **********************************************************************/++#ifndef SECP256K1_MODINV32_IMPL_H+#define SECP256K1_MODINV32_IMPL_H++#include "modinv32.h"++#include "util.h"++static void secp256k1_modinv32_signed30_verify(const secp256k1_modinv32_signed30* a) {+    /* a must be in the range [-2^256, 2^256). */+    VERIFY_CHECK(a->v[0] >> 30 == 0);+    VERIFY_CHECK(a->v[1] >> 30 == 0);+    VERIFY_CHECK(a->v[2] >> 30 == 0);+    VERIFY_CHECK(a->v[3] >> 30 == 0);+    VERIFY_CHECK(a->v[4] >> 30 == 0);+    VERIFY_CHECK(a->v[5] >> 30 == 0);+    VERIFY_CHECK(a->v[6] >> 30 == 0);+    VERIFY_CHECK(a->v[7] >> 30 == 0);+    VERIFY_CHECK(a->v[8] >> 16 == 0 || a->v[8] >> 16 == -(int32_t)1);+}++static uint32_t secp256k1_modinv32_divsteps_30(uint32_t eta, uint32_t f0, uint32_t g0, int32_t *t) {+    uint32_t u = 1, v = 0, q = 0, r = 1;+    uint32_t c1, c2, f = f0, g = g0, x, y, z;+    int i;++    for (i = 0; i < 30; ++i) {+        VERIFY_CHECK((f & 1) == 1);+        VERIFY_CHECK((u * f0 + v * g0) == f << i);+        VERIFY_CHECK((q * f0 + r * g0) == g << i);++        c1 = (int32_t)eta >> 31;+        c2 = -(g & 1);++        x = (f ^ c1) - c1;+        y = (u ^ c1) - c1;+        z = (v ^ c1) - c1;++        g += x & c2;+        q += y & c2;+        r += z & c2;++        c1 &= c2;+        eta = (eta ^ c1) - (c1 + 1);++        f += g & c1;+        u += q & c1;+        v += r & c1;++        g >>= 1;+        u <<= 1;+        v <<= 1;+    }++    t[0] = (int32_t)u;+    t[1] = (int32_t)v;+    t[2] = (int32_t)q;+    t[3] = (int32_t)r;++    return eta;+}++static uint32_t secp256k1_modinv32_divsteps_30_var(uint32_t eta, uint32_t f0, uint32_t g0, int32_t *t) {+    /* inv256[i] = -(2*i+1)^-1 (mod 256) */+    static const uint8_t inv256[128] = {+        0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59,+        0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31,+        0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89,+        0x07, 0x9D, 0x7B, 0x51, 0x4F, 0x25, 0x03, 0x99, 0x17, 0x2D, 0x0B, 0x61,+        0x5F, 0xB5, 0x93, 0xA9, 0x27, 0xBD, 0x9B, 0x71, 0x6F, 0x45, 0x23, 0xB9,+        0x37, 0x4D, 0x2B, 0x81, 0x7F, 0xD5, 0xB3, 0xC9, 0x47, 0xDD, 0xBB, 0x91,+        0x8F, 0x65, 0x43, 0xD9, 0x57, 0x6D, 0x4B, 0xA1, 0x9F, 0xF5, 0xD3, 0xE9,+        0x67, 0xFD, 0xDB, 0xB1, 0xAF, 0x85, 0x63, 0xF9, 0x77, 0x8D, 0x6B, 0xC1,+        0xBF, 0x15, 0xF3, 0x09, 0x87, 0x1D, 0xFB, 0xD1, 0xCF, 0xA5, 0x83, 0x19,+        0x97, 0xAD, 0x8B, 0xE1, 0xDF, 0x35, 0x13, 0x29, 0xA7, 0x3D, 0x1B, 0xF1,+        0xEF, 0xC5, 0xA3, 0x39, 0xB7, 0xCD, 0xAB, 0x01+    };++    uint32_t u = 1, v = 0, q = 0, r = 1;+    uint32_t f = f0, g = g0, m, w, x, y, z;+    int i = 30, limit, zeros;++    for (;;) {+        /* Use a sentinel bit to count zeros only up to i. */+        zeros = secp256k1_ctz32_var(g | (UINT32_MAX << i));++        g >>= zeros;+        u <<= zeros;+        v <<= zeros;+        eta -= zeros;+        i -= zeros;++        if (i <= 0) {+            break;+        }++        VERIFY_CHECK((f & 1) == 1);+        VERIFY_CHECK((g & 1) == 1);+        VERIFY_CHECK((u * f0 + v * g0) == f << (30 - i));+        VERIFY_CHECK((q * f0 + r * g0) == g << (30 - i));++        if ((int32_t)eta < 0) {+            eta = -eta;+            x = f; f = g; g = -x;+            y = u; u = q; q = -y;+            z = v; v = r; r = -z;+        }++        /* Handle up to 8 divsteps at once, subject to eta and i. */+        limit = ((int)eta + 1) > i ? i : ((int)eta + 1);+        m = (UINT32_MAX >> (32 - limit)) & 255U;++        w = (g * inv256[(f >> 1) & 127]) & m;++        g += f * w;+        q += u * w;+        r += v * w;++        VERIFY_CHECK((g & m) == 0);+    }++    t[0] = (int32_t)u;+    t[1] = (int32_t)v;+    t[2] = (int32_t)q;+    t[3] = (int32_t)r;++    return eta;+}++static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp256k1_modinv32_signed30 *e, const int32_t *t, const secp256k1_modinv32_modinfo* modinfo) {+    const int32_t M30 = (int32_t)(UINT32_MAX >> 2);+    int32_t u = t[0], v = t[1], q = t[2], r = t[3], di, ei, md, me;+    int64_t cd, ce;+    int i;++    di = d->v[0];+    ei = e->v[0];++    cd = (int64_t)u * di + (int64_t)v * ei;+    ce = (int64_t)q * di + (int64_t)r * ei;++    /* Calculate the multiples of P to add, to zero the 30 bottom bits. We choose md, me+     * from the centred range [-2^29, 2^29) to keep d, e within [-2^256, 2^256). */+    md = ((int32_t)(modinfo->montmul4 * (uint32_t)cd)) >> 2;+    me = ((int32_t)(modinfo->montmul4 * (uint32_t)ce)) >> 2;++    if (modinfo->modulus.v[0]) {

I think this point still stands; the if should be removed for modulus.v[0] and v[4] (resp. v[8]).

sipa

comment created time in 6 hours

more