mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 11:32:46 +01:00
Merge pull request #5506 from UdjinM6/backport_19.3_candidates
[v19.x] Backport 19.3 candidates, v19.3.0 release notes and version bump
This commit is contained in:
commit
a884f0c536
@ -1,6 +1,6 @@
|
||||
AC_PREREQ([2.69])
|
||||
define(_CLIENT_VERSION_MAJOR, 19)
|
||||
define(_CLIENT_VERSION_MINOR, 2)
|
||||
define(_CLIENT_VERSION_MINOR, 3)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_RC, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Dash Core version v19.2.0
|
||||
# Dash Core version v19.3.0
|
||||
|
||||
Release is now available from:
|
||||
|
||||
@ -7,8 +7,7 @@ Release is now available from:
|
||||
This is a new minor version release, bringing various bugfixes and other
|
||||
improvements.
|
||||
|
||||
This release is mandatory for all nodes. This release resolves issues around the
|
||||
v19 Hard Fork activation. All nodes must upgrade to continue syncing properly.
|
||||
This release is optional for all nodes.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
@ -27,15 +26,6 @@ using version < 0.13 you will have to reindex (start with -reindex-chainstate
|
||||
or -reindex) to make sure your wallet has all the new data synced. Upgrading
|
||||
from version 0.13 should not require any additional actions.
|
||||
|
||||
At the first startup Dash Core will run a migration process which can take
|
||||
anywhere from a few minutes to thirty minutes to finish. After the migration,
|
||||
a downgrade to an older version is only possible with a reindex.
|
||||
|
||||
Please note that seamless migration is only possible on nodes which did not
|
||||
reach the v19 fork block. Nodes that reached it can either rewind a couple
|
||||
of blocks back to a pre-v19 block using `invalidateblock` RPC while still
|
||||
running the old version or they can reindex instead.
|
||||
|
||||
## Downgrade warning
|
||||
|
||||
### Downgrade to a version < v19.2.0
|
||||
@ -46,79 +36,47 @@ reindex or re-sync the whole chain.
|
||||
|
||||
# Notable changes
|
||||
|
||||
## Resolve v19 Hard Fork Issues
|
||||
## CoinJoin improvements
|
||||
|
||||
One of the goals for the v19 Hard Fork was to activate basic BLS scheme and
|
||||
start using it in various on-chain and p2p messages. The motivation behind this
|
||||
change is the need to be aligned with IETF standards. Unfortunately, a few edge
|
||||
cases were missed in our functional tests and were not caught on testnet either.
|
||||
v19 activation attempt on mainnet hit one of these edge cases and mainnet
|
||||
stopped producing blocks. As an intermediate solution v19.1.0 was released which
|
||||
delayed the start of the signaling for the v19 Hard Fork until June 14th.
|
||||
This release fixes a couple of issues with mixing on nodes that start with no
|
||||
wallet loaded initially.
|
||||
|
||||
To resolve these issues we had to rework the way BLS public keys are handled
|
||||
including the way they are serialized in the internal database. This made it
|
||||
incompatible with older versions of Dash Core, so a db migration path was
|
||||
implemented for all recent versions.
|
||||
## Wallet GUI improvements
|
||||
|
||||
## Improve migration and historical data support on light clients
|
||||
Wallets with 100k+ txes should now be able to rescan without hanging forever
|
||||
while processing notifications for every tx. Running `keypoolrefill` with a
|
||||
large number of keys will no longer lockup the GUI and can be interrupted.
|
||||
Running `upgradetohd` can also be interrupted now.
|
||||
|
||||
As a side-effect, the solution implemented to resolve v19 Hard Fork issues
|
||||
opened a path to simplify v19 migration for mobile wallets.
|
||||
## Changes in RPCs, commands and config options
|
||||
|
||||
With previous implementation mobile wallets would have to convert 4k+ pubkeys
|
||||
at the v19 fork point and that can easily take 10-15 seconds if not more.
|
||||
Also, after the v19 Hard Fork, if a masternode list is requested from a block
|
||||
before the v19 Hard Fork, the operator keys were coming in basic BLS scheme,
|
||||
but the masternode merkleroot hash stored in coinbase transaction at that time
|
||||
was calculated with legacy BLS scheme. Hence it was impossible to verify the
|
||||
merkleroot hash.
|
||||
|
||||
To fix these issues a new field `nVersion` was introduced for every entry in
|
||||
`mnlistdiff` p2p message. This field indicates which BLS scheme should be used
|
||||
when deserialising the message - legacy or basic. `nVersion` of the `mnlistdiff`
|
||||
message itself will no longer indicate the scheme and must always be set to `1`.
|
||||
|
||||
## Improve mixing support on light clients
|
||||
|
||||
Recent changes to `dsq` and `dstx` messages allowed mobile clients that get
|
||||
masternode lists from `mnlistdiff` message to determine the masternode related
|
||||
to these messages because the `proTxHash` was used instead of the
|
||||
`masternodeOutpoint`. Once the v19 Hard Fork activates the signature of `dsq`
|
||||
and `dstx` messages will be based on the `proTxHash` which should make it
|
||||
possible for mobile clients to verify it.
|
||||
|
||||
## Allow keeping Chainlocks enabled without signing new ones
|
||||
|
||||
Before this version Chainlocks were either enabled or disabled. Starting with
|
||||
this version it's possible to set `SPORK_19_CHAINLOCKS_ENABLED` to a non-zero
|
||||
value to disable the signing of new Chainlocks while still enforcing the best
|
||||
known one.
|
||||
- `wipewallettxes`: New RPC command which removes all wallet transactions
|
||||
- `wipetxes`: New command for `dash-wallet` that removes all wallet transactions
|
||||
- `masternodelist`: New mode `hpmn` filters only HPMNs/EvoNodes
|
||||
- `protx list`: New type `hpmn` filters only HPMNs/EvoNodes
|
||||
- `-blockversion` config option is allowed on non-mainnet networks now
|
||||
|
||||
## Other changes
|
||||
|
||||
There were a few other minor changes too, specifically:
|
||||
- reindex on DB corruption should now start properly in Qt
|
||||
- a mnemonic passphrase longer than 256 symbols no longer crashes the wallet
|
||||
- a Qt node running with `-disablewawllet` flag should not crash in Settings now
|
||||
- `-masternodeblsprivkey` and `-sporkkey` values are no longer printed in
|
||||
`debug.log`
|
||||
- should use less memory in the long run comparing to older versions
|
||||
- gmp library detection should work better on macos
|
||||
- fixed a couple of typos
|
||||
- Added Kittywhiskers Van Gogh (kittywhiskers) and Odysseas Gabrielides
|
||||
(ogabrielides) to contributors list in 19.2.0 release notes
|
||||
- There should be no false "unknown rules activated" warning in GUI and RPCs now
|
||||
- Empty `settings.json` file no longer results in node startup failure
|
||||
- Block processing was slightly optimized
|
||||
- BLS library was updated to version 1.3.0 to fix a couple tiny issues
|
||||
- Fixed a couple of small issues in tests
|
||||
|
||||
# v19.2.0 Change log
|
||||
# v19.3.0 Change log
|
||||
|
||||
See detailed [set of changes](https://github.com/dashpay/dash/compare/v19.1.0...dashpay:v19.2.0).
|
||||
See detailed [set of changes](https://github.com/dashpay/dash/compare/v19.2.0...dashpay:v19.3.0).
|
||||
|
||||
# Credits
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Konstantin Akimov (knst)
|
||||
- Nathan Marley (nmarley)
|
||||
- Odysseas Gabrielides (ogabrielides)
|
||||
- PastaPastaPasta
|
||||
- thephez
|
||||
- UdjinM6
|
||||
|
||||
As well as everyone that submitted issues, reviewed pull requests and helped
|
||||
@ -146,7 +104,8 @@ Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12.
|
||||
|
||||
These release are considered obsolete. Old release notes can be found here:
|
||||
|
||||
- [v19.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.0.0.md) released May/22/2023
|
||||
- [v19.2.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.2.0.md) released June/19/2023
|
||||
- [v19.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.1.0.md) released May/22/2023
|
||||
- [v19.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.0.0.md) released Apr/14/2023
|
||||
- [v18.2.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.md) released Mar/21/2023
|
||||
- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.1.md) released Jan/17/2023
|
||||
|
189
doc/release-notes/dash/release-notes-19.2.0.md
Normal file
189
doc/release-notes/dash/release-notes-19.2.0.md
Normal file
@ -0,0 +1,189 @@
|
||||
# Dash Core version v19.2.0
|
||||
|
||||
Release is now available from:
|
||||
|
||||
<https://www.dash.org/downloads/#wallets>
|
||||
|
||||
This is a new minor version release, bringing various bugfixes and other
|
||||
improvements.
|
||||
|
||||
This release is mandatory for all nodes. This release resolves issues around the
|
||||
v19 Hard Fork activation. All nodes must upgrade to continue syncing properly.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
<https://github.com/dashpay/dash/issues>
|
||||
|
||||
|
||||
# Upgrading and downgrading
|
||||
|
||||
## How to Upgrade
|
||||
|
||||
If you are running an older version, shut it down. Wait until it has completely
|
||||
shut down (which might take a few minutes for older versions), then run the
|
||||
installer (on Windows) or just copy over /Applications/Dash-Qt (on Mac) or
|
||||
dashd/dash-qt (on Linux). If you upgrade after DIP0003 activation and you were
|
||||
using version < 0.13 you will have to reindex (start with -reindex-chainstate
|
||||
or -reindex) to make sure your wallet has all the new data synced. Upgrading
|
||||
from version 0.13 should not require any additional actions.
|
||||
|
||||
At the first startup Dash Core will run a migration process which can take
|
||||
anywhere from a few minutes to thirty minutes to finish. After the migration,
|
||||
a downgrade to an older version is only possible with a reindex.
|
||||
|
||||
Please note that seamless migration is only possible on nodes which did not
|
||||
reach the v19 fork block. Nodes that reached it can either rewind a couple
|
||||
of blocks back to a pre-v19 block using `invalidateblock` RPC while still
|
||||
running the old version or they can reindex instead.
|
||||
|
||||
## Downgrade warning
|
||||
|
||||
### Downgrade to a version < v19.2.0
|
||||
|
||||
Downgrading to a version older than v19.2.0 is not supported due to changes
|
||||
in the evodb database. If you need to use an older version, you must either
|
||||
reindex or re-sync the whole chain.
|
||||
|
||||
# Notable changes
|
||||
|
||||
## Resolve v19 Hard Fork Issues
|
||||
|
||||
One of the goals for the v19 Hard Fork was to activate basic BLS scheme and
|
||||
start using it in various on-chain and p2p messages. The motivation behind this
|
||||
change is the need to be aligned with IETF standards. Unfortunately, a few edge
|
||||
cases were missed in our functional tests and were not caught on testnet either.
|
||||
v19 activation attempt on mainnet hit one of these edge cases and mainnet
|
||||
stopped producing blocks. As an intermediate solution v19.1.0 was released which
|
||||
delayed the start of the signaling for the v19 Hard Fork until June 14th.
|
||||
|
||||
To resolve these issues we had to rework the way BLS public keys are handled
|
||||
including the way they are serialized in the internal database. This made it
|
||||
incompatible with older versions of Dash Core, so a db migration path was
|
||||
implemented for all recent versions.
|
||||
|
||||
## Improve migration and historical data support on light clients
|
||||
|
||||
As a side-effect, the solution implemented to resolve v19 Hard Fork issues
|
||||
opened a path to simplify v19 migration for mobile wallets.
|
||||
|
||||
With previous implementation mobile wallets would have to convert 4k+ pubkeys
|
||||
at the v19 fork point and that can easily take 10-15 seconds if not more.
|
||||
Also, after the v19 Hard Fork, if a masternode list is requested from a block
|
||||
before the v19 Hard Fork, the operator keys were coming in basic BLS scheme,
|
||||
but the masternode merkleroot hash stored in coinbase transaction at that time
|
||||
was calculated with legacy BLS scheme. Hence it was impossible to verify the
|
||||
merkleroot hash.
|
||||
|
||||
To fix these issues a new field `nVersion` was introduced for every entry in
|
||||
`mnlistdiff` p2p message. This field indicates which BLS scheme should be used
|
||||
when deserialising the message - legacy or basic. `nVersion` of the `mnlistdiff`
|
||||
message itself will no longer indicate the scheme and must always be set to `1`.
|
||||
|
||||
## Improve mixing support on light clients
|
||||
|
||||
Recent changes to `dsq` and `dstx` messages allowed mobile clients that get
|
||||
masternode lists from `mnlistdiff` message to determine the masternode related
|
||||
to these messages because the `proTxHash` was used instead of the
|
||||
`masternodeOutpoint`. Once the v19 Hard Fork activates the signature of `dsq`
|
||||
and `dstx` messages will be based on the `proTxHash` which should make it
|
||||
possible for mobile clients to verify it.
|
||||
|
||||
## Allow keeping Chainlocks enabled without signing new ones
|
||||
|
||||
Before this version Chainlocks were either enabled or disabled. Starting with
|
||||
this version it's possible to set `SPORK_19_CHAINLOCKS_ENABLED` to a non-zero
|
||||
value to disable the signing of new Chainlocks while still enforcing the best
|
||||
known one.
|
||||
|
||||
## Other changes
|
||||
|
||||
There were a few other minor changes too, specifically:
|
||||
- reindex on DB corruption should now start properly in Qt
|
||||
- a mnemonic passphrase longer than 256 symbols no longer crashes the wallet
|
||||
- a Qt node running with `-disablewawllet` flag should not crash in Settings now
|
||||
- `-masternodeblsprivkey` and `-sporkkey` values are no longer printed in
|
||||
`debug.log`
|
||||
- should use less memory in the long run comparing to older versions
|
||||
- gmp library detection should work better on macos
|
||||
- fixed a couple of typos
|
||||
|
||||
# v19.2.0 Change log
|
||||
|
||||
See detailed [set of changes](https://github.com/dashpay/dash/compare/v19.1.0...dashpay:v19.2.0).
|
||||
|
||||
# Credits
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Kittywhiskers Van Gogh (kittywhiskers)
|
||||
- Konstantin Akimov (knst)
|
||||
- Nathan Marley (nmarley)
|
||||
- Odysseas Gabrielides (ogabrielides)
|
||||
- PastaPastaPasta
|
||||
- thephez
|
||||
- UdjinM6
|
||||
|
||||
As well as everyone that submitted issues, reviewed pull requests and helped
|
||||
debug the release candidates.
|
||||
|
||||
# Older releases
|
||||
|
||||
Dash was previously known as Darkcoin.
|
||||
|
||||
Darkcoin tree 0.8.x was a fork of Litecoin tree 0.8, original name was XCoin
|
||||
which was first released on Jan/18/2014.
|
||||
|
||||
Darkcoin tree 0.9.x was the open source implementation of masternodes based on
|
||||
the 0.8.x tree and was first released on Mar/13/2014.
|
||||
|
||||
Darkcoin tree 0.10.x used to be the closed source implementation of Darksend
|
||||
which was released open source on Sep/25/2014.
|
||||
|
||||
Dash Core tree 0.11.x was a fork of Bitcoin Core tree 0.9,
|
||||
Darkcoin was rebranded to Dash.
|
||||
|
||||
Dash Core tree 0.12.0.x was a fork of Bitcoin Core tree 0.10.
|
||||
|
||||
Dash Core tree 0.12.1.x was a fork of Bitcoin Core tree 0.12.
|
||||
|
||||
These release are considered obsolete. Old release notes can be found here:
|
||||
|
||||
- [v19.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.0.0.md) released May/22/2023
|
||||
- [v19.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.0.0.md) released Apr/14/2023
|
||||
- [v18.2.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.md) released Mar/21/2023
|
||||
- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.1.md) released Jan/17/2023
|
||||
- [v18.2.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.0.md) released Jan/01/2023
|
||||
- [v18.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.1.1.md) released January/08/2023
|
||||
- [v18.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.1.0.md) released October/09/2022
|
||||
- [v18.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.0.2.md) released October/09/2022
|
||||
- [v18.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.0.1.md) released August/17/2022
|
||||
- [v0.17.0.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.17.0.3.md) released June/07/2021
|
||||
- [v0.17.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.17.0.2.md) released May/19/2021
|
||||
- [v0.16.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.1.1.md) released November/17/2020
|
||||
- [v0.16.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.1.0.md) released November/14/2020
|
||||
- [v0.16.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.0.1.md) released September/30/2020
|
||||
- [v0.15.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.15.0.0.md) released Febrary/18/2020
|
||||
- [v0.14.0.5](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.5.md) released December/08/2019
|
||||
- [v0.14.0.4](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.4.md) released November/22/2019
|
||||
- [v0.14.0.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.3.md) released August/15/2019
|
||||
- [v0.14.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.2.md) released July/4/2019
|
||||
- [v0.14.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.1.md) released May/31/2019
|
||||
- [v0.14.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.md) released May/22/2019
|
||||
- [v0.13.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.3.md) released Apr/04/2019
|
||||
- [v0.13.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.2.md) released Mar/15/2019
|
||||
- [v0.13.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.1.md) released Feb/9/2019
|
||||
- [v0.13.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.0.md) released Jan/14/2019
|
||||
- [v0.12.3.4](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.4.md) released Dec/14/2018
|
||||
- [v0.12.3.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.3.md) released Sep/19/2018
|
||||
- [v0.12.3.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.2.md) released Jul/09/2018
|
||||
- [v0.12.3.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.1.md) released Jul/03/2018
|
||||
- [v0.12.2.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.3.md) released Jan/12/2018
|
||||
- [v0.12.2.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.2.md) released Dec/17/2017
|
||||
- [v0.12.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.md) released Nov/08/2017
|
||||
- [v0.12.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.1.md) released Feb/06/2017
|
||||
- [v0.12.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.0.md) released Aug/15/2015
|
||||
- [v0.11.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.2.md) released Mar/04/2015
|
||||
- [v0.11.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.1.md) released Feb/10/2015
|
||||
- [v0.11.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.0.md) released Jan/15/2015
|
||||
- [v0.10.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.10.0.md) released Sep/25/2014
|
||||
- [v0.9.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.9.0.md) released Mar/13/2014
|
@ -31,6 +31,7 @@ static void SetupWalletToolArgs(ArgsManager& argsman)
|
||||
|
||||
// Hidden
|
||||
argsman.AddArg("salvage", "Attempt to recover private keys from a corrupt wallet", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
|
||||
argsman.AddArg("wipetxes", "Wipe all transactions from a wallet", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
|
||||
}
|
||||
|
||||
static bool WalletAppInit(int argc, char* argv[])
|
||||
|
@ -162,7 +162,7 @@ public:
|
||||
consensus.DIP0003EnforcementHash = uint256S("000000000000002d1734087b4c5afc3133e4e1c3e1a89218f62bcd9bb3d17f81");
|
||||
consensus.DIP0008Height = 1088640; // 00000000000000112e41e4b3afda8b233b8cc07c532d2eac5de097b68358c43e
|
||||
consensus.BRRHeight = 1374912; // 000000000000000c5a124f3eccfbe6e17876dca79cec9e63dfa70d269113c926
|
||||
consensus.MinBIP9WarningHeight = 1090656; // dip8 activation height + miner confirmation window
|
||||
consensus.MinBIP9WarningHeight = 1899072 + 2016; // V19 activation height + miner confirmation window
|
||||
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
|
||||
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
|
||||
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
|
||||
@ -402,7 +402,7 @@ public:
|
||||
consensus.DIP0003EnforcementHash = uint256S("00000055ebc0e974ba3a3fb785c5ad4365a39637d4df168169ee80d313612f8f");
|
||||
consensus.DIP0008Height = 78800; // 000000000e9329d964d80e7dab2e704b43b6bd2b91fea1e9315d38932e55fb55
|
||||
consensus.BRRHeight = 387500; // 0000001537dbfd09dea69f61c1f8b2afa27c8dc91c934e144797761c9f10367b
|
||||
consensus.MinBIP9WarningHeight = 80816; // dip8 activation height + miner confirmation window
|
||||
consensus.MinBIP9WarningHeight = 850100 + 2016; // v19 activation height + miner confirmation window
|
||||
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
|
||||
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
|
||||
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
|
||||
@ -616,7 +616,7 @@ public:
|
||||
consensus.DIP0003EnforcementHash = uint256();
|
||||
consensus.DIP0008Height = 2; // DIP0008 activated immediately on devnet
|
||||
consensus.BRRHeight = 300;
|
||||
consensus.MinBIP9WarningHeight = 2018; // dip8 activation height + miner confirmation window
|
||||
consensus.MinBIP9WarningHeight = 300 + 2016; // v19 activation height + miner confirmation window
|
||||
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
|
||||
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
|
||||
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
|
||||
|
@ -35,14 +35,8 @@ std::unique_ptr<CCoinJoinClientQueueManager> coinJoinClientQueueManager;
|
||||
void CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (fMasternodeMode) return;
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (!m_mn_sync->IsBlockchainSynced()) return;
|
||||
|
||||
if (!CheckDiskSpace(GetDataDir())) {
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientQueueManager::ProcessMessage -- Not enough disk space, disabling CoinJoin.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_type == NetMsgType::DSQUEUE) {
|
||||
CCoinJoinClientQueueManager::ProcessDSQueue(peer, vRecv);
|
||||
}
|
||||
@ -1806,7 +1800,6 @@ void CCoinJoinClientManager::UpdatedBlockTip(const CBlockIndex* pindex)
|
||||
|
||||
void CCoinJoinClientQueueManager::DoMaintenance()
|
||||
{
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) return;
|
||||
if (m_mn_sync == nullptr) return;
|
||||
if (fMasternodeMode) return; // no client-side mixing on masternodes
|
||||
|
||||
|
3
src/dashbls/.gitignore
vendored
3
src/dashbls/.gitignore
vendored
@ -15,6 +15,7 @@ blspy.*.so
|
||||
.mypy_cache/
|
||||
.pytest_chache/
|
||||
.eggs/
|
||||
cmake-build-debug/
|
||||
|
||||
js_build
|
||||
node_modules
|
||||
@ -67,6 +68,8 @@ yarn-error.log
|
||||
.vs/
|
||||
out/
|
||||
|
||||
target
|
||||
|
||||
Makefile.in
|
||||
/ar-lib
|
||||
/mdate-sh
|
||||
|
@ -14,6 +14,7 @@ endif()
|
||||
|
||||
project(BLS)
|
||||
|
||||
set(BUILD_BLS_JS_BINDINGS "1" CACHE STRING "")
|
||||
set(BUILD_BLS_PYTHON_BINDINGS "1" CACHE STRING "")
|
||||
set(BUILD_BLS_TESTS "1" CACHE STRING "")
|
||||
set(BUILD_BLS_BENCHMARKS "1" CACHE STRING "")
|
||||
@ -110,10 +111,36 @@ set(MI_OVERRIDE "off" CACHE STRING "")
|
||||
add_subdirectory(depends/relic)
|
||||
add_subdirectory(depends/mimalloc)
|
||||
|
||||
#message(STATUS "Patching Relic to make setjmp.h inclusion conditional")
|
||||
#
|
||||
#execute_process(
|
||||
# COMMAND bash -c "git apply ${CMAKE_SOURCE_DIR}/setjmp_patch.diff"
|
||||
# WORKING_DIRECTORY ${RELIC_SRC}
|
||||
#)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
# Write include paths for rust binding
|
||||
if(EMSCRIPTEN)
|
||||
add_subdirectory(js-bindings)
|
||||
file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}/c++/v1/;")
|
||||
endif()
|
||||
|
||||
file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES};")
|
||||
|
||||
if(GMP_INCLUDES)
|
||||
file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${GMP_INCLUDES};")
|
||||
endif()
|
||||
|
||||
# Write gmp library path for rust binding
|
||||
if(GMP_LIBRARIES)
|
||||
file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/gmp_libraries.txt" "${GMP_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
if(BUILD_BLS_JS_BINDINGS)
|
||||
add_subdirectory(js-bindings)
|
||||
endif()
|
||||
else()
|
||||
# emscripten can't build python bindings, it produces only javascript
|
||||
# add_subdirectory(contrib/pybind11)
|
||||
|
373
src/dashbls/apple.rust.deps.sh
Executable file
373
src/dashbls/apple.rust.deps.sh
Executable file
@ -0,0 +1,373 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
# "x86_64-apple-ios"
|
||||
# "aarch64-apple-ios"
|
||||
# "aarch64-apple-ios-sim"
|
||||
# "x86_64-apple-darwin"
|
||||
# "aarch64-apple-darwin"
|
||||
# TODO: it's probably needs to be optimized in order to increase better build velocity
|
||||
# TODO: so we need to combine multiple targets
|
||||
TARGET=$1
|
||||
git submodule update --init
|
||||
MIN_IOS="13.0"
|
||||
MIN_WATCHOS="5.0"
|
||||
MIN_TVOS=$MIN_IOS
|
||||
MIN_MACOS="10.15"
|
||||
|
||||
IPHONEOS=iphoneos
|
||||
IPHONESIMULATOR=iphonesimulator
|
||||
WATCHOS=watchos
|
||||
WATCHSIMULATOR=watchsimulator
|
||||
TVOS=appletvos
|
||||
TVSIMULATOR=appletvsimulator
|
||||
MACOS=macosx
|
||||
|
||||
LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max)
|
||||
BUILD=build
|
||||
|
||||
version_min_flag() {
|
||||
PLATFORM=$1
|
||||
FLAG=""
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
FLAG="-miphoneos-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
FLAG="-mios-simulator-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
FLAG="-mwatchos-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
FLAG="-mwatchos-simulator-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
FLAG="-mtvos-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
FLAG="-mtvos-simulator-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
FLAG="-mmacosx-version-min=${MIN_MACOS}"
|
||||
fi
|
||||
echo $FLAG
|
||||
}
|
||||
|
||||
|
||||
prepare() {
|
||||
download_gmp() {
|
||||
GMP_VERSION="6.2.1"
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
mkdir -p "contrib"
|
||||
if [ ! -s "contrib/gmp-${GMP_VERSION}.tar.bz2" ]; then
|
||||
curl -L -o "contrib/gmp-${GMP_VERSION}.tar.bz2" https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.bz2
|
||||
fi
|
||||
rm -rf "contrib/gmp"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
tar xfj "gmp-${GMP_VERSION}.tar.bz2"
|
||||
mv gmp-${GMP_VERSION} gmp
|
||||
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
|
||||
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #build
|
||||
}
|
||||
|
||||
download_cmake_toolchain() {
|
||||
if [ ! -s "${BUILD}/ios.toolchain.cmake" ]; then
|
||||
SHA256_HASH="d02857ff6bd64f1d7109ca59c3e4f3b2f89d0663c412146e6977c679801b3243"
|
||||
curl -o "${BUILD}/ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake
|
||||
DOWNLOADED_HASH=$(shasum -a 256 ${BUILD}/ios.toolchain.cmake | cut -f 1 -d " ")
|
||||
if [ $SHA256_HASH != "$DOWNLOADED_HASH" ]; then
|
||||
echo "Error: sha256 checksum of ios.toolchain.cmake mismatch" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
download_relic() {
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
mkdir -p "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
git clone --depth 1 --branch "feat/ios-support" https://github.com/pankcuf/relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd relic
|
||||
git fetch --depth 1 origin 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
git checkout 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
fi
|
||||
}
|
||||
rm -rf ${BUILD}
|
||||
mkdir -p ${BUILD}
|
||||
download_relic
|
||||
download_gmp
|
||||
download_cmake_toolchain
|
||||
}
|
||||
|
||||
build_gmp_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
# why this works with this host only?
|
||||
HOST=arm-apple-darwin
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
PLATFORM_PATH=$(xcrun --sdk "$PLATFORM" --show-sdk-platform-path)
|
||||
CLANG=$(xcrun --sdk "$PLATFORM" --find clang)
|
||||
DEVELOPER=$(xcode-select --print-path)
|
||||
CURRENT_DIR=$(pwd)
|
||||
export PATH="${PLATFORM_PATH}/Developer/usr/bin:${DEVELOPER}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin"
|
||||
mkdir gmplib-"${PLATFORM}"-"${ARCH}"
|
||||
CFLAGS="-Wno-unused-value -fembed-bitcode -arch ${ARCH} --sysroot=${SDK} $(version_min_flag "$PLATFORM")"
|
||||
CONFIGURESCRIPT="gmp_configure_script.sh"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd gmp
|
||||
make clean || true
|
||||
make distclean || true
|
||||
echo "HOST: $HOST"
|
||||
echo "PREFIX: ${CURRENT_DIR}/gmplib-${PFX}"
|
||||
|
||||
cat >"$CONFIGURESCRIPT" << EOF
|
||||
#!/bin/sh
|
||||
./configure \
|
||||
CC="$CLANG" CFLAGS="$CFLAGS" CPPFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \
|
||||
--host=${HOST} --prefix="${CURRENT_DIR}/gmplib-${PFX}" \
|
||||
--disable-shared --enable-static --disable-assembly -v
|
||||
EOF
|
||||
|
||||
chmod a+x "$CONFIGURESCRIPT"
|
||||
sh "$CONFIGURESCRIPT"
|
||||
rm "$CONFIGURESCRIPT"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
mkdir -p "${CURRENT_DIR}/log"
|
||||
# shellcheck disable=SC2039
|
||||
make -j "$LOGICALCPU_MAX" &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-build.log
|
||||
# shellcheck disable=SC2039
|
||||
make install &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-install.log
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # gmp
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # build
|
||||
}
|
||||
|
||||
build_relic_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=relic-"${PFX}"
|
||||
TOOLCHAIN=$(pwd)/ios.toolchain.cmake
|
||||
GMP_PFX=$(pwd)/gmplib-${PFX}
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
unset CC
|
||||
# shellcheck disable=SC2155
|
||||
export CC=$(xcrun --sdk "${PLATFORM}" --find clang)
|
||||
|
||||
WSIZE=0
|
||||
IOS_PLATFORM=""
|
||||
OPTIMIZATIONFLAGS=""
|
||||
DEPLOYMENT_TARGET=""
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
if [[ $ARCH = "arm64" ]] || [[ $ARCH = "arm64e" ]]; then
|
||||
IOS_PLATFORM=OS64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
else
|
||||
IOS_PLATFORM=OS
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
if [[ $ARCH = "x86_64" ]]; then
|
||||
IOS_PLATFORM=SIMULATOR64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $ARCH = "arm64" ]]; then
|
||||
IOS_PLATFORM=SIMULATORARM64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
else
|
||||
IOS_PLATFORM=SIMULATOR
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
IOS_PLATFORM=WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
IOS_PLATFORM=TVOS
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_TVOS
|
||||
#TODO
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=OS64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
WSIZE=64
|
||||
IOS_PLATFORM=MAC
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=MAC_ARM64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_MACOS
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
fi
|
||||
|
||||
COMPILER_ARGS="$(version_min_flag "$PLATFORM") -Wno-unused-functions"
|
||||
|
||||
EXTRA_ARGS="-DOPSYS=NONE -DPLATFORM=$IOS_PLATFORM -DDEPLOYMENT_TARGET=$DEPLOYMENT_TARGET -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
if [[ $ARCH = "i386" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X86"
|
||||
elif [[ $ARCH = "x86_64" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X64"
|
||||
else
|
||||
EXTRA_ARGS+=" -DARCH=ARM"
|
||||
if [[ $ARCH = "armv7s" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
|
||||
elif [[ $ARCH = "armv7k" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
|
||||
elif [[ $ARCH = "arm64_32" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
|
||||
fi
|
||||
fi
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
cmake -DCMAKE_PREFIX_PATH:PATH="${GMP_PFX}" -DTESTS=0 -DBENCH=0 -DBUILD_BLS_JS_BINDINGS=0 -DBUILD_BLS_PYTHON_BINDINGS=0 \
|
||||
-DBUILD_BLS_BENCHMARKS=0 -DBUILD_BLS_TESTS=0 -DCHECK=off -DARITH=gmp -DTIMER=HPROC -DFP_PRIME=381 -DMULTI=PTHREAD \
|
||||
-DFP_QNRES=on -DFP_METHD="INTEG;INTEG;INTEG;MONTY;EXGCD;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" \
|
||||
-DCOMP_FLAGS="-pipe -std=c99 -O3 -funroll-loops $OPTIMIZATIONFLAGS -isysroot $SDK -arch $ARCH -fembed-bitcode ${COMPILER_ARGS}" \
|
||||
-DWSIZE=$WSIZE -DVERBS=off -DSHLIB=off -DALLOC="AUTO" -DEP_PLAIN=off -DEP_SUPER=off -DPP_EXT="LAZYR" \
|
||||
-DWITH="DV;BN;MD;FP;EP;FPX;EPX;PP;PC;CP" -DBN_METHD="COMBA;COMBA;MONTY;SLIDE;STEIN;BASIC" ${EXTRA_ARGS} ../../
|
||||
|
||||
make -j "$LOGICALCPU_MAX"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib/relic
|
||||
}
|
||||
|
||||
build_bls_arch() {
|
||||
# shellcheck disable=SC2039
|
||||
BLS_FILES=( "bls" "chaincode" "elements" "extendedprivatekey" "extendedpublickey" "legacy" "privatekey" "schemes" "threshold" )
|
||||
# shellcheck disable=SC2039
|
||||
ALL_BLS_OBJ_FILES=$(printf "%s.o " "${BLS_FILES[@]}")
|
||||
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=${BUILD}/bls-"${PFX}"
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
EXTRA_ARGS="$(version_min_flag "$PLATFORM")"
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
for F in "${BLS_FILES[@]}"
|
||||
do
|
||||
clang -I"../contrib/relic/include" \
|
||||
-I"../../depends/relic/include" \
|
||||
-I"../../include/dashbls" \
|
||||
-I"../relic-${PFX}/_deps/relic-build/include" \
|
||||
-I"../../src/" \
|
||||
-I"../gmplib-${PFX}/include" \
|
||||
-x c++ -std=c++14 -stdlib=libc++ -fembed-bitcode -arch "${ARCH}" -isysroot "${SDK}" "${EXTRA_ARGS}" \
|
||||
-c "../../src/${F}.cpp" -o "${F}.o"
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
xcrun -sdk "$PLATFORM" ar -cvq libbls.a $ALL_BLS_OBJ_FILES
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
}
|
||||
|
||||
build_all_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
build_gmp_arch "$PLATFORM" "$ARCH"
|
||||
build_relic_arch "$PLATFORM" "$ARCH"
|
||||
build_bls_arch "$PLATFORM" "$ARCH"
|
||||
}
|
||||
|
||||
build_target() {
|
||||
BUILD_IN=$1
|
||||
echo "Build target: $BUILD_IN"
|
||||
ARCH=""
|
||||
PLATFORM=""
|
||||
# shellcheck disable=SC2039
|
||||
if [[ $BUILD_IN = "x86_64-apple-ios" ]]; then
|
||||
ARCH=x86_64
|
||||
PLATFORM=$IPHONESIMULATOR
|
||||
elif [[ $BUILD_IN = "aarch64-apple-ios" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$IPHONEOS
|
||||
elif [[ $BUILD_IN = "aarch64-apple-ios-sim" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$IPHONESIMULATOR
|
||||
elif [[ $BUILD_IN = "x86_64-apple-darwin" ]]; then
|
||||
ARCH=x86_64
|
||||
PLATFORM=$MACOS
|
||||
elif [[ $BUILD_IN = "aarch64-apple-darwin" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$MACOS
|
||||
fi
|
||||
build_all_arch "$PLATFORM" "$ARCH"
|
||||
PFX="${PLATFORM}"-"${ARCH}"
|
||||
rm -rf "build/artefacts/${BUILD_IN}"
|
||||
mkdir -p "build/artefacts/${BUILD_IN}"
|
||||
cp "build/gmplib-${PFX}/lib/libgmp.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/relic-${PFX}/_deps/sodium-build/libsodium.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/bls-${PFX}/libbls.a" "build/artefacts/${BUILD_IN}"
|
||||
# cp -rf build/bls-"${PFX}"/*.o build/artefacts/"${BUILD_IN}"/include
|
||||
# cp -rf src/*.hpp build/artefacts/"${BUILD_IN}"/include
|
||||
# cp -rf build/gmplib-"${PFX}"/include/gmp.h build/artefacts/"${BUILD_IN}"/include
|
||||
# cp -rf build/relic-"${PFX}"/_deps/relic-build/include/*.h build/artefacts/"${BUILD_IN}"/include
|
||||
}
|
||||
|
||||
prepare
|
||||
build_target "$TARGET"
|
458
src/dashbls/apple.rust.sh
Executable file
458
src/dashbls/apple.rust.sh
Executable file
@ -0,0 +1,458 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
git submodule update --init
|
||||
|
||||
MIN_IOS="13.0"
|
||||
MIN_WATCHOS="5.0"
|
||||
MIN_TVOS=$MIN_IOS
|
||||
MIN_MACOS="10.15"
|
||||
|
||||
IPHONEOS=iphoneos
|
||||
IPHONESIMULATOR=iphonesimulator
|
||||
WATCHOS=watchos
|
||||
WATCHSIMULATOR=watchsimulator
|
||||
TVOS=appletvos
|
||||
TVSIMULATOR=appletvsimulator
|
||||
MACOS=macosx
|
||||
|
||||
LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max)
|
||||
BUILD=build
|
||||
|
||||
version_min_flag() {
|
||||
PLATFORM=$1
|
||||
FLAG=""
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
FLAG="-miphoneos-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
FLAG="-mios-simulator-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
FLAG="-mwatchos-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
FLAG="-mwatchos-simulator-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
FLAG="-mtvos-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
FLAG="-mtvos-simulator-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
FLAG="-mmacosx-version-min=${MIN_MACOS}"
|
||||
fi
|
||||
echo $FLAG
|
||||
}
|
||||
|
||||
|
||||
prepare() {
|
||||
download_gmp() {
|
||||
GMP_VERSION="6.2.1"
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
mkdir -p "contrib"
|
||||
if [ ! -s "contrib/gmp-${GMP_VERSION}.tar.bz2" ]; then
|
||||
curl -L -o "contrib/gmp-${GMP_VERSION}.tar.bz2" https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.bz2
|
||||
fi
|
||||
rm -rf "contrib/gmp"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
tar xfj "gmp-${GMP_VERSION}.tar.bz2"
|
||||
mv gmp-${GMP_VERSION} gmp
|
||||
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
|
||||
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #build
|
||||
}
|
||||
|
||||
download_cmake_toolchain() {
|
||||
if [ ! -s "${BUILD}/ios.toolchain.cmake" ]; then
|
||||
SHA256_HASH="d02857ff6bd64f1d7109ca59c3e4f3b2f89d0663c412146e6977c679801b3243"
|
||||
curl -o "${BUILD}/ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake
|
||||
DOWNLOADED_HASH=$(shasum -a 256 ${BUILD}/ios.toolchain.cmake | cut -f 1 -d " ")
|
||||
if [ $SHA256_HASH != "$DOWNLOADED_HASH" ]; then
|
||||
echo "Error: sha256 checksum of ios.toolchain.cmake mismatch" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
download_relic() {
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
mkdir -p "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
git clone --depth 1 --branch "feat/ios-support" https://github.com/pankcuf/relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd relic
|
||||
git fetch --depth 1 origin 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
git checkout 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
fi
|
||||
}
|
||||
rm -rf ${BUILD}
|
||||
mkdir -p ${BUILD}
|
||||
download_relic
|
||||
download_gmp
|
||||
download_cmake_toolchain
|
||||
mkdir -p ${BUILD}/artefacts/include
|
||||
}
|
||||
|
||||
build_gmp_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
# why this works with this host only?
|
||||
HOST=arm-apple-darwin
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
PLATFORM_PATH=$(xcrun --sdk "$PLATFORM" --show-sdk-platform-path)
|
||||
CLANG=$(xcrun --sdk "$PLATFORM" --find clang)
|
||||
DEVELOPER=$(xcode-select --print-path)
|
||||
CURRENT_DIR=$(pwd)
|
||||
export PATH="${PLATFORM_PATH}/Developer/usr/bin:${DEVELOPER}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin"
|
||||
mkdir gmplib-"${PLATFORM}"-"${ARCH}"
|
||||
CFLAGS="-Wno-unused-value -fembed-bitcode -arch ${ARCH} --sysroot=${SDK} $(version_min_flag "$PLATFORM")"
|
||||
CONFIGURESCRIPT="gmp_configure_script.sh"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd gmp
|
||||
make clean || true
|
||||
make distclean || true
|
||||
echo "HOST: $HOST"
|
||||
echo "PREFIX: ${CURRENT_DIR}/gmplib-${PFX}"
|
||||
|
||||
cat >"$CONFIGURESCRIPT" << EOF
|
||||
#!/bin/sh
|
||||
./configure \
|
||||
CC="$CLANG" CFLAGS="$CFLAGS" CPPFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \
|
||||
--host=${HOST} --prefix="${CURRENT_DIR}/gmplib-${PFX}" \
|
||||
--disable-shared --enable-static --disable-assembly -v
|
||||
EOF
|
||||
|
||||
chmod a+x "$CONFIGURESCRIPT"
|
||||
sh "$CONFIGURESCRIPT"
|
||||
rm "$CONFIGURESCRIPT"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
mkdir -p "${CURRENT_DIR}/log"
|
||||
# shellcheck disable=SC2039
|
||||
make -j "$LOGICALCPU_MAX" &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-build.log
|
||||
# shellcheck disable=SC2039
|
||||
make install &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-install.log
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # gmp
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # build
|
||||
}
|
||||
|
||||
build_relic_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=relic-"${PFX}"
|
||||
TOOLCHAIN=$(pwd)/ios.toolchain.cmake
|
||||
GMP_PFX=$(pwd)/gmplib-${PFX}
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
unset CC
|
||||
# shellcheck disable=SC2155
|
||||
export CC=$(xcrun --sdk "${PLATFORM}" --find clang)
|
||||
|
||||
WSIZE=0
|
||||
IOS_PLATFORM=""
|
||||
OPTIMIZATIONFLAGS=""
|
||||
DEPLOYMENT_TARGET=""
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
if [[ $ARCH = "arm64" ]] || [[ $ARCH = "arm64e" ]]; then
|
||||
IOS_PLATFORM=OS64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
else
|
||||
IOS_PLATFORM=OS
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
if [[ $ARCH = "x86_64" ]]; then
|
||||
IOS_PLATFORM=SIMULATOR64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $ARCH = "arm64" ]]; then
|
||||
IOS_PLATFORM=SIMULATORARM64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
else
|
||||
IOS_PLATFORM=SIMULATOR
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
IOS_PLATFORM=WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
IOS_PLATFORM=TVOS
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_TVOS
|
||||
#TODO
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=OS64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
WSIZE=64
|
||||
IOS_PLATFORM=MAC
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=MAC_ARM64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_MACOS
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
fi
|
||||
|
||||
COMPILER_ARGS="$(version_min_flag "$PLATFORM") -Wno-unused-functions"
|
||||
|
||||
EXTRA_ARGS="-DOPSYS=NONE -DPLATFORM=$IOS_PLATFORM -DDEPLOYMENT_TARGET=$DEPLOYMENT_TARGET -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
if [[ $ARCH = "i386" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X86"
|
||||
elif [[ $ARCH = "x86_64" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X64"
|
||||
else
|
||||
EXTRA_ARGS+=" -DARCH=ARM"
|
||||
if [[ $ARCH = "armv7s" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
|
||||
elif [[ $ARCH = "armv7k" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
|
||||
elif [[ $ARCH = "arm64_32" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
|
||||
fi
|
||||
fi
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
cmake -DCMAKE_PREFIX_PATH:PATH="${GMP_PFX}" -DTESTS=0 -DBENCH=0 -DBUILD_BLS_JS_BINDINGS=0 -DBUILD_BLS_PYTHON_BINDINGS=0 \
|
||||
-DBUILD_BLS_BENCHMARKS=0 -DBUILD_BLS_TESTS=0 -DCHECK=off -DARITH=gmp -DTIMER=HPROC -DFP_PRIME=381 -DMULTI=PTHREAD \
|
||||
-DFP_QNRES=on -DFP_METHD="INTEG;INTEG;INTEG;MONTY;EXGCD;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" \
|
||||
-DCOMP_FLAGS="-pipe -std=c99 -O3 -funroll-loops $OPTIMIZATIONFLAGS -isysroot $SDK -arch $ARCH -fembed-bitcode ${COMPILER_ARGS}" \
|
||||
-DWSIZE=$WSIZE -DVERBS=off -DSHLIB=off -DALLOC="AUTO" -DEP_PLAIN=off -DEP_SUPER=off -DPP_EXT="LAZYR" \
|
||||
-DWITH="DV;BN;MD;FP;EP;FPX;EPX;PP;PC;CP" -DBN_METHD="COMBA;COMBA;MONTY;SLIDE;STEIN;BASIC" ${EXTRA_ARGS} ../../
|
||||
|
||||
make -j "$LOGICALCPU_MAX"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib/relic
|
||||
}
|
||||
|
||||
build_bls_arch() {
|
||||
# shellcheck disable=SC2039
|
||||
BLS_FILES=( "bls" "chaincode" "elements" "extendedprivatekey" "extendedpublickey" "legacy" "privatekey" "schemes" "threshold" )
|
||||
# shellcheck disable=SC2039
|
||||
ALL_BLS_OBJ_FILES=$(printf "%s.o " "${BLS_FILES[@]}")
|
||||
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=${BUILD}/bls-"${PFX}"
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
EXTRA_ARGS="$(version_min_flag "$PLATFORM")"
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
for F in "${BLS_FILES[@]}"
|
||||
do
|
||||
clang -I"../contrib/relic/include" \
|
||||
-I"../relic-${PFX}/_deps/relic-build/include" \
|
||||
-I"../../src/" \
|
||||
-I"../gmplib-${PFX}/include" \
|
||||
-x c++ -std=c++14 -stdlib=libc++ -fembed-bitcode -arch "${ARCH}" -isysroot "${SDK}" "${EXTRA_ARGS}" \
|
||||
-c "../../src/${F}.cpp" -o "${F}.o"
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
xcrun -sdk "$PLATFORM" ar -cvq libbls.a $ALL_BLS_OBJ_FILES
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
}
|
||||
|
||||
build_all_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
build_gmp_arch "$PLATFORM" "$ARCH"
|
||||
build_relic_arch "$PLATFORM" "$ARCH"
|
||||
build_bls_arch "$PLATFORM" "$ARCH"
|
||||
}
|
||||
|
||||
build_all() {
|
||||
BUILD_IN=$1
|
||||
TARGET_DIR=build/artefacts
|
||||
# shellcheck disable=SC2039
|
||||
IFS='|' read -ra BUILD_PAIRS <<< "$BUILD_IN"
|
||||
# shellcheck disable=SC2039
|
||||
for BUILD_PAIR in "${BUILD_PAIRS[@]}"
|
||||
do
|
||||
# shellcheck disable=SC2039
|
||||
IFS=';' read -ra PARSED_PAIR <<< "$BUILD_PAIR"
|
||||
# shellcheck disable=SC2039
|
||||
PLATFORM=${PARSED_PAIR[0]}
|
||||
# shellcheck disable=SC2039
|
||||
ARCH=${PARSED_PAIR[1]}
|
||||
|
||||
GMP_LIPOARGS=""
|
||||
RELIC_LIPOARGS=""
|
||||
BLS_LIPOARGS=""
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
local NEED_LIPO=0
|
||||
# shellcheck disable=SC2039
|
||||
IFS='+' read -ra ARCHS <<< "$ARCH"
|
||||
# shellcheck disable=SC2039
|
||||
for i in "${!ARCHS[@]}"
|
||||
do
|
||||
# shellcheck disable=SC2039
|
||||
local SINGLEARCH=${ARCHS[i]}
|
||||
|
||||
# build for every platform+arch
|
||||
build_all_arch "$PLATFORM" "$SINGLEARCH"
|
||||
|
||||
PFX="${PLATFORM}"-"${SINGLEARCH}"
|
||||
ARCH_TARGET_DIR=${TARGET_DIR}/${PFX}
|
||||
rm -rf "${ARCH_TARGET_DIR}"
|
||||
mkdir -p "${ARCH_TARGET_DIR}"
|
||||
#mv "${BUILD}/gmplib-${PFX}/lib/libgmp.a" "${ARCH_TARGET_DIR}/libgmp.a"
|
||||
#mv "${BUILD}/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" "${ARCH_TARGET_DIR}/librelic.a"
|
||||
#mv "${BUILD}/bls-${PFX}/libbls.a" "${ARCH_TARGET_DIR}/libbls.a"
|
||||
|
||||
libtool -static -o "${ARCH_TARGET_DIR}/libbls.a" \
|
||||
"${BUILD}/gmplib-${PFX}/lib/libgmp.a" \
|
||||
"${BUILD}/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" \
|
||||
"${BUILD}/bls-${PFX}/libbls.a"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
GMP_LIPOARGS+="${ARCH_TARGET_DIR}/libgmp.a "
|
||||
# shellcheck disable=SC2039
|
||||
RELIC_LIPOARGS+="${ARCH_TARGET_DIR}/librelic.a "
|
||||
# shellcheck disable=SC2039
|
||||
BLS_LIPOARGS+="${ARCH_TARGET_DIR}/libbls.a "
|
||||
|
||||
NEED_LIPO=i
|
||||
done
|
||||
|
||||
# Do lipo if we need https://developer.apple.com/forums/thread/666335?answerId=645963022#645963022
|
||||
# if [[ $NEED_LIPO -gt 0 ]]
|
||||
# then
|
||||
# FAT_TARGET_DIR=${TARGET_DIR}/${PLATFORM}-fat
|
||||
# rm -rf "${FAT_TARGET_DIR}"
|
||||
# mkdir -p "${FAT_TARGET_DIR}"
|
||||
# # shellcheck disable=SC2086
|
||||
# xcrun lipo $GMP_LIPOARGS -create -output "${FAT_TARGET_DIR}/libgmp.a"
|
||||
# # shellcheck disable=SC2086
|
||||
# xcrun lipo $RELIC_LIPOARGS -create -output "${FAT_TARGET_DIR}/librelic.a"
|
||||
# # shellcheck disable=SC2086
|
||||
# xcrun lipo $BLS_LIPOARGS -create -output "${FAT_TARGET_DIR}/libbls.a"
|
||||
# libtool -static -o "${FAT_TARGET_DIR}/libbls_combined.a" "${FAT_TARGET_DIR}/libgmp.a" "${FAT_TARGET_DIR}/librelic.a" "${FAT_TARGET_DIR}/libbls.a"
|
||||
# rm "${FAT_TARGET_DIR}/libgmp.a"
|
||||
# rm "${FAT_TARGET_DIR}/librelic.a"
|
||||
# rm "${FAT_TARGET_DIR}/libbls.a"
|
||||
# mv "${FAT_TARGET_DIR}/libbls_combined.a" "${FAT_TARGET_DIR}/libbls.a"
|
||||
# # clean up
|
||||
# # shellcheck disable=SC2039
|
||||
# for i in "${!ARCHS[@]}"
|
||||
# do
|
||||
# local SINGLEARCH=${ARCHS[i]}
|
||||
# rm -rf "${TARGET_DIR}-${SINGLEARCH}"
|
||||
# done
|
||||
# fi
|
||||
done
|
||||
}
|
||||
|
||||
#make_relic_headers_universal() {
|
||||
# RELIC_TARGET_DIR=relic-iphoneos-arm64
|
||||
# perl -p -e 's/#define WSIZE.*/#ifdef __LP64__\n#define WSIZE 64\n#else\n#define WSIZE 32\n#endif/' \
|
||||
# "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h" \
|
||||
# > "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new"
|
||||
#
|
||||
# rm "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
|
||||
# mv "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new" "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
|
||||
#}
|
||||
|
||||
#copy_headers() {
|
||||
# mkdir build/artefacts/include
|
||||
# # Copy all headers we will need
|
||||
# cp -rf src/*.hpp build/artefacts/include
|
||||
# cp -rf build/gmp/include/gmp.h build/artefacts/include
|
||||
# cp -rf build/contrib/relic/include/*.h build/artefacts/include
|
||||
# cp -rf build/contrib/relic/include/low/*.h build/artefacts/include
|
||||
# cp -rf build/contrib/relic/relic-iphoneos-arm64/include/*.h build/artefacts/include
|
||||
# rm -rf build/artefacts/include/test-utils.hpp
|
||||
#}
|
||||
|
||||
#function make_fat_binary()
|
||||
#{
|
||||
# pushd artefacts
|
||||
#
|
||||
# XCFRAMEWORK_ARGS=""
|
||||
#
|
||||
# for dir in */; do
|
||||
# if [ -d "$dir" ]; then
|
||||
# if [[ "$dir" != "include/" ]]; then
|
||||
# libtool -static -o "${dir}libbls_combined.a" "${dir}libgmp.a" "${dir}librelic.a" "${dir}libbls.a"
|
||||
#
|
||||
# XCFRAMEWORK_ARGS+="-library ${dir}libbls_combined.a -headers include "
|
||||
# fi
|
||||
# fi
|
||||
# done
|
||||
#
|
||||
# #xcodebuild -create-xcframework $XCFRAMEWORK_ARGS -output "libbls.xcframework"
|
||||
#}
|
||||
|
||||
prepare
|
||||
build_all "${MACOS};x86_64+arm64"
|
||||
build_all "${IPHONEOS};arm64|${IPHONESIMULATOR};arm64+x86_64"
|
||||
|
||||
#make_relic_headers_universal
|
||||
#copy_headers
|
||||
#make_fat_binary
|
404
src/dashbls/apple.rust.single.sh
Executable file
404
src/dashbls/apple.rust.single.sh
Executable file
@ -0,0 +1,404 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
# "x86_64-apple-ios"
|
||||
# "x86_64-apple-ios-sim"
|
||||
# "aarch64-apple-ios"
|
||||
# "aarch64-apple-ios-sim"
|
||||
# "x86_64-apple-darwin"
|
||||
# "aarch64-apple-darwin"
|
||||
# TODO: it's probably needs to be optimized in order to increase better build velocity
|
||||
# TODO: so we need to combine multiple targets
|
||||
TARGET=$1
|
||||
git submodule update --init
|
||||
MIN_IOS="13.0"
|
||||
MIN_WATCHOS="5.0"
|
||||
MIN_TVOS=$MIN_IOS
|
||||
MIN_MACOS="10.15"
|
||||
|
||||
IPHONEOS=iphoneos
|
||||
IPHONESIMULATOR=iphonesimulator
|
||||
WATCHOS=watchos
|
||||
WATCHSIMULATOR=watchsimulator
|
||||
TVOS=appletvos
|
||||
TVSIMULATOR=appletvsimulator
|
||||
MACOS=macosx
|
||||
|
||||
LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max)
|
||||
BUILD=build
|
||||
|
||||
version_min_flag() {
|
||||
PLATFORM=$1
|
||||
FLAG=""
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
FLAG="-miphoneos-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
FLAG="-mios-simulator-version-min=${MIN_IOS}"
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
FLAG="-mwatchos-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
FLAG="-mwatchos-simulator-version-min=${MIN_WATCHOS}"
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
FLAG="-mtvos-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
FLAG="-mtvos-simulator-version-min=${MIN_TVOS}"
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
FLAG="-mmacosx-version-min=${MIN_MACOS}"
|
||||
fi
|
||||
echo $FLAG
|
||||
}
|
||||
|
||||
|
||||
prepare() {
|
||||
download_gmp() {
|
||||
GMP_VERSION="6.2.1"
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
mkdir -p "contrib"
|
||||
if [ ! -s "contrib/gmp-${GMP_VERSION}.tar.bz2" ]; then
|
||||
curl -L -o "contrib/gmp-${GMP_VERSION}.tar.bz2" https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.bz2
|
||||
fi
|
||||
rm -rf "contrib/gmp"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
tar xfj "gmp-${GMP_VERSION}.tar.bz2"
|
||||
mv gmp-${GMP_VERSION} gmp
|
||||
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
|
||||
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #build
|
||||
}
|
||||
|
||||
download_cmake_toolchain() {
|
||||
if [ ! -s "${BUILD}/ios.toolchain.cmake" ]; then
|
||||
SHA256_HASH="d02857ff6bd64f1d7109ca59c3e4f3b2f89d0663c412146e6977c679801b3243"
|
||||
curl -o "${BUILD}/ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake
|
||||
DOWNLOADED_HASH=$(shasum -a 256 ${BUILD}/ios.toolchain.cmake | cut -f 1 -d " ")
|
||||
if [ $SHA256_HASH != "$DOWNLOADED_HASH" ]; then
|
||||
echo "Error: sha256 checksum of ios.toolchain.cmake mismatch" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
download_relic() {
|
||||
CURRENT_DIR=$(pwd)
|
||||
echo "$CURRENT_DIR"
|
||||
mkdir -p "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "${CURRENT_DIR}/${BUILD}/contrib"
|
||||
git clone --depth 1 --branch "feat/ios-support" https://github.com/pankcuf/relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd relic
|
||||
git fetch --depth 1 origin 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
git checkout 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #relic
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd #contrib
|
||||
fi
|
||||
}
|
||||
rm -rf ${BUILD}
|
||||
mkdir -p ${BUILD}
|
||||
download_relic
|
||||
download_gmp
|
||||
download_cmake_toolchain
|
||||
}
|
||||
|
||||
build_gmp_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
# why this works with this host only?
|
||||
HOST=arm-apple-darwin
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
PLATFORM_PATH=$(xcrun --sdk "$PLATFORM" --show-sdk-platform-path)
|
||||
CLANG=$(xcrun --sdk "$PLATFORM" --find clang)
|
||||
DEVELOPER=$(xcode-select --print-path)
|
||||
CURRENT_DIR=$(pwd)
|
||||
export PATH="${PLATFORM_PATH}/Developer/usr/bin:${DEVELOPER}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin"
|
||||
mkdir gmplib-"${PLATFORM}"-"${ARCH}"
|
||||
CFLAGS="-Wno-unused-value -fembed-bitcode -arch ${ARCH} --sysroot=${SDK} $(version_min_flag "$PLATFORM")"
|
||||
CONFIGURESCRIPT="gmp_configure_script.sh"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd gmp
|
||||
make clean || true
|
||||
make distclean || true
|
||||
echo "HOST: $HOST"
|
||||
echo "PREFIX: ${CURRENT_DIR}/gmplib-${PFX}"
|
||||
|
||||
cat >"$CONFIGURESCRIPT" << EOF
|
||||
#!/bin/sh
|
||||
./configure \
|
||||
CC="$CLANG" CFLAGS="$CFLAGS" CPPFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \
|
||||
--host=${HOST} --prefix="${CURRENT_DIR}/gmplib-${PFX}" \
|
||||
--disable-shared --enable-static --disable-assembly -v
|
||||
EOF
|
||||
|
||||
chmod a+x "$CONFIGURESCRIPT"
|
||||
sh "$CONFIGURESCRIPT"
|
||||
rm "$CONFIGURESCRIPT"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
mkdir -p "${CURRENT_DIR}/log"
|
||||
# shellcheck disable=SC2039
|
||||
make -j "$LOGICALCPU_MAX" &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-build.log
|
||||
# shellcheck disable=SC2039
|
||||
make install &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-install.log
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # gmp
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # build
|
||||
}
|
||||
|
||||
build_relic_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd ${BUILD}
|
||||
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=relic-"${PFX}"
|
||||
TOOLCHAIN=$(pwd)/ios.toolchain.cmake
|
||||
GMP_PFX=$(pwd)/gmplib-${PFX}
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
unset CC
|
||||
# shellcheck disable=SC2155
|
||||
export CC=$(xcrun --sdk "${PLATFORM}" --find clang)
|
||||
|
||||
WSIZE=0
|
||||
IOS_PLATFORM=""
|
||||
OPTIMIZATIONFLAGS=""
|
||||
DEPLOYMENT_TARGET=""
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
# shellcheck disable=SC2053
|
||||
if [[ $PLATFORM = $IPHONEOS ]]; then
|
||||
if [[ $ARCH = "arm64" ]] || [[ $ARCH = "arm64e" ]]; then
|
||||
IOS_PLATFORM=OS64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
else
|
||||
IOS_PLATFORM=OS
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then
|
||||
if [[ $ARCH = "x86_64" ]]; then
|
||||
IOS_PLATFORM=SIMULATOR64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $ARCH = "arm64" ]]; then
|
||||
IOS_PLATFORM=SIMULATORARM64
|
||||
DEPLOYMENT_TARGET=$MIN_IOS
|
||||
WSIZE=64
|
||||
else
|
||||
IOS_PLATFORM=SIMULATOR
|
||||
WSIZE=32
|
||||
fi
|
||||
elif [[ $PLATFORM = $WATCHOS ]]; then
|
||||
IOS_PLATFORM=WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_WATCHOS
|
||||
DEPLOYMENT_TARGET=$MIN_WATCHOS
|
||||
WSIZE=32
|
||||
elif [[ $PLATFORM = $TVOS ]]; then
|
||||
IOS_PLATFORM=TVOS
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $TVSIMULATOR ]]; then
|
||||
IOS_PLATFORM=SIMULATOR_TVOS
|
||||
#TODO
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=OS64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_TVOS
|
||||
WSIZE=64
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
elif [[ $PLATFORM = $MACOS ]]; then
|
||||
WSIZE=64
|
||||
IOS_PLATFORM=MAC
|
||||
if [[ $ARCH = "arm64" ]]
|
||||
then
|
||||
IOS_PLATFORM=MAC_ARM64
|
||||
fi
|
||||
DEPLOYMENT_TARGET=$MIN_MACOS
|
||||
OPTIMIZATIONFLAGS=-fomit-frame-pointer
|
||||
fi
|
||||
|
||||
COMPILER_ARGS="$(version_min_flag "$PLATFORM") -Wno-unused-functions"
|
||||
|
||||
EXTRA_ARGS="-DOPSYS=NONE -DPLATFORM=$IOS_PLATFORM -DDEPLOYMENT_TARGET=$DEPLOYMENT_TARGET -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN"
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
if [[ $ARCH = "i386" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X86"
|
||||
elif [[ $ARCH = "x86_64" ]]; then
|
||||
EXTRA_ARGS+=" -DARCH=X64"
|
||||
else
|
||||
EXTRA_ARGS+=" -DARCH=ARM"
|
||||
if [[ $ARCH = "armv7s" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
|
||||
elif [[ $ARCH = "armv7k" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
|
||||
elif [[ $ARCH = "arm64_32" ]]; then
|
||||
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
|
||||
fi
|
||||
fi
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
cmake -DCMAKE_PREFIX_PATH:PATH="${GMP_PFX}" -DTESTS=0 -DBENCH=0 -DBUILD_BLS_JS_BINDINGS=0 -DBUILD_BLS_PYTHON_BINDINGS=0 \
|
||||
-DBUILD_BLS_BENCHMARKS=0 -DBUILD_BLS_TESTS=0 -DCHECK=off -DARITH=gmp -DTIMER=HPROC -DFP_PRIME=381 -DMULTI=PTHREAD \
|
||||
-DFP_QNRES=on -DFP_METHD="INTEG;INTEG;INTEG;MONTY;EXGCD;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" \
|
||||
-DCOMP_FLAGS="-pipe -std=c99 -O3 -funroll-loops $OPTIMIZATIONFLAGS -isysroot $SDK -arch $ARCH -fembed-bitcode ${COMPILER_ARGS}" \
|
||||
-DWSIZE=$WSIZE -DVERBS=off -DSHLIB=off -DALLOC="AUTO" -DEP_PLAIN=off -DEP_SUPER=off -DPP_EXT="LAZYR" \
|
||||
-DWITH="DV;BN;MD;FP;EP;FPX;EPX;PP;PC;CP" -DBN_METHD="COMBA;COMBA;MONTY;SLIDE;STEIN;BASIC" ${EXTRA_ARGS} ../../
|
||||
|
||||
make -j "$LOGICALCPU_MAX"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # contrib/relic
|
||||
}
|
||||
|
||||
build_bls_arch() {
|
||||
# shellcheck disable=SC2039
|
||||
BLS_FILES=( "bls" "chaincode" "elements" "extendedprivatekey" "extendedpublickey" "legacy" "privatekey" "schemes" "threshold" )
|
||||
# shellcheck disable=SC2039
|
||||
ALL_BLS_OBJ_FILES=$(printf "%s.o " "${BLS_FILES[@]}")
|
||||
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
PFX=${PLATFORM}-${ARCH}
|
||||
SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path)
|
||||
|
||||
BUILDDIR=${BUILD}/bls-"${PFX}"
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir "$BUILDDIR"
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
pushd "$BUILDDIR"
|
||||
|
||||
EXTRA_ARGS="$(version_min_flag "$PLATFORM")"
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
|
||||
# shellcheck disable=SC2039
|
||||
for F in "${BLS_FILES[@]}"
|
||||
do
|
||||
clang -I"../contrib/relic/include" \
|
||||
-I"../relic-${PFX}/_deps/relic-build/include" \
|
||||
-I"../../src/" \
|
||||
-I"../gmplib-${PFX}/include" \
|
||||
-x c++ -std=c++14 -stdlib=libc++ -fembed-bitcode -arch "${ARCH}" -isysroot "${SDK}" "${EXTRA_ARGS}" \
|
||||
-c "../../src/${F}.cpp" -o "${F}.o"
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
xcrun -sdk "$PLATFORM" ar -cvq libbls.a $ALL_BLS_OBJ_FILES
|
||||
|
||||
# shellcheck disable=SC2039,SC2164
|
||||
popd # "$BUILDDIR"
|
||||
}
|
||||
|
||||
build_all_arch() {
|
||||
PLATFORM=$1
|
||||
ARCH=$2
|
||||
build_gmp_arch "$PLATFORM" "$ARCH"
|
||||
build_relic_arch "$PLATFORM" "$ARCH"
|
||||
build_bls_arch "$PLATFORM" "$ARCH"
|
||||
}
|
||||
|
||||
build_target() {
|
||||
BUILD_IN=$1
|
||||
echo "Build target: $BUILD_IN"
|
||||
ARCH=""
|
||||
PLATFORM=""
|
||||
# shellcheck disable=SC2039
|
||||
if [[ $BUILD_IN = "x86_64-apple-ios" ]]; then
|
||||
ARCH=x86_64
|
||||
PLATFORM=$IPHONESIMULATOR
|
||||
elif [[ $BUILD_IN = "aarch64-apple-ios" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$IPHONEOS
|
||||
elif [[ $BUILD_IN = "aarch64-apple-ios-sim" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$IPHONESIMULATOR
|
||||
elif [[ $BUILD_IN = "x86_64-apple-darwin" ]]; then
|
||||
ARCH=x86_64
|
||||
PLATFORM=$MACOS
|
||||
elif [[ $BUILD_IN = "aarch64-apple-darwin" ]]; then
|
||||
ARCH=arm64
|
||||
PLATFORM=$MACOS
|
||||
fi
|
||||
build_all_arch "$PLATFORM" "$ARCH"
|
||||
PFX="${PLATFORM}"-"${ARCH}"
|
||||
rm -rf "build/artefacts/${BUILD_IN}"
|
||||
mkdir -p "build/artefacts/${BUILD_IN}/include"
|
||||
# libtool -static -o "build/artefacts/${BUILD_IN}/libbls.a" \
|
||||
# "build/gmplib-${PFX}/lib/libgmp.a" \
|
||||
# "build/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" \
|
||||
# "build/bls-${PFX}/libbls.a"
|
||||
cp "build/gmplib-${PFX}/lib/libgmp.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/relic-${PFX}/_deps/sodium-build/libsodium.a" "build/artefacts/${BUILD_IN}"
|
||||
cp "build/bls-${PFX}/libbls.a" "build/artefacts/${BUILD_IN}"
|
||||
cp -rf build/bls-"${PFX}"/*.o build/artefacts/"${BUILD_IN}"/include
|
||||
cp -rf src/*.hpp build/artefacts/"${BUILD_IN}"/include
|
||||
cp -rf build/gmplib-"${PFX}"/include/gmp.h build/artefacts/"${BUILD_IN}"/include
|
||||
cp -rf build/relic-"${PFX}"/_deps/relic-build/include/*.h build/artefacts/"${BUILD_IN}"/include
|
||||
}
|
||||
|
||||
#make_relic_headers_universal() {
|
||||
# RELIC_TARGET_DIR=relic-iphoneos-arm64
|
||||
# perl -p -e 's/#define WSIZE.*/#ifdef __LP64__\n#define WSIZE 64\n#else\n#define WSIZE 32\n#endif/' \
|
||||
# "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h" \
|
||||
# > "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new"
|
||||
#
|
||||
# rm "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
|
||||
# mv "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new" "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
|
||||
#}
|
||||
#
|
||||
#copy_headers() {
|
||||
## mkdir build/artefacts/include
|
||||
# # Copy all headers we will need
|
||||
# cp -rf src/*.hpp ${BUILD}/artefacts/include
|
||||
# cp -rf ${BUILD}/contrib/gmp/include/gmp.h ${BUILD}/artefacts/include
|
||||
# cp -rf ${BUILD}/contrib/relic/include/*.h ${BUILD}/artefacts/include
|
||||
# cp -rf ${BUILD}/contrib/relic/include/low/*.h ${BUILD}/artefacts/include
|
||||
# #cp -rf ${BUILD}/contrib/relic/relic-iphoneos-arm64/include/*.h ${BUILD}/artefacts/include
|
||||
# rm -rf ${BUILD}/artefacts/include/test-utils.hpp
|
||||
#}
|
||||
|
||||
prepare
|
||||
build_target "$TARGET"
|
||||
#copy_headers
|
||||
#build_all "${MACOS};x86_64+arm64"
|
||||
#build_all "${IPHONEOS};arm64|${IPHONESIMULATOR};arm64+x86_64"
|
||||
|
||||
#make_relic_headers_universal
|
||||
#copy_headers
|
||||
#make_fat_binary
|
@ -1,5 +1,5 @@
|
||||
AC_PREREQ([2.60])
|
||||
AC_INIT([libdashbls],[1.2.4])
|
||||
AC_INIT([libdashbls],[1.3.0])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([build-aux/m4])
|
||||
|
||||
@ -783,3 +783,4 @@ AC_OUTPUT
|
||||
|
||||
dnl Peplace conflict-prone PACKAGE-prefixed macros with DASHBLS
|
||||
sed -i.old 's/PACKAGE/DASHBLS/g' depends/relic/include/relic_conf.h
|
||||
sed -i.old 's/PACKAGE/DASHBLS/g' config.status
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
GTElement Pair(const G2Element &b) const;
|
||||
uint32_t GetFingerprint(bool fLegacy = false) const;
|
||||
std::vector<uint8_t> Serialize(bool fLegacy = false) const;
|
||||
G1Element Copy();
|
||||
|
||||
friend bool operator==(const G1Element &a, const G1Element &b);
|
||||
friend bool operator!=(const G1Element &a, const G1Element &b);
|
||||
@ -101,6 +102,7 @@ public:
|
||||
G2Element Negate() const;
|
||||
GTElement Pair(const G1Element &a) const;
|
||||
std::vector<uint8_t> Serialize(bool fLegacy = false) const;
|
||||
G2Element Copy();
|
||||
|
||||
friend bool operator==(G2Element const &a, G2Element const &b);
|
||||
friend bool operator!=(G2Element const &a, G2Element const &b);
|
||||
|
@ -39,6 +39,7 @@ class CoreMPL {
|
||||
public:
|
||||
CoreMPL() = delete;
|
||||
CoreMPL(const std::string& strId) : strCiphersuiteId(strId) {}
|
||||
virtual ~CoreMPL() {}
|
||||
// Generates a private key from a seed, similar to HD key generation
|
||||
// (hashes the seed), and reduces it mod the group order
|
||||
virtual PrivateKey KeyGen(const vector<uint8_t>& seed);
|
||||
@ -112,7 +113,7 @@ protected:
|
||||
bool fLegacy);
|
||||
};
|
||||
|
||||
class BasicSchemeMPL : public CoreMPL {
|
||||
class BasicSchemeMPL final : public CoreMPL {
|
||||
public:
|
||||
static const std::string CIPHERSUITE_ID;
|
||||
BasicSchemeMPL() : CoreMPL(BasicSchemeMPL::CIPHERSUITE_ID) {}
|
||||
@ -133,7 +134,7 @@ public:
|
||||
const G2Element& signature) override;
|
||||
};
|
||||
|
||||
class AugSchemeMPL : public CoreMPL {
|
||||
class AugSchemeMPL final : public CoreMPL {
|
||||
|
||||
public:
|
||||
static const std::string CIPHERSUITE_ID;
|
||||
@ -186,7 +187,7 @@ public:
|
||||
const G2Element& signature) override;
|
||||
};
|
||||
|
||||
class PopSchemeMPL : public CoreMPL {
|
||||
class PopSchemeMPL final : public CoreMPL {
|
||||
|
||||
public:
|
||||
static const std::string CIPHERSUITE_ID;
|
||||
@ -221,7 +222,7 @@ public:
|
||||
/**
|
||||
* This scheme reflects the Sign/Verify behaviour of older bls-signatures library versions (<0.1.29).
|
||||
*/
|
||||
class LegacySchemeMPL : public CoreMPL {
|
||||
class LegacySchemeMPL final : public CoreMPL {
|
||||
|
||||
public:
|
||||
LegacySchemeMPL() : CoreMPL(std::string{}) {}
|
||||
|
@ -34,5 +34,5 @@ foreach(file ${JS_BINDINGS_TESTS})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/${file} tests/${file} COPYONLY)
|
||||
endforeach()
|
||||
|
||||
set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1 -s NODEJS_CATCH_EXIT=1 -s NODEJS_CATCH_REJECTION=1")
|
||||
set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1")
|
||||
add_custom_command(TARGET blsjstmp POST_BUILD COMMAND npm run build:web)
|
||||
|
1
src/dashbls/js-bindings/blsjs.d.ts
vendored
1
src/dashbls/js-bindings/blsjs.d.ts
vendored
@ -21,6 +21,7 @@ export declare class BasicSchemeMPL {
|
||||
static deriveChildSk(sk: PrivateKey, index: number): PrivateKey;
|
||||
static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey;
|
||||
static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element;
|
||||
static verifySecure(pk: G1Element, sig: G2Element, msg: Uint8Array): boolean;
|
||||
}
|
||||
|
||||
export declare class PopSchemeMPL {
|
||||
|
@ -42,7 +42,8 @@ EMSCRIPTEN_BINDINGS(blsjs) {
|
||||
.class_function("aggregateVerify", &SchemeMPLWrapper<BasicSchemeMPL>::AggregateVerify)
|
||||
.class_function("deriveChildSk", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSk)
|
||||
.class_function("deriveChildSkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSkUnhardened)
|
||||
.class_function("deriveChildPkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened);
|
||||
.class_function("deriveChildPkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened)
|
||||
.class_function("verifySecure", &SchemeMPLWrapper<BasicSchemeMPL>::VerifySecure);
|
||||
|
||||
class_<PopSchemeMPLWrapper>("PopSchemeMPL")
|
||||
.class_function("skToG1", &PopSchemeMPLWrapper::SkToG1)
|
||||
|
@ -81,6 +81,15 @@ template <typename SchemeMPL> class SchemeMPLWrapper : public JSWrapper<SchemeMP
|
||||
return G1ElementWrapper(mpl.DeriveChildPkUnhardened(pk.GetWrappedInstance(), index));
|
||||
}
|
||||
|
||||
static bool VerifySecure(val pubkeyArray, const G2ElementWrapper &signature, val messageVal) {
|
||||
std::vector<G1Element> pubkeys = G1ElementWrapper::Unwrap
|
||||
(helpers::toVectorFromJSArray<G1ElementWrapper>(pubkeyArray));
|
||||
|
||||
std::vector <uint8_t> message = helpers::toVector(messageVal);
|
||||
|
||||
return mpl.VerifySecure(pubkeys, signature.GetWrappedInstance(), message);
|
||||
}
|
||||
|
||||
protected:
|
||||
static inline SchemeMPL mpl;
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ from bls12381 import h_eff, q
|
||||
from ec import JacobianPoint, default_ec_twist, eval_iso
|
||||
from fields import Fq, Fq2, roots_of_unity
|
||||
from hash_to_field import Hp2
|
||||
from typing import Union
|
||||
|
||||
|
||||
def sgn0(x: Fq2) -> int:
|
||||
@ -198,7 +199,7 @@ def iso3(P):
|
||||
#
|
||||
# map from Fq2 element(s) to point in G2 subgroup of Ell2
|
||||
#
|
||||
def opt_swu2_map(t: Fq2, t2: Fq2 = None) -> JacobianPoint:
|
||||
def opt_swu2_map(t: Fq2, t2: Union[Fq2, None] = None) -> JacobianPoint:
|
||||
Pp = iso3(osswu2_help(t))
|
||||
if t2 is not None:
|
||||
Pp2 = iso3(osswu2_help(t2))
|
||||
|
2
src/dashbls/rust-bindings/.gitignore
vendored
Normal file
2
src/dashbls/rust-bindings/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
Cargo.lock
|
||||
target
|
17
src/dashbls/rust-bindings/bls-dash-sys/.rustfmt.toml
Normal file
17
src/dashbls/rust-bindings/bls-dash-sys/.rustfmt.toml
Normal file
@ -0,0 +1,17 @@
|
||||
unstable_features = true
|
||||
|
||||
blank_lines_lower_bound = 0
|
||||
condense_wildcard_suffixes = true
|
||||
error_on_line_overflow = true
|
||||
error_on_unformatted = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
imports_granularity = "Crate"
|
||||
normalize_comments = true
|
||||
normalize_doc_attributes = true
|
||||
reorder_impl_items = true
|
||||
group_imports = "StdExternalCrate"
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
15
src/dashbls/rust-bindings/bls-dash-sys/Cargo.toml
Normal file
15
src/dashbls/rust-bindings/bls-dash-sys/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "bls-dash-sys"
|
||||
description = ""
|
||||
version = "1.2.5"
|
||||
build = "build.rs"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
apple = []
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
bindgen = "0.65.1"
|
||||
glob ="0.3"
|
435
src/dashbls/rust-bindings/bls-dash-sys/bindings.rs
Normal file
435
src/dashbls/rust-bindings/bls-dash-sys/bindings.rs
Normal file
@ -0,0 +1,435 @@
|
||||
pub type G1Element = *mut ::std::os::raw::c_void;
|
||||
pub type G2Element = *mut ::std::os::raw::c_void;
|
||||
pub type PrivateKey = *mut ::std::os::raw::c_void;
|
||||
pub type CoreMPL = *mut ::std::os::raw::c_void;
|
||||
pub type BasicSchemeMPL = CoreMPL;
|
||||
pub type AugSchemeMPL = CoreMPL;
|
||||
pub type PopSchemeMPL = CoreMPL;
|
||||
pub type LegacySchemeMPL = CoreMPL;
|
||||
pub type BIP32ExtendedPrivateKey = *mut ::std::os::raw::c_void;
|
||||
pub type BIP32ExtendedPublicKey = *mut ::std::os::raw::c_void;
|
||||
pub type BIP32ChainCode = *mut ::std::os::raw::c_void;
|
||||
|
||||
extern "C" {
|
||||
pub fn G1ElementSize() -> ::std::os::raw::c_int;
|
||||
|
||||
pub fn G1ElementFromBytes(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
legacy: bool,
|
||||
didErr: *mut bool,
|
||||
) -> G1Element;
|
||||
|
||||
pub fn G1ElementGenerator() -> G1Element;
|
||||
|
||||
pub fn G1ElementIsValid(el: G1Element) -> bool;
|
||||
|
||||
pub fn G1ElementGetFingerprint(el: G1Element, legacy: bool) -> u32;
|
||||
|
||||
pub fn G1ElementIsEqual(el1: G1Element, el2: G1Element) -> bool;
|
||||
|
||||
pub fn G1ElementAdd(el1: G1Element, el2: G1Element) -> G1Element;
|
||||
|
||||
pub fn G1ElementMul(el: G1Element, sk: PrivateKey) -> G1Element;
|
||||
|
||||
pub fn G1ElementNegate(el: G1Element) -> G1Element;
|
||||
|
||||
pub fn G1ElementCopy(el: G1Element) -> G1Element;
|
||||
|
||||
pub fn G1ElementSerialize(el: G1Element, legacy: bool) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn G1ElementFree(el: G1Element);
|
||||
|
||||
pub fn G2ElementSize() -> ::std::os::raw::c_int;
|
||||
|
||||
pub fn G2ElementFromBytes(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
legacy: bool,
|
||||
didErr: *mut bool,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn G2ElementGenerator() -> G2Element;
|
||||
|
||||
pub fn G2ElementIsValid(el: G2Element) -> bool;
|
||||
|
||||
pub fn G2ElementIsEqual(el1: G2Element, el2: G2Element) -> bool;
|
||||
|
||||
pub fn G2ElementAdd(el1: G2Element, el2: G2Element) -> G2Element;
|
||||
|
||||
pub fn G2ElementMul(el: G2Element, sk: PrivateKey) -> G2Element;
|
||||
|
||||
pub fn G2ElementNegate(el: G2Element) -> G2Element;
|
||||
|
||||
pub fn G2ElementCopy(el: G2Element) -> G2Element;
|
||||
|
||||
pub fn G2ElementSerialize(el: G2Element, legacy: bool) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn G2ElementFree(el: G2Element);
|
||||
|
||||
pub fn PrivateKeyFromBytes(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
modOrder: bool,
|
||||
didErr: *mut bool,
|
||||
) -> PrivateKey;
|
||||
|
||||
pub fn PrivateKeyFromSeedBIP32(data: *const ::std::os::raw::c_void, len: usize) -> PrivateKey;
|
||||
|
||||
pub fn PrivateKeyAggregate(sks: *mut *mut ::std::os::raw::c_void, len: usize) -> PrivateKey;
|
||||
|
||||
pub fn PrivateKeyGetG1Element(sk: PrivateKey, didErr: *mut bool) -> G1Element;
|
||||
|
||||
pub fn PrivateKeyGetG2Element(sk: PrivateKey, didErr: *mut bool) -> G2Element;
|
||||
|
||||
pub fn PrivateKeyGetG2Power(sk: PrivateKey, el: G2Element) -> G2Element;
|
||||
|
||||
pub fn PrivateKeyIsEqual(sk1: PrivateKey, sk2: PrivateKey) -> bool;
|
||||
|
||||
pub fn PrivateKeySerialize(sk: PrivateKey) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn PrivateKeyFree(sk: PrivateKey);
|
||||
|
||||
pub fn PrivateKeySizeBytes() -> usize;
|
||||
|
||||
pub fn SecFree(p: *mut ::std::os::raw::c_void);
|
||||
|
||||
pub fn AllocPtrArray(len: usize) -> *mut *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn SetPtrArray(
|
||||
arrPtr: *mut *mut ::std::os::raw::c_void,
|
||||
elemPtr: *mut ::std::os::raw::c_void,
|
||||
index: ::std::os::raw::c_int,
|
||||
);
|
||||
|
||||
pub fn FreePtrArray(inPtr: *mut *mut ::std::os::raw::c_void);
|
||||
|
||||
pub fn GetPtrAtIndex(
|
||||
arrPtr: *mut *mut ::std::os::raw::c_void,
|
||||
index: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn SecAllocBytes(len: usize) -> *mut u8;
|
||||
|
||||
pub fn GetAddressAtIndex(
|
||||
ptr: *mut u8,
|
||||
index: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn GetLastErrorMsg() -> *const ::std::os::raw::c_char;
|
||||
|
||||
pub fn CoreMPLKeyGen(
|
||||
scheme: CoreMPL,
|
||||
seed: *const ::std::os::raw::c_void,
|
||||
seedLen: usize,
|
||||
didErr: *mut bool,
|
||||
) -> PrivateKey;
|
||||
|
||||
pub fn CoreMPLSkToG1(scheme: CoreMPL, sk: PrivateKey) -> G1Element;
|
||||
|
||||
pub fn CoreMPLSign(
|
||||
scheme: CoreMPL,
|
||||
sk: PrivateKey,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn CoreMPLVerify(
|
||||
scheme: BasicSchemeMPL,
|
||||
pk: G1Element,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn CoreMPLVerifySecure(
|
||||
scheme: CoreMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
sig: G2Element,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
) -> bool;
|
||||
|
||||
pub fn CoreMPLAggregatePubKeys(
|
||||
scheme: CoreMPL,
|
||||
pubKeys: *mut *mut ::std::os::raw::c_void,
|
||||
pkLen: usize,
|
||||
) -> G1Element;
|
||||
|
||||
pub fn CoreMPLAggregateSigs(
|
||||
scheme: CoreMPL,
|
||||
sigs: *mut *mut ::std::os::raw::c_void,
|
||||
sigLen: usize,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn CoreMPLDeriveChildSk(scheme: CoreMPL, sk: PrivateKey, index: u32) -> PrivateKey;
|
||||
|
||||
pub fn CoreMPLDeriveChildSkUnhardened(
|
||||
scheme: CoreMPL,
|
||||
sk: PrivateKey,
|
||||
index: u32,
|
||||
) -> PrivateKey;
|
||||
|
||||
pub fn CoreMPLDeriveChildPkUnhardened(scheme: CoreMPL, sk: G1Element, index: u32) -> G1Element;
|
||||
|
||||
pub fn CoreMPLAggregateVerify(
|
||||
scheme: CoreMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pkLen: usize,
|
||||
msgs: *mut *mut ::std::os::raw::c_void,
|
||||
msgLens: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn NewBasicSchemeMPL() -> BasicSchemeMPL;
|
||||
|
||||
pub fn BasicSchemeMPLAggregateVerify(
|
||||
scheme: BasicSchemeMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
msgs: *mut *mut ::std::os::raw::c_void,
|
||||
msgsLens: *const ::std::os::raw::c_void,
|
||||
msgsLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn BasicSchemeMPLFree(scheme: BasicSchemeMPL);
|
||||
|
||||
pub fn NewAugSchemeMPL() -> AugSchemeMPL;
|
||||
|
||||
pub fn AugSchemeMPLSign(
|
||||
scheme: AugSchemeMPL,
|
||||
sk: PrivateKey,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn AugSchemeMPLSignPrepend(
|
||||
scheme: AugSchemeMPL,
|
||||
sk: PrivateKey,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
prepPk: G1Element,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn AugSchemeMPLVerify(
|
||||
scheme: AugSchemeMPL,
|
||||
pk: G1Element,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn AugSchemeMPLAggregateVerify(
|
||||
scheme: AugSchemeMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
msgs: *mut *mut ::std::os::raw::c_void,
|
||||
msgsLens: *const ::std::os::raw::c_void,
|
||||
msgsLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn AugSchemeMPLFree(scheme: AugSchemeMPL);
|
||||
|
||||
pub fn NewPopSchemeMPL() -> PopSchemeMPL;
|
||||
|
||||
pub fn PopSchemeMPLPopProve(scheme: PopSchemeMPL, sk: PrivateKey) -> G2Element;
|
||||
|
||||
pub fn PopSchemeMPLPopVerify(scheme: PopSchemeMPL, pk: G1Element, sig: G2Element) -> bool;
|
||||
|
||||
pub fn PopSchemeMPLFastAggregateVerify(
|
||||
scheme: PopSchemeMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
msgs: *const ::std::os::raw::c_void,
|
||||
msgsLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn PopSchemeMPLFree(scheme: PopSchemeMPL);
|
||||
|
||||
pub fn NewLegacySchemeMPL() -> LegacySchemeMPL;
|
||||
|
||||
pub fn LegacySchemeMPLSign(
|
||||
scheme: LegacySchemeMPL,
|
||||
sk: PrivateKey,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn LegacySchemeMPLSignPrepend(
|
||||
scheme: LegacySchemeMPL,
|
||||
sk: PrivateKey,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
prepPk: G1Element,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn LegacySchemeMPLVerify(
|
||||
scheme: LegacySchemeMPL,
|
||||
pk: G1Element,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn LegacySchemeMPLVerifySecure(
|
||||
scheme: LegacySchemeMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
sig: G2Element,
|
||||
msg: *const ::std::os::raw::c_void,
|
||||
msgLen: usize,
|
||||
) -> bool;
|
||||
|
||||
pub fn LegacySchemeMPLAggregateVerify(
|
||||
scheme: LegacySchemeMPL,
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
msgs: *mut *mut ::std::os::raw::c_void,
|
||||
msgsLens: *const ::std::os::raw::c_void,
|
||||
msgsLen: usize,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn LegacySchemeMPLFree(scheme: LegacySchemeMPL);
|
||||
|
||||
pub fn ThresholdPrivateKeyShare(
|
||||
sks: *mut *mut ::std::os::raw::c_void,
|
||||
sksLen: usize,
|
||||
hash: *const ::std::os::raw::c_void,
|
||||
didErr: *mut bool,
|
||||
) -> PrivateKey;
|
||||
|
||||
pub fn ThresholdPrivateKeyRecover(
|
||||
sks: *mut *mut ::std::os::raw::c_void,
|
||||
sksLen: usize,
|
||||
hashes: *mut *mut ::std::os::raw::c_void,
|
||||
hashesLen: usize,
|
||||
didErr: *mut bool,
|
||||
) -> PrivateKey;
|
||||
|
||||
pub fn ThresholdPublicKeyShare(
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
hash: *const ::std::os::raw::c_void,
|
||||
didErr: *mut bool,
|
||||
) -> G1Element;
|
||||
|
||||
pub fn ThresholdPublicKeyRecover(
|
||||
pks: *mut *mut ::std::os::raw::c_void,
|
||||
pksLen: usize,
|
||||
hashes: *mut *mut ::std::os::raw::c_void,
|
||||
hashesLen: usize,
|
||||
didErr: *mut bool,
|
||||
) -> G1Element;
|
||||
|
||||
pub fn ThresholdSignatureShare(
|
||||
sigs: *mut *mut ::std::os::raw::c_void,
|
||||
sigsLen: usize,
|
||||
hash: *const ::std::os::raw::c_void,
|
||||
didErr: *mut bool,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn ThresholdSignatureRecover(
|
||||
sigs: *mut *mut ::std::os::raw::c_void,
|
||||
sigsLen: usize,
|
||||
hashes: *mut *mut ::std::os::raw::c_void,
|
||||
hashesLen: usize,
|
||||
didErr: *mut bool,
|
||||
) -> G2Element;
|
||||
|
||||
pub fn ThresholdSign(sk: PrivateKey, hash: *const ::std::os::raw::c_void) -> G2Element;
|
||||
|
||||
pub fn ThresholdVerify(
|
||||
pk: G1Element,
|
||||
hash: *const ::std::os::raw::c_void,
|
||||
sig: G2Element,
|
||||
) -> bool;
|
||||
|
||||
pub fn BIP32ChainCodeSerialize(cc: BIP32ChainCode) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ChainCodeIsEqual(cc1: BIP32ChainCode, cc2: BIP32ChainCode) -> bool;
|
||||
|
||||
pub fn BIP32ChainCodeFree(cc: BIP32ChainCode);
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyFromBytes(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
legacy: bool,
|
||||
didErr: *mut bool,
|
||||
) -> BIP32ExtendedPublicKey;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyPublicChild(
|
||||
pk: BIP32ExtendedPublicKey,
|
||||
index: u32,
|
||||
legacy: bool,
|
||||
) -> BIP32ExtendedPublicKey;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyGetChainCode(pk: BIP32ExtendedPublicKey) -> BIP32ChainCode;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeySerialize(
|
||||
pk: BIP32ExtendedPublicKey,
|
||||
legacy: bool,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyIsEqual(
|
||||
pk1: BIP32ExtendedPublicKey,
|
||||
pk2: BIP32ExtendedPublicKey,
|
||||
) -> bool;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyGetPublicKey(
|
||||
pk: BIP32ExtendedPublicKey,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ExtendedPublicKeyFree(pk: BIP32ExtendedPublicKey);
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyFromBytes(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
didErr: *mut bool,
|
||||
) -> BIP32ExtendedPrivateKey;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyFromSeed(
|
||||
data: *const ::std::os::raw::c_void,
|
||||
len: usize,
|
||||
didErr: *mut bool,
|
||||
) -> BIP32ExtendedPrivateKey;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyPrivateChild(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
index: u32,
|
||||
legacy: bool,
|
||||
) -> BIP32ExtendedPrivateKey;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyPublicChild(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
index: u32,
|
||||
) -> BIP32ExtendedPublicKey;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyGetChainCode(sk: BIP32ExtendedPrivateKey) -> BIP32ChainCode;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeySerialize(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyIsEqual(
|
||||
sk1: BIP32ExtendedPrivateKey,
|
||||
sk2: BIP32ExtendedPrivateKey,
|
||||
) -> bool;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyGetPrivateKey(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyGetExtendedPublicKey(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
legacy: bool,
|
||||
didErr: *mut bool,
|
||||
) -> BIP32ExtendedPublicKey;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyGetPublicKey(
|
||||
sk: BIP32ExtendedPrivateKey,
|
||||
didErr: *mut bool,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
|
||||
pub fn BIP32ExtendedPrivateKeyFree(sk: BIP32ExtendedPrivateKey);
|
||||
}
|
374
src/dashbls/rust-bindings/bls-dash-sys/build.rs
Normal file
374
src/dashbls/rust-bindings/bls-dash-sys/build.rs
Normal file
@ -0,0 +1,374 @@
|
||||
use std::{env, fs, io, io::Write, path::{Path, PathBuf}, process::{Command, Output}};
|
||||
|
||||
#[cfg(not(feature = "apple"))]
|
||||
fn create_cross_cmake_command() -> Command {
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
let mut command = if target_arch.eq("wasm32") {
|
||||
Command::new("emcmake")
|
||||
} else {
|
||||
Command::new("cmake")
|
||||
};
|
||||
|
||||
if target_arch.eq("wasm32") {
|
||||
command.arg("cmake");
|
||||
}
|
||||
|
||||
command
|
||||
}
|
||||
|
||||
fn handle_command_output(output: Output) {
|
||||
io::stdout()
|
||||
.write_all(&output.stdout)
|
||||
.expect("should write output");
|
||||
|
||||
io::stderr()
|
||||
.write_all(&output.stderr)
|
||||
.expect("should write output");
|
||||
|
||||
assert!(output.status.success());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "apple"))]
|
||||
fn main() {
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
// TODO: fix build for wasm32 on MacOS
|
||||
// errors with `error: linking with `rust-lld` failed: exit status: 1`
|
||||
if target_arch.eq("wasm32") {
|
||||
println!("Build for wasm32 is not fully supported");
|
||||
return;
|
||||
}
|
||||
|
||||
let root_path = Path::new("../..")
|
||||
.canonicalize()
|
||||
.expect("can't get abs path");
|
||||
|
||||
let bls_dash_build_path = root_path.join("build");
|
||||
let bls_dash_src_path = root_path.join("src");
|
||||
let c_bindings_path = root_path.join("rust-bindings/bls-dash-sys/c-bindings");
|
||||
|
||||
println!("root {}", root_path.display());
|
||||
println!("bls_dash_build_path {}", bls_dash_build_path.display());
|
||||
println!("bls_dash_src_path {}", bls_dash_src_path.display());
|
||||
// println!("c_bindings_path {}", c_bindings_path.display());
|
||||
|
||||
// Run cmake
|
||||
|
||||
println!("Run cmake:");
|
||||
|
||||
if bls_dash_build_path.exists() {
|
||||
fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
|
||||
}
|
||||
|
||||
fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
|
||||
|
||||
let cmake_output = create_cross_cmake_command()
|
||||
.current_dir(&bls_dash_build_path)
|
||||
.arg("-DBUILD_BLS_PYTHON_BINDINGS=0")
|
||||
.arg("-DBUILD_BLS_TESTS=0")
|
||||
.arg("-DBUILD_BLS_BENCHMARKS=0")
|
||||
.arg("-DBUILD_BLS_JS_BINDINGS=0")
|
||||
.arg("..")
|
||||
.output()
|
||||
.expect("can't run cmake");
|
||||
|
||||
handle_command_output(cmake_output);
|
||||
|
||||
// Build deps for bls-signatures
|
||||
|
||||
println!("Build dependencies:");
|
||||
|
||||
let build_output = Command::new("cmake")
|
||||
.args(["--build", ".", "--", "-j", "6"])
|
||||
.current_dir(&bls_dash_build_path)
|
||||
.output()
|
||||
.expect("can't build bls-signatures deps");
|
||||
|
||||
handle_command_output(build_output);
|
||||
|
||||
// Collect include paths
|
||||
let include_paths_file_path = bls_dash_build_path.join("include_paths.txt");
|
||||
|
||||
let include_paths =
|
||||
fs::read_to_string(include_paths_file_path).expect("should read include paths from file");
|
||||
|
||||
let mut include_paths: Vec<_> = include_paths
|
||||
.split(';')
|
||||
.filter(|path| !path.is_empty())
|
||||
.map(|path| PathBuf::from(path))
|
||||
.collect();
|
||||
|
||||
include_paths.extend([
|
||||
bls_dash_build_path.join("_deps/relic-src/include"),
|
||||
bls_dash_build_path.join("_deps/relic-build/include"),
|
||||
bls_dash_build_path.join("src"),
|
||||
root_path.join("include/dashbls"),
|
||||
bls_dash_build_path.join("depends/relic/include"),
|
||||
bls_dash_build_path.join("depends/mimalloc/include"),
|
||||
root_path.join("depends/relic/include"),
|
||||
root_path.join("depends/mimalloc/include"),
|
||||
bls_dash_src_path.clone(),
|
||||
]);
|
||||
|
||||
// Build c binding
|
||||
|
||||
println!("Build C binding:");
|
||||
|
||||
let mut cc = cc::Build::new();
|
||||
|
||||
let cpp_files_mask = c_bindings_path.join("**/*.cpp");
|
||||
|
||||
let cpp_files: Vec<_> = glob::glob(cpp_files_mask.to_str().unwrap())
|
||||
.expect("can't get list of cpp files")
|
||||
.filter_map(Result::ok)
|
||||
.collect();
|
||||
|
||||
cc.files(cpp_files)
|
||||
.includes(&include_paths)
|
||||
.cpp(true)
|
||||
.flag_if_supported("-std=c++14");
|
||||
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
// Fix homebrew LLVM installation issue
|
||||
if env::consts::OS == "macos" && target_arch == "wasm32" {
|
||||
cc.archiver("llvm-ar");
|
||||
}
|
||||
|
||||
if target_arch.eq("wasm32") {
|
||||
cc.flag_if_supported("-ffreestanding")
|
||||
.define("_LIBCPP_HAS_NO_THREADS", Some("1"));
|
||||
}
|
||||
|
||||
if !cfg!(debug_assertions) {
|
||||
cc.opt_level(2);
|
||||
}
|
||||
|
||||
cc.compile("bls-dash-sys");
|
||||
|
||||
// // Link dependencies
|
||||
// println!(
|
||||
// "cargo:rustc-link-search={}",
|
||||
// bls_dash_build_path.join("_deps/sodium-build").display()
|
||||
// );
|
||||
|
||||
// println!("cargo:rustc-link-lib=static=sodium");
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search={}",
|
||||
root_path.join("build/depends/relic/lib").display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib=static=relic_s");
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search={}",
|
||||
root_path.join("build/depends/mimalloc").display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib=static=mimalloc-secure");
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search={}",
|
||||
bls_dash_build_path.join("src").display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib=static=dashbls");
|
||||
|
||||
// Link GMP if exists
|
||||
let gmp_libraries_file_path = bls_dash_build_path.join("gmp_libraries.txt");
|
||||
|
||||
if gmp_libraries_file_path.exists() {
|
||||
let gmp_libraries_path = PathBuf::from(
|
||||
fs::read_to_string(gmp_libraries_file_path)
|
||||
.expect("should read gmp includes from file"),
|
||||
);
|
||||
|
||||
let gmp_libraries_parent_path = gmp_libraries_path
|
||||
.parent()
|
||||
.expect("can't get gmp libraries parent dir");
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search={}",
|
||||
gmp_libraries_parent_path.display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib=static=gmp");
|
||||
}
|
||||
|
||||
// Generate rust code for c binding to src/lib.rs
|
||||
// println!("Generate C binding for rust:");
|
||||
|
||||
// let mut builder = bindgen::Builder::default()
|
||||
// // .trust_clang_mangling(true)
|
||||
// // .wasm_import_module_name()
|
||||
// .size_t_is_usize(true)
|
||||
// .parse_callbacks(Box::new(bindgen::CargoCallbacks));
|
||||
|
||||
// let headers_to_process = [
|
||||
// "blschia.h",
|
||||
// "elements.h",
|
||||
// "privatekey.h",
|
||||
// "schemes.h",
|
||||
// "threshold.h",
|
||||
// "bip32/chaincode.h",
|
||||
// "bip32/extendedprivatekey.h",
|
||||
// "bip32/extendedpublickey.h",
|
||||
// ];
|
||||
|
||||
// for header in headers_to_process {
|
||||
// builder = builder.header(c_bindings_path.join(header).to_str().unwrap())
|
||||
// }
|
||||
|
||||
// if target_arch == "wasm32" {
|
||||
// builder = builder.clang_args(
|
||||
// include_paths
|
||||
// .iter()
|
||||
// .map(|path| format!("-I{}", path.display())),
|
||||
// );
|
||||
// }
|
||||
|
||||
// let bindings = builder.generate().expect("Unable to generate bindings");
|
||||
|
||||
// let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
|
||||
// bindings
|
||||
// .write_to_file(out_path.join("bindings.rs"))
|
||||
// .expect("couldn't write bindings");
|
||||
|
||||
// // Rerun build if files changed
|
||||
// println!("cargo:rerun-if-changed={}", c_bindings_path.display());
|
||||
println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
|
||||
}
|
||||
|
||||
// fn main() {
|
||||
// let target = env::var("TARGET").unwrap();
|
||||
// println!("Building bls-signatures for apple target: {}", target);
|
||||
// let root_path = Path::new("../..")
|
||||
// .canonicalize()
|
||||
// .expect("can't get abs path");
|
||||
// let bls_dash_build_path = root_path.join("build");
|
||||
// let bls_dash_src_path = root_path.join("src");
|
||||
// let artefacts_path = bls_dash_build_path.join("artefacts");
|
||||
// let target_path = artefacts_path.join(&target);
|
||||
// let script = root_path.join("apple.rust.single.sh");
|
||||
// if bls_dash_build_path.exists() {
|
||||
// fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
|
||||
// }
|
||||
// fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
|
||||
// let output = Command::new("sh")
|
||||
// .current_dir(&root_path)
|
||||
// .arg(script)
|
||||
// .arg(target)
|
||||
// .output()
|
||||
// .expect("Failed to execute the shell script");
|
||||
// handle_command_output(output);
|
||||
// let library_path = target_path.join("libbls.a");
|
||||
// if !fs::metadata(&library_path).is_ok() {
|
||||
// panic!("Library file not found: {}", library_path.display());
|
||||
// }
|
||||
// println!("cargo:rustc-link-search={}", target_path.display());
|
||||
// println!("cargo:rustc-link-lib=static=gmp");
|
||||
// println!("cargo:rustc-link-lib=static=sodium");
|
||||
// println!("cargo:rustc-link-lib=static=relic_s");
|
||||
// println!("cargo:rustc-link-search={}", bls_dash_build_path.join("src").display());
|
||||
// println!("cargo:rustc-link-lib=static=bls");
|
||||
// println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
|
||||
// }
|
||||
|
||||
#[cfg(feature = "apple")]
|
||||
fn main() {
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
// TODO: fix build for wasm32 on MacOS
|
||||
// errors with `error: linking with `rust-lld` failed: exit status: 1`
|
||||
if target_arch.eq("wasm32") {
|
||||
println!("Build for wasm32 is not fully supported");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
println!("Building bls-signatures for apple target: {}", target);
|
||||
let root_path = Path::new("../..")
|
||||
.canonicalize()
|
||||
.expect("can't get abs path");
|
||||
let bls_dash_build_path = root_path.join("build");
|
||||
let bls_dash_src_path = root_path.join("src");
|
||||
let bls_dash_src_include_path = root_path.join("include/dashbls");
|
||||
let c_bindings_path = root_path.join("rust-bindings/bls-dash-sys/c-bindings");
|
||||
let artefacts_path = bls_dash_build_path.join("artefacts");
|
||||
let target_path = artefacts_path.join(&target);
|
||||
let script = root_path.join("apple.rust.deps.sh");
|
||||
if bls_dash_build_path.exists() {
|
||||
fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
|
||||
}
|
||||
fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
|
||||
let output = Command::new("sh")
|
||||
.current_dir(&root_path)
|
||||
.arg(script)
|
||||
.arg(target.as_str())
|
||||
.output()
|
||||
.expect("Failed to execute the shell script");
|
||||
handle_command_output(output);
|
||||
let (arch, platform) = match target.as_str() {
|
||||
"x86_64-apple-ios" => ("x86_64", "iphonesimulator"),
|
||||
"aarch64-apple-ios" => ("arm64", "iphoneos"),
|
||||
"aarch64-apple-ios-sim" => ("arm64", "iphonesimulator"),
|
||||
"x86_64-apple-darwin" => ("x86_64", "macosx"),
|
||||
"aarch64-apple-darwin" => ("arm64", "macosx"),
|
||||
_ => panic!("Target {} not supported", target.as_str())
|
||||
};
|
||||
env::set_var("IPHONEOS_DEPLOYMENT_TARGET", "13.0");
|
||||
|
||||
// Collect include paths
|
||||
let include_paths_file_path = bls_dash_build_path.join("include_paths.txt");
|
||||
|
||||
let include_paths =
|
||||
fs::read_to_string(include_paths_file_path).expect("should read include paths from file");
|
||||
|
||||
let mut include_paths: Vec<_> = include_paths
|
||||
.split(';')
|
||||
.filter(|path| !path.is_empty())
|
||||
.map(|path| PathBuf::from(path))
|
||||
.collect();
|
||||
|
||||
include_paths.extend([
|
||||
bls_dash_build_path.join(format!("relic-{}-{}/_deps/relic-src/include", platform, arch)),
|
||||
bls_dash_build_path.join(format!("relic-{}-{}/_deps/relic-build/include", platform, arch)),
|
||||
bls_dash_build_path.join("contrib/relic/src"),
|
||||
root_path.join("src"),
|
||||
root_path.join("include/dashbls"),
|
||||
root_path.join("depends/relic/include"),
|
||||
root_path.join("depends/mimalloc/include"),
|
||||
root_path.join("depends/catch2/include"),
|
||||
bls_dash_src_path.clone(),
|
||||
bls_dash_src_include_path.clone()
|
||||
]);
|
||||
|
||||
let cpp_files: Vec<_> = glob::glob(c_bindings_path.join("**/*.cpp").to_str().unwrap())
|
||||
.expect("can't get list of cpp files")
|
||||
.filter_map(Result::ok)
|
||||
.collect();
|
||||
|
||||
let mut cc = cc::Build::new();
|
||||
cc.files(cpp_files)
|
||||
.includes(&include_paths)
|
||||
.cpp(true)
|
||||
.flag("-Wno-unused-parameter")
|
||||
.flag("-Wno-sign-compare")
|
||||
.flag("-Wno-delete-non-abstract-non-virtual-dtor")
|
||||
.flag("-std=c++14");
|
||||
|
||||
cc.compile("dashbls");
|
||||
|
||||
println!("cargo:rustc-link-search={}", target_path.display());
|
||||
println!("cargo:rustc-link-lib=static=gmp");
|
||||
// println!("cargo:rustc-link-lib=static=sodium");
|
||||
// println!("cargo:rustc-link-lib=static=relic_s");
|
||||
println!("cargo:rustc-link-lib=static=bls");
|
||||
println!("cargo:rustc-link-search={}", bls_dash_src_path.display());
|
||||
println!("cargo:rustc-link-lib=static=dashbls");
|
||||
println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#include <vector>
|
||||
#include "bls.hpp"
|
||||
#include "chaincode.h"
|
||||
|
||||
void* BIP32ChainCodeSerialize(const BIP32ChainCode cc)
|
||||
{
|
||||
const bls::ChainCode* ccPtr = (bls::ChainCode*)cc;
|
||||
const std::vector<uint8_t> serialized = ccPtr->Serialize();
|
||||
uint8_t* buffer = (uint8_t*)malloc(bls::ChainCode::SIZE);
|
||||
memcpy(buffer, serialized.data(), bls::ChainCode::SIZE);
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
bool BIP32ChainCodeIsEqual(const BIP32ChainCode cc1, const BIP32ChainCode cc2)
|
||||
{
|
||||
const bls::ChainCode* cc1Ptr = (bls::ChainCode*)cc1;
|
||||
const bls::ChainCode* cc2Ptr = (bls::ChainCode*)cc2;
|
||||
return *cc1Ptr == *cc2Ptr;
|
||||
}
|
||||
|
||||
void BIP32ChainCodeFree(const BIP32ChainCode cc)
|
||||
{
|
||||
const bls::ChainCode* ccPtr = (bls::ChainCode*)cc;
|
||||
delete ccPtr;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#ifndef BIP32CHAINCODE_H_
|
||||
#define BIP32CHAINCODE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* BIP32ChainCode;
|
||||
|
||||
void* BIP32ChainCodeSerialize(const BIP32ChainCode cc);
|
||||
bool BIP32ChainCodeIsEqual(const BIP32ChainCode cc1, const BIP32ChainCode cc2);
|
||||
void BIP32ChainCodeFree(const BIP32ChainCode cc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BIP32CHAINCODE_H_
|
@ -0,0 +1,128 @@
|
||||
#include "extendedprivatekey.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../blschia.h"
|
||||
#include "../error.h"
|
||||
#include "bls.hpp"
|
||||
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromBytes(const void* data, bool* didErr)
|
||||
{
|
||||
bls::ExtendedPrivateKey* el = nullptr;
|
||||
try {
|
||||
el = new bls::ExtendedPrivateKey(bls::ExtendedPrivateKey::FromBytes(
|
||||
bls::Bytes((uint8_t*)(data), bls::ExtendedPrivateKey::SIZE)));
|
||||
} catch (const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromSeed(const void* data, const size_t len, bool* didErr)
|
||||
{
|
||||
bls::ExtendedPrivateKey* el = nullptr;
|
||||
try {
|
||||
el = new bls::ExtendedPrivateKey(bls::ExtendedPrivateKey::FromSeed(
|
||||
bls::Bytes((uint8_t*)(data), len)));
|
||||
} catch (const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyPrivateChild(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const uint32_t index,
|
||||
const bool legacy)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
return new bls::ExtendedPrivateKey(skPtr->PrivateChild(index, legacy));
|
||||
}
|
||||
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyPublicChild(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const uint32_t index)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
return new bls::ExtendedPublicKey(skPtr->PublicChild(index));
|
||||
}
|
||||
|
||||
BIP32ChainCode BIP32ExtendedPrivateKeyGetChainCode(const BIP32ExtendedPrivateKey sk)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
return new bls::ChainCode(skPtr->GetChainCode());
|
||||
}
|
||||
|
||||
void* BIP32ExtendedPrivateKeySerialize(const BIP32ExtendedPrivateKey sk)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
uint8_t* buffer =
|
||||
bls::Util::SecAlloc<uint8_t>(bls::ExtendedPrivateKey::SIZE);
|
||||
skPtr->Serialize(buffer);
|
||||
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
bool BIP32ExtendedPrivateKeyIsEqual(
|
||||
const BIP32ExtendedPrivateKey sk1,
|
||||
const BIP32ExtendedPrivateKey sk2)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* sk1Ptr = (bls::ExtendedPrivateKey*)sk1;
|
||||
const bls::ExtendedPrivateKey* sk2Ptr = (bls::ExtendedPrivateKey*)sk2;
|
||||
return *sk1Ptr == *sk2Ptr;
|
||||
}
|
||||
|
||||
void* BIP32ExtendedPrivateKeyGetPrivateKey(const BIP32ExtendedPrivateKey sk)
|
||||
{
|
||||
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
return new bls::PrivateKey(skPtr->GetPrivateKey());
|
||||
}
|
||||
|
||||
void* BIP32ExtendedPrivateKeyGetPublicKey(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
bool* didErr)
|
||||
{
|
||||
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
bls::G1Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G1Element(skPtr->GetPublicKey());
|
||||
*didErr = false;
|
||||
} catch (const std::exception& ex) {
|
||||
// set err
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyGetExtendedPublicKey(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const bool legacy,
|
||||
bool* didErr)
|
||||
{
|
||||
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
bls::ExtendedPublicKey* pk = nullptr;
|
||||
try {
|
||||
pk = new bls::ExtendedPublicKey(skPtr->GetExtendedPublicKey(legacy));
|
||||
*didErr = false;
|
||||
} catch (const std::exception& ex) {
|
||||
// set err
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
return pk;
|
||||
}
|
||||
|
||||
void BIP32ExtendedPrivateKeyFree(const BIP32ExtendedPrivateKey sk)
|
||||
{
|
||||
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
|
||||
delete skPtr;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
#ifndef BIP32EXTENDEDPRIVATEKEY_H_
|
||||
#define BIP32EXTENDEDPRIVATEKEY_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "extendedpublickey.h"
|
||||
#include "chaincode.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* BIP32ExtendedPrivateKey;
|
||||
|
||||
// ExtendedPrivateKey
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromBytes(
|
||||
const void* data,
|
||||
bool* didErr);
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromSeed(const void* data, const size_t len, bool* didErr);
|
||||
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyPrivateChild(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const uint32_t index,
|
||||
const bool legacy);
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyPublicChild(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const uint32_t index);
|
||||
BIP32ChainCode BIP32ExtendedPrivateKeyGetChainCode(const BIP32ExtendedPrivateKey sk);
|
||||
void* BIP32ExtendedPrivateKeySerialize(const BIP32ExtendedPrivateKey sk);
|
||||
bool BIP32ExtendedPrivateKeyIsEqual(
|
||||
const BIP32ExtendedPrivateKey sk1,
|
||||
const BIP32ExtendedPrivateKey sk2);
|
||||
void* BIP32ExtendedPrivateKeyGetPrivateKey(const BIP32ExtendedPrivateKey sk);
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyGetExtendedPublicKey(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
const bool legacy,
|
||||
bool* didErr);
|
||||
void* BIP32ExtendedPrivateKeyGetPublicKey(
|
||||
const BIP32ExtendedPrivateKey sk,
|
||||
bool* didErr);
|
||||
void BIP32ExtendedPrivateKeyFree(const BIP32ExtendedPrivateKey sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BIP32EXTENDEDPRIVATEKEY_H_
|
@ -0,0 +1,72 @@
|
||||
#include "extendedpublickey.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../blschia.h"
|
||||
#include "../error.h"
|
||||
#include "bls.hpp"
|
||||
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyFromBytes(
|
||||
const void* data,
|
||||
const bool legacy,
|
||||
bool* didErr)
|
||||
{
|
||||
bls::ExtendedPublicKey* el = nullptr;
|
||||
try {
|
||||
el = new bls::ExtendedPublicKey(bls::ExtendedPublicKey::FromBytes(
|
||||
bls::Bytes((uint8_t*)(data), bls::ExtendedPublicKey::SIZE),
|
||||
legacy));
|
||||
} catch (const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyPublicChild(
|
||||
const BIP32ExtendedPublicKey pk,
|
||||
const uint32_t index,
|
||||
const bool legacy)
|
||||
{
|
||||
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
|
||||
return new bls::ExtendedPublicKey(pkPtr->PublicChild(index, legacy));
|
||||
}
|
||||
|
||||
BIP32ChainCode BIP32ExtendedPublicKeyGetChainCode(const BIP32ExtendedPublicKey pk)
|
||||
{
|
||||
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
|
||||
return new bls::ChainCode(pkPtr->GetChainCode());
|
||||
}
|
||||
|
||||
void* BIP32ExtendedPublicKeyGetPublicKey(const BIP32ExtendedPublicKey pk) {
|
||||
bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
|
||||
return new bls::G1Element(pkPtr->GetPublicKey());
|
||||
}
|
||||
|
||||
void* BIP32ExtendedPublicKeySerialize(
|
||||
const BIP32ExtendedPublicKey pk,
|
||||
const bool legacy)
|
||||
{
|
||||
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
|
||||
const std::vector<uint8_t> serialized = pkPtr->Serialize(legacy);
|
||||
uint8_t* buffer = (uint8_t*)malloc(bls::ExtendedPublicKey::SIZE);
|
||||
memcpy(buffer, serialized.data(), bls::ExtendedPublicKey::SIZE);
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
bool BIP32ExtendedPublicKeyIsEqual(
|
||||
const BIP32ExtendedPublicKey pk1,
|
||||
const BIP32ExtendedPublicKey pk2)
|
||||
{
|
||||
const bls::ExtendedPublicKey* pk1Ptr = (bls::ExtendedPublicKey*)pk1;
|
||||
const bls::ExtendedPublicKey* pk2Ptr = (bls::ExtendedPublicKey*)pk2;
|
||||
return *pk1Ptr == *pk2Ptr;
|
||||
}
|
||||
|
||||
void BIP32ExtendedPublicKeyFree(const BIP32ExtendedPublicKey pk)
|
||||
{
|
||||
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
|
||||
delete pkPtr;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
#ifndef BIP32EXTENDEDPUBLICKEY_H_
|
||||
#define BIP32EXTENDEDPUBLICKEY_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "chaincode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* BIP32ExtendedPublicKey;
|
||||
|
||||
// ExtendedPublicKey
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyFromBytes(
|
||||
const void* data,
|
||||
const bool legacy,
|
||||
bool* didErr);
|
||||
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyPublicChild(
|
||||
const BIP32ExtendedPublicKey pk,
|
||||
const uint32_t index,
|
||||
const bool legacy);
|
||||
BIP32ChainCode BIP32ExtendedPublicKeyGetChainCode(const BIP32ExtendedPublicKey pk);
|
||||
void* BIP32ExtendedPublicKeyGetPublicKey(const BIP32ExtendedPublicKey pk);
|
||||
void* BIP32ExtendedPublicKeySerialize(
|
||||
const BIP32ExtendedPublicKey pk,
|
||||
const bool legacy);
|
||||
bool BIP32ExtendedPublicKeyIsEqual(
|
||||
const BIP32ExtendedPublicKey pk1,
|
||||
const BIP32ExtendedPublicKey pk2);
|
||||
void BIP32ExtendedPublicKeyFree(const BIP32ExtendedPublicKey pk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BIP32EXTENDEDPUBLICKEY_H_
|
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include "bls.hpp"
|
||||
#include "error.h"
|
||||
#include "blschia.h"
|
||||
|
||||
// TODO: Revisit
|
||||
|
||||
std::string gErrMsg;
|
||||
|
||||
void SecFree(void *p) {
|
||||
bls::Util::SecFree(p);
|
||||
}
|
||||
|
||||
void** AllocPtrArray(size_t len) {
|
||||
// caller to free
|
||||
return (void**)bls::Util::SecAlloc<uint8_t>(sizeof(void*) * len);
|
||||
}
|
||||
|
||||
void SetPtrArray(void** arrPtr, void* elemPtr, int index) {
|
||||
arrPtr[index] = elemPtr;
|
||||
}
|
||||
|
||||
void FreePtrArray(void** inPtr) {
|
||||
bls::Util::SecFree(inPtr);
|
||||
}
|
||||
|
||||
void* GetPtrAtIndex(void** arrPtr, int index) {
|
||||
return arrPtr[index];
|
||||
}
|
||||
|
||||
uint8_t* SecAllocBytes(size_t len) {
|
||||
return (uint8_t*)bls::Util::SecAlloc<uint8_t>(sizeof(uint8_t) * len);
|
||||
}
|
||||
|
||||
void* GetAddressAtIndex(uint8_t* ptr, int index) {
|
||||
return (void*)&ptr[index];
|
||||
}
|
||||
|
||||
const char* GetLastErrorMsg() {
|
||||
return gErrMsg.c_str();
|
||||
}
|
46
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/blschia.h
Normal file
46
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/blschia.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BLSCHIA_H_
|
||||
#define BLSCHIA_H_
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "privatekey.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Export the BLS SecFree method
|
||||
void SecFree(void *p);
|
||||
|
||||
typedef void** carr;
|
||||
|
||||
// Additional C++ helper funcs for allocations
|
||||
void** AllocPtrArray(size_t len);
|
||||
void SetPtrArray(void **arrPtr, void *elemPtr, int index);
|
||||
void FreePtrArray(void **inPtr);
|
||||
void* GetPtrAtIndex(void **arrPtr, int index);
|
||||
|
||||
// Allocates an array of bytes with size of passed in len argument
|
||||
uint8_t* SecAllocBytes(size_t len);
|
||||
|
||||
void* GetAddressAtIndex(uint8_t *ptr, int index);
|
||||
|
||||
const char* GetLastErrorMsg();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BLSCHIA_H_
|
162
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/elements.cpp
Normal file
162
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/elements.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
#include "bls.hpp"
|
||||
#include "blschia.h"
|
||||
#include "error.h"
|
||||
#include "elements.h"
|
||||
|
||||
// G1Element
|
||||
int G1ElementSize() {
|
||||
return bls::G1Element::SIZE;
|
||||
}
|
||||
|
||||
G1Element G1ElementFromBytes(const void* data, bool legacy, bool* didErr) {
|
||||
bls::G1Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G1Element(
|
||||
bls::G1Element::FromBytes(bls::Bytes((uint8_t*)(data), bls::G1Element::SIZE), legacy)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
G1Element G1ElementGenerator() {
|
||||
return new bls::G1Element(bls::G1Element::Generator());
|
||||
}
|
||||
|
||||
bool G1ElementIsValid(const G1Element el) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
return elPtr->IsValid();
|
||||
}
|
||||
|
||||
uint32_t G1ElementGetFingerprint(const G1Element el, const bool legacy) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
return elPtr->GetFingerprint(legacy);
|
||||
}
|
||||
|
||||
void* G1ElementSerialize(const G1Element el, const bool legacy) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
const std::vector<uint8_t> serialized = elPtr->Serialize(legacy);
|
||||
uint8_t* buffer = (uint8_t*)malloc(bls::G1Element::SIZE);
|
||||
memcpy(buffer, serialized.data(), bls::G1Element::SIZE);
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
bool G1ElementIsEqual(const G1Element el1, const G1Element el2) {
|
||||
const bls::G1Element* el1Ptr = (bls::G1Element*)el1;
|
||||
const bls::G1Element* el2Ptr = (bls::G1Element*)el2;
|
||||
return *el1Ptr == *el2Ptr;
|
||||
}
|
||||
|
||||
G1Element G1ElementAdd(const G1Element el1, const G1Element el2) {
|
||||
const bls::G1Element* el1Ptr = (bls::G1Element*)el1;
|
||||
const bls::G1Element* el2Ptr = (bls::G1Element*)el2;
|
||||
return new bls::G1Element((*el1Ptr) + (*el2Ptr));
|
||||
}
|
||||
|
||||
G1Element G1ElementMul(const G1Element el, const PrivateKey sk) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G1Element(*elPtr * *skPtr);
|
||||
}
|
||||
|
||||
G1Element G1ElementNegate(const G1Element el) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
return new bls::G1Element(elPtr->Negate());
|
||||
}
|
||||
|
||||
G1Element G1ElementCopy(const G1Element el) {
|
||||
return new bls::G1Element(((bls::G1Element*)el)->Copy());
|
||||
}
|
||||
|
||||
void G1ElementFree(const G1Element el) {
|
||||
const bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
delete elPtr;
|
||||
}
|
||||
|
||||
// G2Element
|
||||
int G2ElementSize() {
|
||||
return bls::G2Element::SIZE;
|
||||
}
|
||||
|
||||
G2Element G2ElementFromBytes(const void* data, const bool legacy, bool* didErr) {
|
||||
bls::G2Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G2Element(
|
||||
bls::G2Element::FromBytes(bls::Bytes((uint8_t*)data, bls::G2Element::SIZE), legacy)
|
||||
);
|
||||
*didErr = false;
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element G2ElementGenerator() {
|
||||
return new bls::G2Element(bls::G2Element::Generator());
|
||||
}
|
||||
|
||||
bool G2ElementIsValid(const G2Element el) {
|
||||
const bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
return elPtr->IsValid();
|
||||
}
|
||||
|
||||
void* G2ElementSerialize(const G2Element el, const bool legacy) {
|
||||
const bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
const std::vector<uint8_t> serialized = elPtr->Serialize(legacy);
|
||||
uint8_t* buffer = (uint8_t*)malloc(bls::G2Element::SIZE);
|
||||
memcpy(buffer, serialized.data(), bls::G2Element::SIZE);
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
bool G2ElementIsEqual(const G2Element el1, const G2Element el2) {
|
||||
const bls::G2Element* el1Ptr = (bls::G2Element*)el1;
|
||||
const bls::G2Element* el2Ptr = (bls::G2Element*)el2;
|
||||
return *el1Ptr == *el2Ptr;
|
||||
}
|
||||
|
||||
G2Element G2ElementAdd(const G2Element el1, const G2Element el2) {
|
||||
bls::G2Element* el1Ptr = (bls::G2Element*)el1;
|
||||
bls::G2Element* el2Ptr = (bls::G2Element*)el2;
|
||||
return new bls::G2Element(*el1Ptr + *el2Ptr);
|
||||
}
|
||||
|
||||
G2Element G2ElementMul(const G2Element el, const PrivateKey sk) {
|
||||
const bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(*elPtr * *skPtr);
|
||||
}
|
||||
|
||||
G2Element G2ElementNegate(const G2Element el) {
|
||||
const bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
return new bls::G2Element(elPtr->Negate());
|
||||
}
|
||||
|
||||
G2Element G2ElementCopy(const G1Element el) {
|
||||
return new bls::G2Element(((bls::G2Element*)el)->Copy());
|
||||
}
|
||||
|
||||
void G2ElementFree(const G2Element el) {
|
||||
bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
delete elPtr;
|
||||
}
|
58
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/elements.h
Normal file
58
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/elements.h
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ELEMENTS_H_
|
||||
#define ELEMENTS_H_
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* G1Element;
|
||||
typedef void* G2Element;
|
||||
typedef void* PrivateKey;
|
||||
|
||||
// G1Element
|
||||
int G1ElementSize();
|
||||
G1Element G1ElementFromBytes(const void* data, const bool legacy, bool* didErr);
|
||||
G1Element G1ElementGenerator();
|
||||
bool G1ElementIsValid(const G1Element el);
|
||||
uint32_t G1ElementGetFingerprint(const G1Element el, const bool legacy);
|
||||
bool G1ElementIsEqual(const G1Element el1, const G1Element el2);
|
||||
G1Element G1ElementAdd(const G1Element el1, const G1Element el2);
|
||||
G1Element G1ElementMul(const G1Element el, const PrivateKey sk);
|
||||
G1Element G1ElementNegate(const G1Element el);
|
||||
G1Element G1ElementCopy(const G1Element el);
|
||||
void* G1ElementSerialize(const G1Element el, const bool legacy);
|
||||
void G1ElementFree(const G1Element el);
|
||||
|
||||
// G2Element
|
||||
int G2ElementSize();
|
||||
G2Element G2ElementFromBytes(const void* data, const bool legacy, bool* didErr);
|
||||
G2Element G2ElementGenerator();
|
||||
bool G2ElementIsValid(const G2Element el);
|
||||
bool G2ElementIsEqual(const G2Element el1, const G2Element el2);
|
||||
G2Element G2ElementAdd(const G2Element el1, const G2Element el2);
|
||||
G2Element G2ElementMul(const G2Element el, const PrivateKey sk);
|
||||
G2Element G2ElementNegate(const G2Element el);
|
||||
G2Element G2ElementCopy(const G2Element el);
|
||||
void* G2ElementSerialize(const G2Element el, const bool legacy);
|
||||
void G2ElementFree(const G2Element el);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // ELEMENTS_H_
|
21
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/error.h
Normal file
21
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/error.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2020 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ERROR_H_
|
||||
#define ERROR_H_
|
||||
#include <string>
|
||||
|
||||
extern std::string gErrMsg;
|
||||
|
||||
#endif // ERROR_H_
|
120
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/privatekey.cpp
Normal file
120
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/privatekey.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
#include "bls.hpp"
|
||||
#include "privatekey.h"
|
||||
#include "blschia.h"
|
||||
#include "error.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
// private key bindings implementation
|
||||
PrivateKey PrivateKeyFromBytes(const void* data, const bool modOrder, bool* didErr) {
|
||||
bls::PrivateKey* skPtr = nullptr;
|
||||
try {
|
||||
skPtr = new bls::PrivateKey(
|
||||
bls::PrivateKey::FromBytes(
|
||||
bls::Bytes((uint8_t*)data, bls::PrivateKey::PRIVATE_KEY_SIZE),
|
||||
modOrder
|
||||
)
|
||||
);
|
||||
} catch (const std::exception& ex) {
|
||||
// set err
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return skPtr;
|
||||
}
|
||||
|
||||
PrivateKey PrivateKeyFromSeedBIP32(const void* data, const size_t len) {
|
||||
return new bls::PrivateKey(
|
||||
bls::PrivateKey::FromSeedBIP32(bls::Bytes((uint8_t*)data, len))
|
||||
);
|
||||
}
|
||||
|
||||
PrivateKey PrivateKeyAggregate(void** sks, const size_t len) {
|
||||
return new bls::PrivateKey(
|
||||
bls::PrivateKey::Aggregate(toBLSVector<bls::PrivateKey>(sks, len))
|
||||
);
|
||||
}
|
||||
|
||||
void* PrivateKeySerialize(const PrivateKey sk) {
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
uint8_t* buffer = bls::Util::SecAlloc<uint8_t>(bls::PrivateKey::PRIVATE_KEY_SIZE);
|
||||
skPtr->Serialize(buffer);
|
||||
|
||||
return (void*)buffer;
|
||||
}
|
||||
|
||||
size_t PrivateKeySizeBytes() {
|
||||
return bls::PrivateKey::PRIVATE_KEY_SIZE;
|
||||
}
|
||||
|
||||
bool PrivateKeyIsEqual(const PrivateKey sk1, const PrivateKey sk2) {
|
||||
const bls::PrivateKey* sk1Ptr = (bls::PrivateKey*)sk1;
|
||||
const bls::PrivateKey* sk2Ptr = (bls::PrivateKey*)sk2;
|
||||
return *sk1Ptr == *sk2Ptr;
|
||||
}
|
||||
|
||||
G1Element PrivateKeyGetG1Element(const PrivateKey sk, bool* didErr) {
|
||||
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
bls::G1Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G1Element(skPtr->GetG1Element());
|
||||
*didErr = false;
|
||||
} catch (const std::exception& ex) {
|
||||
// set err
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element PrivateKeyGetG2Element(const PrivateKey sk, bool* didErr) {
|
||||
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
bls::G2Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G2Element(skPtr->GetG2Element());
|
||||
*didErr = false;
|
||||
} catch (const std::exception& ex) {
|
||||
// set err
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element PrivateKeyGetG2Power(const PrivateKey sk, const G2Element el) {
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
const bls::G2Element* elPtr = (bls::G2Element*)el;
|
||||
return new bls::G2Element(skPtr->GetG2Power(*elPtr));
|
||||
}
|
||||
|
||||
G2Element PrivateKeySignG2(const PrivateKey sk,
|
||||
uint8_t* msg,
|
||||
const size_t len,
|
||||
const uint8_t* dst,
|
||||
const size_t dstLen) {
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(skPtr->SignG2(msg, len, dst, dstLen));
|
||||
}
|
||||
|
||||
void PrivateKeyFree(PrivateKey sk) {
|
||||
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
delete skPtr;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PRIVATEKEY_H_
|
||||
#define PRIVATEKEY_H_
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "elements.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* PrivateKey;
|
||||
|
||||
PrivateKey PrivateKeyFromBytes(const void* data, const bool modOrder, bool* didErr);
|
||||
PrivateKey PrivateKeyFromSeedBIP32(const void* data, const size_t len);
|
||||
PrivateKey PrivateKeyAggregate(void** sks, const size_t len);
|
||||
G1Element PrivateKeyGetG1Element(const PrivateKey sk, bool* didErr);
|
||||
G2Element PrivateKeyGetG2Element(const PrivateKey sk, bool* didErr);
|
||||
G2Element PrivateKeyGetG2Power(const PrivateKey sk, const G2Element el);
|
||||
bool PrivateKeyIsEqual(const PrivateKey sk1, const PrivateKey sk2);
|
||||
void* PrivateKeySerialize(const PrivateKey sk);
|
||||
void PrivateKeyFree(const PrivateKey sk);
|
||||
size_t PrivateKeySizeBytes();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // PRIVATEKEY_H_
|
388
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp
Normal file
388
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp
Normal file
@ -0,0 +1,388 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "schemes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "bls.hpp"
|
||||
#include "blschia.h"
|
||||
#include "elements.h"
|
||||
#include "error.h"
|
||||
#include "privatekey.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
// Implementation of bindings for CoreMPL class
|
||||
|
||||
PrivateKey CoreMPLKeyGen(
|
||||
const CoreMPL scheme,
|
||||
const void* seed,
|
||||
const size_t seedLen,
|
||||
bool* didErr)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
bls::PrivateKey* sk = nullptr;
|
||||
try {
|
||||
sk = new bls::PrivateKey(
|
||||
schemePtr->KeyGen(bls::Bytes((uint8_t*)seed, seedLen)));
|
||||
} catch (const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return sk;
|
||||
}
|
||||
|
||||
G1Element CoreMPLSkToG1(const CoreMPL scheme, const PrivateKey sk)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G1Element(schemePtr->SkToG1(*skPtr));
|
||||
}
|
||||
|
||||
G2Element CoreMPLSign(
|
||||
CoreMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(
|
||||
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen)));
|
||||
}
|
||||
|
||||
bool CoreMPLVerify(
|
||||
const CoreMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return schemePtr->Verify(
|
||||
*pkPtr, bls::Bytes((uint8_t*)msg, msgLen), *sigPtr);
|
||||
}
|
||||
|
||||
bool CoreMPLVerifySecure(
|
||||
const CoreMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const G2Element sig,
|
||||
const void* msg,
|
||||
const size_t msgLen)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const uint8_t* msgPtr = (uint8_t*)msg;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return schemePtr->VerifySecure(
|
||||
vecPubKeys, *sigPtr, bls::Bytes(msgPtr, msgLen));
|
||||
}
|
||||
|
||||
G1Element CoreMPLAggregatePubKeys(
|
||||
const CoreMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
return new bls::G1Element(
|
||||
schemePtr->Aggregate(toBLSVector<bls::G1Element>(pks, pksLen)));
|
||||
}
|
||||
|
||||
G2Element CoreMPLAggregateSigs(
|
||||
const CoreMPL scheme,
|
||||
void** sigs,
|
||||
const size_t sigsLen)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
return new bls::G2Element(
|
||||
schemePtr->Aggregate(toBLSVector<bls::G2Element>(sigs, sigsLen)));
|
||||
}
|
||||
|
||||
PrivateKey CoreMPLDeriveChildSk(
|
||||
const CoreMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const uint32_t index)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::PrivateKey(schemePtr->DeriveChildSk(*skPtr, index));
|
||||
}
|
||||
|
||||
PrivateKey CoreMPLDeriveChildSkUnhardened(
|
||||
CoreMPL scheme,
|
||||
PrivateKey sk,
|
||||
uint32_t index)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::PrivateKey(
|
||||
schemePtr->DeriveChildSkUnhardened(*skPtr, index));
|
||||
}
|
||||
|
||||
G1Element CoreMPLDeriveChildPkUnhardened(
|
||||
CoreMPL scheme,
|
||||
G1Element el,
|
||||
uint32_t index)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
bls::G1Element* elPtr = (bls::G1Element*)el;
|
||||
return new bls::G1Element(
|
||||
schemePtr->DeriveChildPkUnhardened(*elPtr, index));
|
||||
}
|
||||
|
||||
bool CoreMPLAggregateVerify(
|
||||
const CoreMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
|
||||
const size_t* msgLensPtr = (size_t*)msgsLens;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const std::vector<size_t> vecMsgsLens =
|
||||
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
|
||||
const std::vector<bls::Bytes> vecMsgs =
|
||||
toVectorBytes(msgs, msgsLen, vecMsgsLens);
|
||||
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
|
||||
}
|
||||
|
||||
// BasicSchemeMPL
|
||||
BasicSchemeMPL NewBasicSchemeMPL() { return new bls::BasicSchemeMPL(); }
|
||||
|
||||
bool BasicSchemeMPLAggregateVerify(
|
||||
BasicSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::BasicSchemeMPL* schemePtr = (bls::BasicSchemeMPL*)scheme;
|
||||
const size_t* msgLensPtr = (size_t*)msgsLens;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const std::vector<size_t> vecMsgsLens =
|
||||
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
|
||||
const std::vector<bls::Bytes> vecMsgs =
|
||||
toVectorBytes(msgs, msgsLen, vecMsgsLens);
|
||||
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
|
||||
}
|
||||
|
||||
void BasicSchemeMPLFree(BasicSchemeMPL scheme)
|
||||
{
|
||||
bls::BasicSchemeMPL* schemePtr = (bls::BasicSchemeMPL*)scheme;
|
||||
delete schemePtr;
|
||||
}
|
||||
|
||||
// AugSchemeMPL
|
||||
AugSchemeMPL NewAugSchemeMPL() { return new bls::AugSchemeMPL(); }
|
||||
|
||||
G2Element AugSchemeMPLSign(
|
||||
const AugSchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen)
|
||||
{
|
||||
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(
|
||||
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen)));
|
||||
}
|
||||
|
||||
G2Element AugSchemeMPLSignPrepend(
|
||||
const AugSchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G1Element prepPk)
|
||||
{
|
||||
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
const bls::G1Element* prepPkPtr = (bls::G1Element*)prepPk;
|
||||
return new bls::G2Element(
|
||||
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen), *prepPkPtr));
|
||||
}
|
||||
|
||||
bool AugSchemeMPLVerify(
|
||||
const AugSchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
|
||||
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
|
||||
const uint8_t* msgPtr = (uint8_t*)msg;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return schemePtr->Verify(*pkPtr, bls::Bytes(msgPtr, msgLen), *sigPtr);
|
||||
}
|
||||
|
||||
bool AugSchemeMPLAggregateVerify(
|
||||
const AugSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
|
||||
const size_t* msgLensPtr = (size_t*)msgsLens;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const std::vector<size_t> vecMsgsLens =
|
||||
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
|
||||
const std::vector<bls::Bytes> vecMsgs =
|
||||
toVectorBytes(msgs, msgsLen, vecMsgsLens);
|
||||
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
|
||||
}
|
||||
|
||||
void AugSchemeMPLFree(AugSchemeMPL scheme)
|
||||
{
|
||||
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
|
||||
delete schemePtr;
|
||||
}
|
||||
|
||||
// PopSchemeMPL
|
||||
PopSchemeMPL NewPopSchemeMPL() { return new bls::PopSchemeMPL(); }
|
||||
|
||||
G2Element PopSchemeMPLPopProve(
|
||||
const PopSchemeMPL scheme,
|
||||
const PrivateKey sk)
|
||||
{
|
||||
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(schemePtr->PopProve(*skPtr));
|
||||
}
|
||||
|
||||
bool PopSchemeMPLPopVerify(
|
||||
const PopSchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
|
||||
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return schemePtr->PopVerify(*pkPtr, *sigPtr);
|
||||
}
|
||||
|
||||
bool PopSchemeMPLFastAggregateVerify(
|
||||
const PopSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
return schemePtr->FastAggregateVerify(
|
||||
vecPubKeys, bls::Bytes((uint8_t*)msg, msgLen), *sigPtr);
|
||||
}
|
||||
|
||||
void PopSchemeMPLFree(PopSchemeMPL scheme)
|
||||
{
|
||||
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
|
||||
delete schemePtr;
|
||||
}
|
||||
|
||||
// LegacySchemeMPL
|
||||
LegacySchemeMPL NewLegacySchemeMPL() { return new bls::LegacySchemeMPL(); }
|
||||
|
||||
G2Element LegacySchemeMPLSign(
|
||||
const LegacySchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen)
|
||||
{
|
||||
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
|
||||
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(
|
||||
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen)));
|
||||
}
|
||||
|
||||
bool LegacySchemeMPLVerify(
|
||||
const LegacySchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
|
||||
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
|
||||
const uint8_t* msgPtr = (uint8_t*)msg;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return schemePtr->Verify(*pkPtr, bls::Bytes(msgPtr, msgLen), *sigPtr);
|
||||
}
|
||||
|
||||
bool LegacySchemeMPLVerifySecure(
|
||||
const LegacySchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const G2Element sig,
|
||||
const void* msg,
|
||||
const size_t msgLen)
|
||||
{
|
||||
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const uint8_t* msgPtr = (uint8_t*)msg;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
// Because of scheme pointer it will call CoreMPL::VerifySecure with 'legacy' flag variant
|
||||
return schemePtr->VerifySecure(
|
||||
vecPubKeys, *sigPtr, bls::Bytes(msgPtr, msgLen));
|
||||
}
|
||||
|
||||
bool LegacySchemeMPLAggregateVerify(
|
||||
const LegacySchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig)
|
||||
{
|
||||
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
|
||||
const size_t* msgLensPtr = (size_t*)msgsLens;
|
||||
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
const std::vector<bls::G1Element> vecPubKeys =
|
||||
toBLSVector<bls::G1Element>(pks, pksLen);
|
||||
const std::vector<size_t> vecMsgsLens =
|
||||
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
|
||||
const std::vector<bls::Bytes> vecMsgs =
|
||||
toVectorBytes(msgs, msgsLen, vecMsgsLens);
|
||||
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
|
||||
}
|
||||
|
||||
void LegacySchemeMPLFree(LegacySchemeMPL scheme)
|
||||
{
|
||||
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
|
||||
delete schemePtr;
|
||||
}
|
184
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.h
Normal file
184
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.h
Normal file
@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SCHEMES_H_
|
||||
#define SCHEMES_H_
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "elements.h"
|
||||
#include "privatekey.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* CoreMPL;
|
||||
typedef CoreMPL BasicSchemeMPL;
|
||||
typedef CoreMPL AugSchemeMPL;
|
||||
typedef CoreMPL PopSchemeMPL;
|
||||
typedef CoreMPL LegacySchemeMPL;
|
||||
|
||||
// CoreMPL
|
||||
PrivateKey CoreMPLKeyGen(
|
||||
const CoreMPL scheme,
|
||||
const void* seed,
|
||||
const size_t seedLen,
|
||||
bool* didErr);
|
||||
G1Element CoreMPLSkToG1(const CoreMPL scheme, const PrivateKey sk);
|
||||
G2Element CoreMPLSign(
|
||||
const CoreMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen);
|
||||
bool CoreMPLVerify(
|
||||
const BasicSchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig);
|
||||
bool CoreMPLVerifySecure(
|
||||
const CoreMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const G2Element sig,
|
||||
const void* msg,
|
||||
const size_t msgLen);
|
||||
G1Element CoreMPLAggregatePubKeys(
|
||||
const CoreMPL scheme,
|
||||
void** pubKeys,
|
||||
const size_t pkLen);
|
||||
G2Element CoreMPLAggregateSigs(
|
||||
const CoreMPL scheme,
|
||||
void** sigs,
|
||||
const size_t sigLen);
|
||||
PrivateKey CoreMPLDeriveChildSk(
|
||||
const CoreMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const uint32_t index);
|
||||
PrivateKey CoreMPLDeriveChildSkUnhardened(
|
||||
const CoreMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const uint32_t index);
|
||||
G1Element CoreMPLDeriveChildPkUnhardened(
|
||||
const CoreMPL scheme,
|
||||
const G1Element sk,
|
||||
const uint32_t index);
|
||||
bool CoreMPLAggregateVerify(
|
||||
const CoreMPL scheme,
|
||||
void** pks,
|
||||
const size_t pkLen,
|
||||
void** msgs,
|
||||
const void* msgLens,
|
||||
const size_t msgLen,
|
||||
const G2Element sig);
|
||||
|
||||
// BasicSchemeMPL
|
||||
BasicSchemeMPL NewBasicSchemeMPL();
|
||||
bool BasicSchemeMPLAggregateVerify(
|
||||
BasicSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig);
|
||||
void BasicSchemeMPLFree(BasicSchemeMPL scheme);
|
||||
|
||||
// AugSchemeMPL
|
||||
AugSchemeMPL NewAugSchemeMPL();
|
||||
G2Element AugSchemeMPLSign(
|
||||
const AugSchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen);
|
||||
G2Element AugSchemeMPLSignPrepend(
|
||||
const AugSchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G1Element prepPk);
|
||||
bool AugSchemeMPLVerify(
|
||||
const AugSchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig);
|
||||
bool AugSchemeMPLAggregateVerify(
|
||||
const AugSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig);
|
||||
void AugSchemeMPLFree(AugSchemeMPL scheme);
|
||||
|
||||
// PopSchemeMPL
|
||||
PopSchemeMPL NewPopSchemeMPL();
|
||||
G2Element PopSchemeMPLPopProve(
|
||||
const PopSchemeMPL scheme,
|
||||
const PrivateKey sk);
|
||||
bool PopSchemeMPLPopVerify(
|
||||
const PopSchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const G2Element sig);
|
||||
bool PopSchemeMPLFastAggregateVerify(
|
||||
const PopSchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const void* msgs,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig);
|
||||
void PopSchemeMPLFree(PopSchemeMPL scheme);
|
||||
|
||||
// LegacySchemeMPL
|
||||
LegacySchemeMPL NewLegacySchemeMPL();
|
||||
G2Element LegacySchemeMPLSign(
|
||||
const LegacySchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen);
|
||||
G2Element LegacySchemeMPLSignPrepend(
|
||||
const LegacySchemeMPL scheme,
|
||||
const PrivateKey sk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G1Element prepPk);
|
||||
bool LegacySchemeMPLVerify(
|
||||
const LegacySchemeMPL scheme,
|
||||
const G1Element pk,
|
||||
const void* msg,
|
||||
const size_t msgLen,
|
||||
const G2Element sig);
|
||||
bool LegacySchemeMPLVerifySecure(
|
||||
const LegacySchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
const G2Element sig,
|
||||
const void* msg,
|
||||
const size_t msgLen);
|
||||
bool LegacySchemeMPLAggregateVerify(
|
||||
const LegacySchemeMPL scheme,
|
||||
void** pks,
|
||||
const size_t pksLen,
|
||||
void** msgs,
|
||||
const void* msgsLens,
|
||||
const size_t msgsLen,
|
||||
const G2Element sig);
|
||||
void LegacySchemeMPLFree(LegacySchemeMPL scheme);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // SCHEMES_H_
|
168
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/threshold.cpp
Normal file
168
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/threshold.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "bls.hpp"
|
||||
#include "privatekey.h"
|
||||
#include "elements.h"
|
||||
#include "blschia.h"
|
||||
#include "threshold.h"
|
||||
#include "utils.hpp"
|
||||
#include "error.h"
|
||||
|
||||
std::vector<bls::Bytes> toVectorHashes(void** elems, const size_t len) {
|
||||
std::vector<bls::Bytes> vec;
|
||||
vec.reserve(len);
|
||||
for (int i = 0 ; i < len; ++i) {
|
||||
vec.push_back(
|
||||
bls::Bytes((uint8_t*)elems[i], HashSize)
|
||||
);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
PrivateKey ThresholdPrivateKeyShare(void** sks, const size_t sksLen, const void* hash, bool* didErr) {
|
||||
bls::PrivateKey* sk = nullptr;
|
||||
try {
|
||||
sk = new bls::PrivateKey(
|
||||
bls::Threshold::PrivateKeyShare(
|
||||
toBLSVector<bls::PrivateKey>(sks, sksLen),
|
||||
bls::Bytes((uint8_t*)hash, HashSize)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return sk;
|
||||
}
|
||||
|
||||
PrivateKey ThresholdPrivateKeyRecover(void** sks,
|
||||
const size_t sksLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr) {
|
||||
bls::PrivateKey* sk = nullptr;
|
||||
std::vector<bls::Bytes> pop = toVectorHashes(hashes, hashesLen);
|
||||
try {
|
||||
sk = new bls::PrivateKey(
|
||||
bls::Threshold::PrivateKeyRecover(
|
||||
toBLSVector<bls::PrivateKey>(sks, sksLen),
|
||||
toVectorHashes(hashes, hashesLen)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return sk;
|
||||
}
|
||||
|
||||
G1Element ThresholdPublicKeyShare(void** pks, const size_t pksLen, const void* hash, bool* didErr) {
|
||||
bls::G1Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G1Element(
|
||||
bls::Threshold::PublicKeyShare(
|
||||
toBLSVector<bls::G1Element>(pks, pksLen),
|
||||
bls::Bytes((uint8_t*)hash, HashSize)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
G1Element ThresholdPublicKeyRecover(void** pks,
|
||||
const size_t pksLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr) {
|
||||
bls::G1Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G1Element(
|
||||
bls::Threshold::PublicKeyRecover(
|
||||
toBLSVector<bls::G1Element>(pks, pksLen),
|
||||
toVectorHashes(hashes, hashesLen)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element ThresholdSignatureShare(void** sigs, const size_t sigsLen, const void* hash, bool* didErr) {
|
||||
bls::G2Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G2Element(
|
||||
bls::Threshold::SignatureShare(
|
||||
toBLSVector<bls::G2Element>(sigs, sigsLen),
|
||||
bls::Bytes((uint8_t*)hash, HashSize)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element ThresholdSignatureRecover(void** sigs,
|
||||
const size_t sigsLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr) {
|
||||
bls::G2Element* el = nullptr;
|
||||
try {
|
||||
el = new bls::G2Element(
|
||||
bls::Threshold::SignatureRecover(
|
||||
toBLSVector<bls::G2Element>(sigs, sigsLen),
|
||||
toVectorHashes(hashes, hashesLen)
|
||||
)
|
||||
);
|
||||
} catch(const std::exception& ex) {
|
||||
gErrMsg = ex.what();
|
||||
*didErr = true;
|
||||
return nullptr;
|
||||
}
|
||||
*didErr = false;
|
||||
return el;
|
||||
}
|
||||
|
||||
G2Element ThresholdSign(const PrivateKey sk, const void* hash) {
|
||||
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
|
||||
return new bls::G2Element(
|
||||
bls::Threshold::Sign(*skPtr, bls::Bytes((uint8_t*)hash, HashSize))
|
||||
);
|
||||
}
|
||||
|
||||
bool ThresholdVerify(const G1Element pk, const void* hash, const G2Element sig) {
|
||||
bls::G1Element* pkPtr = (bls::G1Element*)pk;
|
||||
bls::G2Element* sigPtr = (bls::G2Element*)sig;
|
||||
return bls::Threshold::Verify(*pkPtr, bls::Bytes((uint8_t*)hash, HashSize), *sigPtr);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THRESHOLD_H_
|
||||
#define THRESHOLD_H_
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "privatekey.h"
|
||||
#include "elements.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const int HashSize = 32;
|
||||
|
||||
PrivateKey ThresholdPrivateKeyShare(void** sks, const size_t sksLen, const void* hash, bool* didErr);
|
||||
PrivateKey ThresholdPrivateKeyRecover(void** sks,
|
||||
const size_t sksLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr);
|
||||
|
||||
G1Element ThresholdPublicKeyShare(void** pks, const size_t pksLen, const void* hash, bool* didErr);
|
||||
G1Element ThresholdPublicKeyRecover(void** pks,
|
||||
const size_t pksLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr);
|
||||
|
||||
G2Element ThresholdSignatureShare(void** sigs, const size_t sigsLen, const void* hash, bool* didErr);
|
||||
G2Element ThresholdSignatureRecover(void** sigs,
|
||||
const size_t sigsLen,
|
||||
void** hashes,
|
||||
const size_t hashesLen,
|
||||
bool* didErr);
|
||||
|
||||
G2Element ThresholdSign(const PrivateKey sk, const void* hash);
|
||||
bool ThresholdVerify(const G1Element pk, const void* hash, const G2Element sig);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // THRESHOLD_H_
|
40
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/utils.cpp
Normal file
40
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/utils.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <vector>
|
||||
#include "bls.hpp"
|
||||
#include "privatekey.h"
|
||||
#include "elements.h"
|
||||
|
||||
// helper functions
|
||||
template <class T>
|
||||
std::vector<T> toBLSVector(void** elems, const size_t len) {
|
||||
std::vector<T> vec;
|
||||
vec.reserve(len);
|
||||
for (int i = 0 ; i < len; ++i) {
|
||||
T* el = (T*)elems[i];
|
||||
vec.push_back(*el);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<bls::Bytes> toVectorBytes(void** elems, const size_t len, const std::vector<size_t> vecElemsLens) {
|
||||
std::vector<bls::Bytes> vec;
|
||||
vec.reserve(len);
|
||||
for (int i = 0 ; i < len; ++i) {
|
||||
uint8_t* elPtr = (uint8_t*)elems[i];
|
||||
vec.push_back(bls::Bytes(elPtr, vecElemsLens[i]));
|
||||
}
|
||||
return vec;
|
||||
}
|
34
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/utils.hpp
Normal file
34
src/dashbls/rust-bindings/bls-dash-sys/c-bindings/utils.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2021 The Dash Core developers
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "bls.hpp"
|
||||
#include "privatekey.h"
|
||||
#include "elements.h"
|
||||
|
||||
// helper functions
|
||||
template <class T>
|
||||
std::vector<T> toBLSVector(void** elems, const size_t len) {
|
||||
std::vector<T> vec;
|
||||
vec.reserve(len);
|
||||
for (int i = 0 ; i < (int)len; ++i) {
|
||||
const T* el = (T*)elems[i];
|
||||
vec.push_back(*el);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<bls::Bytes> toVectorBytes(void** elems, const size_t len, const std::vector<size_t> vecElemsLens);
|
8
src/dashbls/rust-bindings/bls-dash-sys/include.h
Normal file
8
src/dashbls/rust-bindings/bls-dash-sys/include.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include "c-bindings/blschia.h"
|
||||
#include "c-bindings/elements.h"
|
||||
#include "c-bindings/privatekey.h"
|
||||
#include "c-bindings/schemes.h"
|
||||
#include "c-bindings/threshold.h"
|
||||
#include "c-bindings/bip32/chaincode.h"
|
||||
#include "c-bindings/bip32/extendedprivatekey.h"
|
||||
#include "c-bindings/bip32/extendedpublickey.h"
|
6
src/dashbls/rust-bindings/bls-dash-sys/src/lib.rs
Normal file
6
src/dashbls/rust-bindings/bls-dash-sys/src/lib.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
// include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
include!("../bindings.rs");
|
@ -0,0 +1,79 @@
|
||||
use bls_dash_sys as sys;
|
||||
|
||||
#[test]
|
||||
fn sign_and_verify() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let bad_seed = b"weedseedweedseedweedseedweedseed";
|
||||
|
||||
unsafe {
|
||||
let scheme = sys::NewAugSchemeMPL();
|
||||
let mut did_err = false;
|
||||
|
||||
let sk = sys::CoreMPLKeyGen(
|
||||
scheme,
|
||||
seed.as_ptr() as *const _,
|
||||
seed.len(),
|
||||
&mut did_err as *mut _,
|
||||
);
|
||||
assert!(!did_err);
|
||||
|
||||
let pk = sys::PrivateKeyGetG1Element(sk, &mut did_err as *mut _);
|
||||
assert!(!did_err);
|
||||
|
||||
let sk2 = sys::CoreMPLKeyGen(
|
||||
scheme,
|
||||
bad_seed.as_ptr() as *const _,
|
||||
bad_seed.len(),
|
||||
&mut did_err as *mut _,
|
||||
);
|
||||
assert!(!did_err);
|
||||
|
||||
let pk2 = sys::PrivateKeyGetG1Element(sk2, &mut did_err as *mut _);
|
||||
assert!(!did_err);
|
||||
|
||||
let message = b"Evgeny owns 1337 dash no cap";
|
||||
let sig = sys::CoreMPLSign(scheme, sk, message.as_ptr() as *const _, message.len());
|
||||
|
||||
let verify =
|
||||
sys::CoreMPLVerify(scheme, pk, message.as_ptr() as *const _, message.len(), sig);
|
||||
assert!(verify);
|
||||
|
||||
let verify_bad = sys::CoreMPLVerify(
|
||||
scheme,
|
||||
pk2,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
sig,
|
||||
);
|
||||
assert!(!verify_bad);
|
||||
|
||||
sys::G2ElementFree(sig);
|
||||
sys::G1ElementFree(pk2);
|
||||
sys::PrivateKeyFree(sk2);
|
||||
sys::G1ElementFree(pk);
|
||||
sys::PrivateKeyFree(sk);
|
||||
sys::AugSchemeMPLFree(scheme);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_key_from_bip32() {
|
||||
use std::slice;
|
||||
let long_seed: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2];
|
||||
let long_private_key_test_data: [u8; 32] = [50, 67, 148, 112, 207, 6, 210, 118, 137, 125, 27, 144, 105, 189, 214, 228, 68, 83, 144, 205, 80, 105, 133, 222, 14, 26, 28, 136, 167, 111, 241, 118];
|
||||
let short_seed: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let short_private_key_test_data: [u8; 32] = [70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30, 185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189];
|
||||
unsafe {
|
||||
let c_private_key = sys::PrivateKeyFromSeedBIP32(long_seed.as_ptr() as *const _, long_seed.len());
|
||||
let serialized = sys::PrivateKeySerialize(c_private_key) as *const u8;
|
||||
let data = slice::from_raw_parts(serialized, sys::PrivateKeySizeBytes());
|
||||
assert_eq!(data, &long_private_key_test_data);
|
||||
sys::PrivateKeyFree(c_private_key);
|
||||
|
||||
let c_private_key = sys::PrivateKeyFromSeedBIP32(short_seed.as_ptr() as *const _, short_seed.len());
|
||||
let serialized = sys::PrivateKeySerialize(c_private_key) as *const u8;
|
||||
let data = slice::from_raw_parts(serialized, sys::PrivateKeySizeBytes());
|
||||
assert_eq!(data, &short_private_key_test_data);
|
||||
sys::PrivateKeyFree(c_private_key);
|
||||
}
|
||||
}
|
17
src/dashbls/rust-bindings/bls-signatures/.rustfmt.toml
Normal file
17
src/dashbls/rust-bindings/bls-signatures/.rustfmt.toml
Normal file
@ -0,0 +1,17 @@
|
||||
unstable_features = true
|
||||
|
||||
blank_lines_lower_bound = 0
|
||||
condense_wildcard_suffixes = true
|
||||
error_on_line_overflow = true
|
||||
error_on_unformatted = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
imports_granularity = "Crate"
|
||||
normalize_comments = true
|
||||
normalize_doc_attributes = true
|
||||
reorder_impl_items = true
|
||||
group_imports = "StdExternalCrate"
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
18
src/dashbls/rust-bindings/bls-signatures/Cargo.toml
Normal file
18
src/dashbls/rust-bindings/bls-signatures/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "bls-signatures"
|
||||
description = ""
|
||||
version = "1.2.5"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
legacy = []
|
||||
bip32 = []
|
||||
use_serde = ["serde"]
|
||||
dash_helpers = ["rand"]
|
||||
default = [ "legacy", "bip32", "dash_helpers", "use_serde"]
|
||||
apple = ["bls-dash-sys/apple"]
|
||||
|
||||
[dependencies]
|
||||
bls-dash-sys = { path = "../bls-dash-sys" }
|
||||
serde = { version= "1.0.160", features = ["derive"], optional = true}
|
||||
rand = { version= "0.8.5", optional = true}
|
@ -0,0 +1,33 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use bls_dash_sys::{BIP32ChainCodeFree, BIP32ChainCodeIsEqual, BIP32ChainCodeSerialize};
|
||||
|
||||
pub const BIP32_CHAIN_CODE_SIZE: usize = 32;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChainCode {
|
||||
pub(crate) c_chain_code: *mut c_void,
|
||||
}
|
||||
|
||||
impl ChainCode {
|
||||
pub fn serialize(&self) -> Box<[u8; BIP32_CHAIN_CODE_SIZE]> {
|
||||
unsafe {
|
||||
let malloc_ptr = BIP32ChainCodeSerialize(self.c_chain_code);
|
||||
Box::from_raw(malloc_ptr as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ChainCode {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe { BIP32ChainCodeIsEqual(self.c_chain_code, other.c_chain_code) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ChainCode {}
|
||||
|
||||
impl Drop for ChainCode {
|
||||
fn drop(&mut self) {
|
||||
unsafe { BIP32ChainCodeFree(self.c_chain_code) }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
mod chain_code;
|
||||
mod private_key;
|
||||
mod public_key;
|
||||
|
||||
pub use chain_code::*;
|
||||
pub use private_key::*;
|
||||
pub use public_key::*;
|
@ -0,0 +1,205 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use bls_dash_sys::{
|
||||
BIP32ExtendedPrivateKeyFree, BIP32ExtendedPrivateKeyFromBytes, BIP32ExtendedPrivateKeyFromSeed,
|
||||
BIP32ExtendedPrivateKeyGetChainCode, BIP32ExtendedPrivateKeyGetExtendedPublicKey,
|
||||
BIP32ExtendedPrivateKeyGetPrivateKey, BIP32ExtendedPrivateKeyGetPublicKey,
|
||||
BIP32ExtendedPrivateKeyIsEqual, BIP32ExtendedPrivateKeyPrivateChild,
|
||||
BIP32ExtendedPrivateKeyPublicChild, BIP32ExtendedPrivateKeySerialize,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
bip32::{chain_code::ChainCode, ExtendedPublicKey},
|
||||
utils::{c_err_to_result, SecureBox},
|
||||
BlsError, G1Element, PrivateKey,
|
||||
};
|
||||
|
||||
pub const BIP32_EXTENDED_PRIVATE_KEY_SIZE: usize = 77;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExtendedPrivateKey {
|
||||
c_extended_private_key: *mut c_void,
|
||||
}
|
||||
|
||||
impl PartialEq for ExtendedPrivateKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe {
|
||||
BIP32ExtendedPrivateKeyIsEqual(
|
||||
self.c_extended_private_key,
|
||||
other.c_extended_private_key,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExtendedPrivateKey {}
|
||||
|
||||
impl ExtendedPrivateKey {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
if bytes.len() != BIP32_EXTENDED_PRIVATE_KEY_SIZE {
|
||||
return Err(BlsError {
|
||||
msg: format!(
|
||||
"Extended Private Key size must be {}, got {}",
|
||||
BIP32_EXTENDED_PRIVATE_KEY_SIZE,
|
||||
bytes.len()
|
||||
),
|
||||
});
|
||||
}
|
||||
Ok(ExtendedPrivateKey {
|
||||
c_extended_private_key: c_err_to_result(|did_err| unsafe {
|
||||
BIP32ExtendedPrivateKeyFromBytes(bytes.as_ptr() as *const _, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_seed(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Ok(ExtendedPrivateKey {
|
||||
c_extended_private_key: c_err_to_result(|did_err| unsafe {
|
||||
BIP32ExtendedPrivateKeyFromSeed(bytes.as_ptr() as *const _, bytes.len(), did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn private_child_with_legacy_flag(&self, index: u32, legacy: bool) -> Self {
|
||||
ExtendedPrivateKey {
|
||||
c_extended_private_key: unsafe {
|
||||
BIP32ExtendedPrivateKeyPrivateChild(self.c_extended_private_key, index, legacy)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn private_child(&self, index: u32) -> Self {
|
||||
self.private_child_with_legacy_flag(index, false)
|
||||
}
|
||||
|
||||
pub fn public_child(&self, index: u32) -> ExtendedPublicKey {
|
||||
ExtendedPublicKey {
|
||||
c_extended_public_key: unsafe {
|
||||
BIP32ExtendedPrivateKeyPublicChild(self.c_extended_private_key, index)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn extended_public_key_with_legacy_flag(
|
||||
&self,
|
||||
legacy: bool,
|
||||
) -> Result<ExtendedPublicKey, BlsError> {
|
||||
Ok(ExtendedPublicKey {
|
||||
c_extended_public_key: c_err_to_result(|did_err| unsafe {
|
||||
BIP32ExtendedPrivateKeyGetExtendedPublicKey(
|
||||
self.c_extended_private_key,
|
||||
legacy,
|
||||
did_err,
|
||||
)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn extended_public_key(&self) -> Result<ExtendedPublicKey, BlsError> {
|
||||
self.extended_public_key_with_legacy_flag(false)
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> Result<G1Element, BlsError> {
|
||||
Ok(G1Element {
|
||||
c_element: c_err_to_result(|did_err| unsafe {
|
||||
BIP32ExtendedPrivateKeyGetPublicKey(self.c_extended_private_key, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn private_key(&self) -> PrivateKey {
|
||||
PrivateKey {
|
||||
c_private_key: unsafe {
|
||||
BIP32ExtendedPrivateKeyGetPrivateKey(self.c_extended_private_key)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> SecureBox {
|
||||
unsafe {
|
||||
let secalloc_ptr = BIP32ExtendedPrivateKeySerialize(self.c_extended_private_key);
|
||||
SecureBox::from_ptr(secalloc_ptr as *mut u8, BIP32_EXTENDED_PRIVATE_KEY_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chain_code(&self) -> ChainCode {
|
||||
ChainCode {
|
||||
c_chain_code: unsafe {
|
||||
BIP32ExtendedPrivateKeyGetChainCode(self.c_extended_private_key)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ExtendedPrivateKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe { BIP32ExtendedPrivateKeyFree(self.c_extended_private_key) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
|
||||
let private_key_bytes = private_key.serialize();
|
||||
let private_key_2 = ExtendedPrivateKey::from_bytes(private_key_bytes.as_ref())
|
||||
.expect("cannot deserialize extended private key");
|
||||
|
||||
assert_eq!(private_key, private_key_2);
|
||||
assert_eq!(private_key.private_key(), private_key_2.private_key());
|
||||
assert_eq!(private_key.public_key(), private_key_2.public_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hierarchical_deterministic_keys() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let private_child = private_key.private_child(1337);
|
||||
let private_grandchild = private_child.private_child(420);
|
||||
|
||||
let public_child = public_key.public_child(1337);
|
||||
let public_grandchild = public_child.public_child(420);
|
||||
|
||||
assert_eq!(
|
||||
public_grandchild,
|
||||
private_grandchild
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_keys_match() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
assert_eq!(private_key.public_key(), Ok(public_key.public_key()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fingerprint_for_short_bip32_seed() {
|
||||
assert_eq!(
|
||||
ExtendedPrivateKey::from_seed(&[1u8, 50, 6, 244, 24, 199, 1, 25])
|
||||
.expect("cannot generate extended private key")
|
||||
.public_key()
|
||||
.expect("cannot get public key from extended private key")
|
||||
.fingerprint_legacy(),
|
||||
0xa4700b27
|
||||
);
|
||||
}
|
||||
}
|
119
src/dashbls/rust-bindings/bls-signatures/src/bip32/public_key.rs
Normal file
119
src/dashbls/rust-bindings/bls-signatures/src/bip32/public_key.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use bls_dash_sys::{
|
||||
BIP32ExtendedPublicKeyFree, BIP32ExtendedPublicKeyFromBytes,
|
||||
BIP32ExtendedPublicKeyGetChainCode, BIP32ExtendedPublicKeyGetPublicKey,
|
||||
BIP32ExtendedPublicKeyIsEqual, BIP32ExtendedPublicKeyPublicChild,
|
||||
BIP32ExtendedPublicKeySerialize,
|
||||
};
|
||||
|
||||
use crate::{bip32::chain_code::ChainCode, utils::c_err_to_result, BlsError, G1Element};
|
||||
|
||||
pub const BIP32_EXTENDED_PUBLIC_KEY_SIZE: usize = 93;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExtendedPublicKey {
|
||||
pub(crate) c_extended_public_key: *mut c_void,
|
||||
}
|
||||
|
||||
impl PartialEq for ExtendedPublicKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe {
|
||||
BIP32ExtendedPublicKeyIsEqual(self.c_extended_public_key, other.c_extended_public_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExtendedPublicKey {}
|
||||
|
||||
impl ExtendedPublicKey {
|
||||
pub(crate) fn from_bytes_with_legacy_flag(
|
||||
bytes: &[u8],
|
||||
legacy: bool,
|
||||
) -> Result<Self, BlsError> {
|
||||
if bytes.len() != BIP32_EXTENDED_PUBLIC_KEY_SIZE {
|
||||
return Err(BlsError {
|
||||
msg: format!(
|
||||
"Extended Public Key size must be {}, got {}",
|
||||
BIP32_EXTENDED_PUBLIC_KEY_SIZE,
|
||||
bytes.len()
|
||||
),
|
||||
});
|
||||
}
|
||||
Ok(ExtendedPublicKey {
|
||||
c_extended_public_key: c_err_to_result(|did_err| unsafe {
|
||||
BIP32ExtendedPublicKeyFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, false)
|
||||
}
|
||||
|
||||
pub(crate) fn public_child_with_legacy_flag(&self, index: u32, legacy: bool) -> Self {
|
||||
ExtendedPublicKey {
|
||||
c_extended_public_key: unsafe {
|
||||
BIP32ExtendedPublicKeyPublicChild(self.c_extended_public_key, index, legacy)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn public_child(&self, index: u32) -> Self {
|
||||
self.public_child_with_legacy_flag(index, false)
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_with_legacy_flag(
|
||||
&self,
|
||||
legacy: bool,
|
||||
) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
|
||||
unsafe {
|
||||
let malloc_ptr = BIP32ExtendedPublicKeySerialize(self.c_extended_public_key, legacy);
|
||||
Box::from_raw(malloc_ptr as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
|
||||
self.serialize_with_legacy_flag(false)
|
||||
}
|
||||
|
||||
pub fn chain_code(&self) -> ChainCode {
|
||||
ChainCode {
|
||||
c_chain_code: unsafe { BIP32ExtendedPublicKeyGetChainCode(self.c_extended_public_key) },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> G1Element {
|
||||
G1Element {
|
||||
c_element: unsafe { BIP32ExtendedPublicKeyGetPublicKey(self.c_extended_public_key) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ExtendedPublicKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe { BIP32ExtendedPublicKeyFree(self.c_extended_public_key) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::bip32::ExtendedPrivateKey;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let public_key_bytes = public_key.serialize();
|
||||
let public_key_2 = ExtendedPublicKey::from_bytes(public_key_bytes.as_ref())
|
||||
.expect("cannot deserialize extended public key");
|
||||
|
||||
assert_eq!(public_key, public_key_2);
|
||||
}
|
||||
}
|
368
src/dashbls/rust-bindings/bls-signatures/src/elements.rs
Normal file
368
src/dashbls/rust-bindings/bls-signatures/src/elements.rs
Normal file
@ -0,0 +1,368 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use bls_dash_sys::{CoreMPLDeriveChildPkUnhardened, G1ElementFree, G1ElementFromBytes, G1ElementGenerator, G1ElementGetFingerprint, G1ElementIsEqual, G1ElementSerialize, G1ElementCopy, G2ElementCopy, G2ElementFree, G2ElementFromBytes, G2ElementIsEqual, G2ElementSerialize, ThresholdPublicKeyRecover, ThresholdSignatureRecover};
|
||||
#[cfg(feature = "use_serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::{schemes::Scheme, utils::c_err_to_result, BlsError, BasicSchemeMPL};
|
||||
|
||||
// TODO Split into modules
|
||||
|
||||
pub const G1_ELEMENT_SIZE: usize = 48; // TODO somehow extract it from bls library
|
||||
pub const G2_ELEMENT_SIZE: usize = 96; // TODO somehow extract it from bls library
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub type PublicKey = G1Element;
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub type Signature = G2Element;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct G1Element {
|
||||
pub(crate) c_element: *mut c_void,
|
||||
}
|
||||
|
||||
impl PartialEq for G1Element {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe { G1ElementIsEqual(self.c_element, other.c_element) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for G1Element {}
|
||||
|
||||
impl G1Element {
|
||||
pub fn generate() -> Self {
|
||||
let c_element = unsafe { G1ElementGenerator() };
|
||||
|
||||
G1Element { c_element }
|
||||
}
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub fn verify(&self, signature: &G2Element, message: &[u8]) -> bool {
|
||||
self.verify_basic(signature, message)
|
||||
}
|
||||
|
||||
pub fn verify_basic(&self, signature: &G2Element, message: &[u8]) -> bool {
|
||||
let basic_scheme = BasicSchemeMPL::new();
|
||||
basic_scheme.verify(self, message, signature)
|
||||
}
|
||||
|
||||
pub(crate) fn from_bytes_with_legacy_flag(
|
||||
bytes: &[u8],
|
||||
legacy: bool,
|
||||
) -> Result<Self, BlsError> {
|
||||
if bytes.len() != G1_ELEMENT_SIZE {
|
||||
return Err(BlsError {
|
||||
msg: format!(
|
||||
"G1 Element size must be {}, got {}",
|
||||
G1_ELEMENT_SIZE,
|
||||
bytes.len()
|
||||
),
|
||||
});
|
||||
}
|
||||
Ok(G1Element {
|
||||
c_element: c_err_to_result(|did_err| unsafe {
|
||||
G1ElementFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, false)
|
||||
}
|
||||
|
||||
pub(crate) fn to_bytes_with_legacy_flag(&self, legacy: bool) -> Box<[u8; G1_ELEMENT_SIZE]> {
|
||||
unsafe {
|
||||
let malloc_ptr = G1ElementSerialize(self.c_element, legacy);
|
||||
Box::from_raw(malloc_ptr as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Box<[u8; G1_ELEMENT_SIZE]> {
|
||||
self.to_bytes_with_legacy_flag(false)
|
||||
}
|
||||
|
||||
pub fn derive_child_public_key_unhardened(
|
||||
&self,
|
||||
scheme: &impl Scheme,
|
||||
index: u32,
|
||||
) -> G1Element {
|
||||
G1Element {
|
||||
c_element: unsafe {
|
||||
CoreMPLDeriveChildPkUnhardened(scheme.as_mut_ptr(), self.c_element, index)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn fingerprint_with_legacy_flag(&self, legacy: bool) -> u32 {
|
||||
unsafe { G1ElementGetFingerprint(self.c_element, legacy) }
|
||||
}
|
||||
|
||||
pub fn fingerprint(&self) -> u32 {
|
||||
self.fingerprint_with_legacy_flag(false)
|
||||
}
|
||||
|
||||
pub fn threshold_recover(
|
||||
bls_ids_with_elements: &[(Vec<u8>, G1Element)],
|
||||
) -> Result<Self, BlsError> {
|
||||
unsafe {
|
||||
let len = bls_ids_with_elements.len();
|
||||
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_elements
|
||||
.iter()
|
||||
.map(|(hash, element)| {
|
||||
(
|
||||
hash.as_ptr() as *mut c_void,
|
||||
element.c_element as *mut c_void,
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
|
||||
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
|
||||
Ok(G1Element {
|
||||
c_element: c_err_to_result(|did_err| {
|
||||
ThresholdPublicKeyRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for G1Element {
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
G1Element{c_element: G1ElementCopy(self.c_element)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Serialize trait for G1Element
|
||||
impl Serialize for G1Element {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let bytes = *self.to_bytes();
|
||||
serializer.serialize_bytes(&bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Deserialize trait for G1Element
|
||||
impl<'de> Deserialize<'de> for G1Element {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct G1ElementVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for G1ElementVisitor {
|
||||
type Value = G1Element;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a byte array representing a G1Element")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
G1Element::from_bytes(bytes).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(G1ElementVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for G1Element {
|
||||
fn drop(&mut self) {
|
||||
unsafe { G1ElementFree(self.c_element) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct G2Element {
|
||||
pub(crate) c_element: *mut c_void,
|
||||
}
|
||||
|
||||
impl PartialEq for G2Element {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe { G2ElementIsEqual(self.c_element, other.c_element) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for G2Element {}
|
||||
|
||||
impl G2Element {
|
||||
pub(crate) fn from_bytes_with_legacy_flag(
|
||||
bytes: &[u8],
|
||||
legacy: bool,
|
||||
) -> Result<Self, BlsError> {
|
||||
if bytes.len() != G2_ELEMENT_SIZE {
|
||||
return Err(BlsError {
|
||||
msg: format!(
|
||||
"G2 Element size must be {}, got {}",
|
||||
G2_ELEMENT_SIZE,
|
||||
bytes.len()
|
||||
),
|
||||
});
|
||||
}
|
||||
Ok(G2Element {
|
||||
c_element: c_err_to_result(|did_err| unsafe {
|
||||
G2ElementFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, false)
|
||||
}
|
||||
|
||||
pub(crate) fn to_bytes_with_legacy_flag(&self, legacy: bool) -> Box<[u8; G2_ELEMENT_SIZE]> {
|
||||
unsafe {
|
||||
let malloc_ptr = G2ElementSerialize(self.c_element, legacy);
|
||||
Box::from_raw(malloc_ptr as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Box<[u8; G2_ELEMENT_SIZE]> {
|
||||
self.to_bytes_with_legacy_flag(false)
|
||||
}
|
||||
|
||||
pub fn threshold_recover(
|
||||
bls_ids_with_elements: &[(Vec<u8>, G2Element)],
|
||||
) -> Result<Self, BlsError> {
|
||||
unsafe {
|
||||
let len = bls_ids_with_elements.len();
|
||||
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_elements
|
||||
.iter()
|
||||
.map(|(hash, element)| {
|
||||
(
|
||||
hash.as_ptr() as *mut c_void,
|
||||
element.c_element as *mut c_void,
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
|
||||
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
|
||||
Ok(G2Element {
|
||||
c_element: c_err_to_result(|did_err| {
|
||||
ThresholdSignatureRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for G2Element {
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
G2Element{c_element: G2ElementCopy(self.c_element)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Serialize trait for G1Element
|
||||
impl Serialize for G2Element {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let bytes = *self.to_bytes();
|
||||
serializer.serialize_bytes(&bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Deserialize trait for G1Element
|
||||
impl<'de> Deserialize<'de> for G2Element {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct G2ElementVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for G2ElementVisitor {
|
||||
type Value = G2Element;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a byte array representing a G2Element")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
G2Element::from_bytes(bytes).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(G2ElementVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for G2Element {
|
||||
fn drop(&mut self) {
|
||||
unsafe { G2ElementFree(self.c_element) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
schemes::{AugSchemeMPL, Scheme},
|
||||
PrivateKey,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn g1_serialize_deserialize() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let scheme = AugSchemeMPL::new();
|
||||
let sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
|
||||
|
||||
let g1 = sk.g1_element().expect("cannot get G1 element");
|
||||
let g1_bytes = g1.to_bytes();
|
||||
let g1_2 =
|
||||
G1Element::from_bytes(g1_bytes.as_ref()).expect("cannot build G1 element from bytes");
|
||||
|
||||
assert_eq!(g1, g1_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn g2_serialize_deserialize() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let scheme = AugSchemeMPL::new();
|
||||
let sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
|
||||
|
||||
let g2 = scheme.sign(&sk, b"ayy");
|
||||
let g2_bytes = g2.to_bytes();
|
||||
let g2_2 =
|
||||
G2Element::from_bytes(g2_bytes.as_ref()).expect("cannot build G2 element from bytes");
|
||||
|
||||
assert_eq!(g2, g2_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_generate_new_g1_element() {
|
||||
let g1_element = G1Element::generate();
|
||||
|
||||
assert_eq!(g1_element.to_bytes().len(), 48);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_fingerprint() {
|
||||
let bytes = [
|
||||
151, 241, 211, 167, 49, 151, 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104,
|
||||
140, 79, 151, 116, 185, 5, 161, 78, 58, 63, 23, 27, 172, 88, 108, 85, 232, 63, 249,
|
||||
122, 26, 239, 251, 58, 240, 10, 219, 34, 198, 187,
|
||||
];
|
||||
|
||||
let g1_element =
|
||||
G1Element::from_bytes(&bytes).expect("should create g1 element from bytes");
|
||||
|
||||
assert_eq!(g1_element.fingerprint(), 2093959050);
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
mod private_key;
|
||||
mod public_key;
|
@ -0,0 +1,58 @@
|
||||
use crate::{
|
||||
bip32::{ExtendedPrivateKey, ExtendedPublicKey},
|
||||
BlsError,
|
||||
};
|
||||
|
||||
impl ExtendedPrivateKey {
|
||||
pub fn private_child_legacy(&self, index: u32) -> Self {
|
||||
self.private_child_with_legacy_flag(index, true)
|
||||
}
|
||||
|
||||
pub fn extended_public_key_legacy(&self) -> Result<ExtendedPublicKey, BlsError> {
|
||||
self.extended_public_key_with_legacy_flag(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize_legacy() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key_legacy()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let public_key_bytes = public_key.serialize_legacy();
|
||||
let public_key_2 = ExtendedPublicKey::from_bytes_legacy(public_key_bytes.as_ref())
|
||||
.expect("cannot deserialize extended public key");
|
||||
|
||||
assert_eq!(public_key, public_key_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hierarchical_deterministic_keys_legacy() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key_legacy()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let private_child = private_key.private_child_legacy(1337);
|
||||
let private_grandchild = private_child.private_child_legacy(420);
|
||||
|
||||
let public_child = public_key.public_child_legacy(1337);
|
||||
let public_grandchild = public_child.public_child_legacy(420);
|
||||
|
||||
assert_eq!(
|
||||
public_grandchild,
|
||||
private_grandchild
|
||||
.extended_public_key_legacy()
|
||||
.expect("cannot get extended public key")
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
use crate::{
|
||||
bip32::{ExtendedPublicKey, BIP32_EXTENDED_PUBLIC_KEY_SIZE},
|
||||
BlsError,
|
||||
};
|
||||
|
||||
impl ExtendedPublicKey {
|
||||
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, true)
|
||||
}
|
||||
|
||||
pub fn public_child_legacy(&self, index: u32) -> Self {
|
||||
self.public_child_with_legacy_flag(index, true)
|
||||
}
|
||||
|
||||
pub fn serialize_legacy(&self) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
|
||||
self.serialize_with_legacy_flag(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::bip32::ExtendedPrivateKey;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize_legacy() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key_legacy()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let public_key_bytes = public_key.serialize_legacy();
|
||||
let public_key_2 = ExtendedPublicKey::from_bytes_legacy(public_key_bytes.as_ref())
|
||||
.expect("cannot deserialize extended public key");
|
||||
|
||||
assert_eq!(public_key, public_key_2);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
use crate::{BlsError, G1Element, G2Element, G1_ELEMENT_SIZE, G2_ELEMENT_SIZE};
|
||||
|
||||
impl G1Element {
|
||||
pub fn serialize_legacy(&self) -> Box<[u8; G1_ELEMENT_SIZE]> {
|
||||
self.to_bytes_with_legacy_flag(true)
|
||||
}
|
||||
|
||||
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, true)
|
||||
}
|
||||
|
||||
pub fn fingerprint_legacy(&self) -> u32 {
|
||||
self.fingerprint_with_legacy_flag(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Element {
|
||||
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
|
||||
Self::from_bytes_with_legacy_flag(bytes, true)
|
||||
}
|
||||
|
||||
pub fn serialize_legacy(&self) -> Box<[u8; G2_ELEMENT_SIZE]> {
|
||||
self.to_bytes_with_legacy_flag(true)
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
mod bip32;
|
||||
mod elements;
|
104
src/dashbls/rust-bindings/bls-signatures/src/lib.rs
Normal file
104
src/dashbls/rust-bindings/bls-signatures/src/lib.rs
Normal file
@ -0,0 +1,104 @@
|
||||
mod elements;
|
||||
mod private_key;
|
||||
mod schemes;
|
||||
mod utils;
|
||||
|
||||
#[cfg(feature = "legacy")]
|
||||
mod legacy;
|
||||
|
||||
#[cfg(feature = "bip32")]
|
||||
pub mod bip32;
|
||||
|
||||
use std::{error::Error, fmt::Display};
|
||||
|
||||
pub use elements::{G1Element, G2Element, G1_ELEMENT_SIZE, G2_ELEMENT_SIZE};
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub use elements::{PublicKey, Signature};
|
||||
pub use private_key::{PrivateKey, PRIVATE_KEY_SIZE};
|
||||
pub use schemes::{AugSchemeMPL, BasicSchemeMPL, LegacySchemeMPL, Scheme};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct BlsError {
|
||||
// Need to use owned version as each time BLS has an error its binding glue overwrites error
|
||||
// message variable.
|
||||
msg: String,
|
||||
}
|
||||
|
||||
impl Display for BlsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for BlsError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::schemes::{AugSchemeMPL, Scheme};
|
||||
|
||||
#[test]
|
||||
fn basic_sign() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let bad_seed = b"weedseedweedseedweedseedweedseed";
|
||||
|
||||
let scheme = AugSchemeMPL::new();
|
||||
|
||||
let private_key_before =
|
||||
PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
|
||||
|
||||
// Also test private key serialization
|
||||
let private_key_bytes = private_key_before.to_bytes();
|
||||
let private_key = PrivateKey::from_bytes(private_key_bytes.as_slice(), false)
|
||||
.expect("cannot build private key from bytes");
|
||||
drop(private_key_bytes);
|
||||
|
||||
let public_key = private_key.g1_element().expect("unable to get public key");
|
||||
|
||||
let private_key_bad =
|
||||
PrivateKey::key_gen(&scheme, bad_seed).expect("unable to generate private key");
|
||||
let public_key_bad = private_key_bad
|
||||
.g1_element()
|
||||
.expect("unable to get public key");
|
||||
|
||||
let message = b"Evgeny owns 1337 dash no cap";
|
||||
|
||||
let signature = scheme.sign(&private_key, message);
|
||||
let verify = scheme.verify(&public_key, message, &signature);
|
||||
assert!(verify);
|
||||
let verify_bad = scheme.verify(&public_key_bad, message, &signature);
|
||||
assert!(!verify_bad);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_seed() {
|
||||
let seed = b"lol";
|
||||
let scheme = AugSchemeMPL::new();
|
||||
let private_key = PrivateKey::key_gen(&scheme, seed);
|
||||
|
||||
assert!(matches!(
|
||||
private_key,
|
||||
Err(BlsError { msg }) if msg == "Seed size must be at least 32 bytes"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hd_keys_deterministic() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let scheme = AugSchemeMPL::new();
|
||||
|
||||
let master_sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
|
||||
let master_pk = master_sk.g1_element().expect("unable to get public key");
|
||||
|
||||
let child_sk_u = master_sk.derive_child_private_key_unhardened(&scheme, 22);
|
||||
let grandchild_sk_u = child_sk_u.derive_child_private_key_unhardened(&scheme, 0);
|
||||
|
||||
let child_pk_u = master_pk.derive_child_public_key_unhardened(&scheme, 22);
|
||||
let grandchild_pk_u = child_pk_u.derive_child_public_key_unhardened(&scheme, 0);
|
||||
|
||||
assert_eq!(
|
||||
grandchild_pk_u,
|
||||
grandchild_sk_u.g1_element().expect("cannot get public key")
|
||||
);
|
||||
}
|
||||
}
|
315
src/dashbls/rust-bindings/bls-signatures/src/private_key.rs
Executable file
315
src/dashbls/rust-bindings/bls-signatures/src/private_key.rs
Executable file
@ -0,0 +1,315 @@
|
||||
use std::{ffi::c_void, ops::Mul};
|
||||
|
||||
use bls_dash_sys::{
|
||||
CoreMPLDeriveChildSk, CoreMPLDeriveChildSkUnhardened, CoreMPLKeyGen, G1ElementMul,
|
||||
PrivateKeyFree, PrivateKeyFromBytes, PrivateKeyFromSeedBIP32, PrivateKeyGetG1Element,
|
||||
PrivateKeyIsEqual, PrivateKeySerialize, ThresholdPrivateKeyRecover,
|
||||
};
|
||||
use rand::{prelude::StdRng, Rng};
|
||||
#[cfg(feature = "use_serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::{schemes::Scheme, utils::{c_err_to_result, SecureBox}, BasicSchemeMPL, BlsError, G1Element, G2Element};
|
||||
|
||||
pub const PRIVATE_KEY_SIZE: usize = 32; // TODO somehow extract it from bls library
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PrivateKey {
|
||||
pub(crate) c_private_key: *mut c_void,
|
||||
}
|
||||
|
||||
impl PartialEq for PrivateKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
unsafe { PrivateKeyIsEqual(self.c_private_key, other.c_private_key) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for PrivateKey {}
|
||||
|
||||
impl Mul<G1Element> for PrivateKey {
|
||||
type Output = Result<G1Element, BlsError>;
|
||||
|
||||
fn mul(self, rhs: G1Element) -> Self::Output {
|
||||
Ok(G1Element {
|
||||
c_element: c_err_to_result(|_| unsafe {
|
||||
G1ElementMul(rhs.c_element, self.c_private_key)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<PrivateKey> for G1Element {
|
||||
type Output = Result<G1Element, BlsError>;
|
||||
|
||||
fn mul(self, rhs: PrivateKey) -> Self::Output {
|
||||
rhs * self
|
||||
}
|
||||
}
|
||||
|
||||
impl PrivateKey {
|
||||
pub(crate) fn as_mut_ptr(&self) -> *mut c_void {
|
||||
self.c_private_key
|
||||
}
|
||||
|
||||
// TODO Rename to from_seed
|
||||
pub fn key_gen(scheme: &impl Scheme, seed: &[u8]) -> Result<Self, BlsError> {
|
||||
Ok(PrivateKey {
|
||||
c_private_key: c_err_to_result(|did_err| unsafe {
|
||||
CoreMPLKeyGen(
|
||||
scheme.as_mut_ptr(),
|
||||
seed.as_ptr() as *const _,
|
||||
seed.len(),
|
||||
did_err,
|
||||
)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub fn generate_dash(rng: &mut StdRng) -> Result<Self, BlsError> {
|
||||
let seed = rng.gen::<[u8; 32]>();
|
||||
let scheme = BasicSchemeMPL::new();
|
||||
Ok(PrivateKey {
|
||||
c_private_key: c_err_to_result(|did_err| unsafe {
|
||||
CoreMPLKeyGen(
|
||||
scheme.as_mut_ptr(),
|
||||
seed.as_ptr() as *const _,
|
||||
seed.len(),
|
||||
did_err,
|
||||
)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub fn sign(&self, message: &[u8]) -> G2Element {
|
||||
self.sign_basic(message)
|
||||
}
|
||||
|
||||
pub fn sign_basic(&self, message: &[u8]) -> G2Element {
|
||||
let scheme = BasicSchemeMPL::new();
|
||||
scheme.sign(self, message)
|
||||
}
|
||||
|
||||
#[cfg(feature = "dash_helpers")]
|
||||
pub fn generate_dash_many(count: usize, rng: &mut StdRng) -> Result<Vec<Self>, BlsError> {
|
||||
(0..count)
|
||||
.into_iter()
|
||||
.map(|_| Self::generate_dash(rng))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn g1_element(&self) -> Result<G1Element, BlsError> {
|
||||
Ok(G1Element {
|
||||
c_element: c_err_to_result(|did_err| unsafe {
|
||||
PrivateKeyGetG1Element(self.c_private_key, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> SecureBox {
|
||||
// `PrivateKeySerialize` internally securely allocates memory which we have to
|
||||
// wrap safely
|
||||
unsafe {
|
||||
SecureBox::from_ptr(
|
||||
PrivateKeySerialize(self.c_private_key) as *mut u8,
|
||||
PRIVATE_KEY_SIZE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8], mod_order: bool) -> Result<Self, BlsError> {
|
||||
if bytes.len() != PRIVATE_KEY_SIZE {
|
||||
return Err(BlsError {
|
||||
msg: format!(
|
||||
"Private key size must be {}, got {}",
|
||||
PRIVATE_KEY_SIZE,
|
||||
bytes.len()
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
let c_private_key = c_err_to_result(|did_err| unsafe {
|
||||
PrivateKeyFromBytes(bytes.as_ptr() as *const c_void, mod_order, did_err)
|
||||
})?;
|
||||
|
||||
Ok(PrivateKey { c_private_key })
|
||||
}
|
||||
|
||||
pub fn from_bip32_seed(bytes: &[u8]) -> Self {
|
||||
let c_private_key =
|
||||
unsafe { PrivateKeyFromSeedBIP32(bytes.as_ptr() as *const c_void, bytes.len()) };
|
||||
|
||||
PrivateKey { c_private_key }
|
||||
}
|
||||
|
||||
pub fn derive_child_private_key(&self, scheme: &impl Scheme, index: u32) -> PrivateKey {
|
||||
PrivateKey {
|
||||
c_private_key: unsafe {
|
||||
CoreMPLDeriveChildSk(scheme.as_mut_ptr(), self.c_private_key, index)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive_child_private_key_unhardened(
|
||||
&self,
|
||||
scheme: &impl Scheme,
|
||||
index: u32,
|
||||
) -> PrivateKey {
|
||||
PrivateKey {
|
||||
c_private_key: unsafe {
|
||||
CoreMPLDeriveChildSkUnhardened(scheme.as_mut_ptr(), self.c_private_key, index)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn threshold_recover(
|
||||
bls_ids_with_private_keys: &[(Vec<u8>, PrivateKey)],
|
||||
) -> Result<Self, BlsError> {
|
||||
unsafe {
|
||||
let len = bls_ids_with_private_keys.len();
|
||||
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_private_keys
|
||||
.iter()
|
||||
.map(|(hash, element)| (hash.as_ptr() as *mut c_void, element.c_private_key))
|
||||
.unzip();
|
||||
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
|
||||
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
|
||||
Ok(PrivateKey {
|
||||
c_private_key: c_err_to_result(|did_err| {
|
||||
ThresholdPrivateKeyRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for PrivateKey {
|
||||
fn clone(&self) -> Self {
|
||||
// Serialize the element
|
||||
let bytes = self.to_bytes();
|
||||
// We can panic
|
||||
PrivateKey::from_bytes(bytes.as_slice(), false).expect("expected bytes to be valid")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Serialize trait for G1Element
|
||||
impl Serialize for PrivateKey {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(self.to_bytes().as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
// Implement Deserialize trait for G1Element
|
||||
impl<'de> Deserialize<'de> for PrivateKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct PrivateKeyElementVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for PrivateKeyElementVisitor {
|
||||
type Value = PrivateKey;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a byte array representing a Private Key")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
PrivateKey::from_bytes(bytes, false).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(PrivateKeyElementVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PrivateKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe { PrivateKeyFree(self.c_private_key) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::schemes::AugSchemeMPL;
|
||||
|
||||
#[test]
|
||||
fn serialize_deserialize() {
|
||||
let seed = b"seedweedseedweedseedweedseedweed";
|
||||
let scheme = AugSchemeMPL::new();
|
||||
let sk1 = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
|
||||
let sk1_bytes = sk1.to_bytes();
|
||||
let sk2 = PrivateKey::from_bytes(sk1_bytes.as_slice(), false)
|
||||
.expect("cannot build private key from bytes");
|
||||
|
||||
assert_eq!(sk1, sk2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_private_key_from_bip32_bytes() {
|
||||
let long_seed = [
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 1, 2,
|
||||
];
|
||||
let long_private_key_test_data = [
|
||||
50, 67, 148, 112, 207, 6, 210, 118, 137, 125, 27, 144, 105, 189, 214, 228, 68, 83, 144,
|
||||
205, 80, 105, 133, 222, 14, 26, 28, 136, 167, 111, 241, 118,
|
||||
];
|
||||
let long_private_key = PrivateKey::from_bip32_seed(&long_seed);
|
||||
assert_eq!(*long_private_key.to_bytes(), long_private_key_test_data);
|
||||
|
||||
// Previously didn't work with seed with length != 32
|
||||
let short_seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let short_private_key_test_data = [
|
||||
70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30,
|
||||
185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189,
|
||||
];
|
||||
let short_private_key = PrivateKey::from_bip32_seed(&short_seed);
|
||||
assert_eq!(*short_private_key.to_bytes(), short_private_key_test_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keys_multiplication() {
|
||||
// 46891c2cec49593c81921e473db7480029e0fc1eb933c6b93d81f5370eb19fbd
|
||||
let private_key_data = [
|
||||
70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30,
|
||||
185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189,
|
||||
];
|
||||
// 0e2f9055c17eb13221d8b41833468ab49f7d4e874ddf4b217f5126392a608fd48ccab3510548f1da4f397c1ad4f8e01a
|
||||
let public_key_data = [
|
||||
14, 47, 144, 85, 193, 126, 177, 50, 33, 216, 180, 24, 51, 70, 138, 180, 159, 125, 78,
|
||||
135, 77, 223, 75, 33, 127, 81, 38, 57, 42, 96, 143, 212, 140, 202, 179, 81, 5, 72, 241,
|
||||
218, 79, 57, 124, 26, 212, 248, 224, 26,
|
||||
];
|
||||
// 03fd387c4d4c66ec9dcdb31ef0c08ad881090dcda13d4b2c9cbc5ef264ff4dc7
|
||||
let expected_data = [
|
||||
3, 253, 56, 124, 77, 76, 102, 236, 157, 205, 179, 30, 240, 192, 138, 216, 129, 9, 13,
|
||||
205, 161, 61, 75, 44, 156, 188, 94, 242, 100, 255, 77, 199,
|
||||
];
|
||||
let private_key = PrivateKey::from_bytes(&private_key_data, false).unwrap();
|
||||
let public_key = G1Element::from_bytes_legacy(&public_key_data).unwrap();
|
||||
let result = (private_key * public_key).unwrap();
|
||||
assert_eq!(
|
||||
&result.serialize_legacy()[..32],
|
||||
&expected_data,
|
||||
"should match"
|
||||
);
|
||||
let private_key = PrivateKey::from_bytes(&private_key_data, false).unwrap();
|
||||
let public_key = G1Element::from_bytes_legacy(&public_key_data).unwrap();
|
||||
let result = (public_key * private_key).unwrap();
|
||||
assert_eq!(
|
||||
&result.serialize_legacy()[..32],
|
||||
&expected_data,
|
||||
"should match"
|
||||
);
|
||||
}
|
||||
}
|
434
src/dashbls/rust-bindings/bls-signatures/src/schemes.rs
Normal file
434
src/dashbls/rust-bindings/bls-signatures/src/schemes.rs
Normal file
@ -0,0 +1,434 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use bls_dash_sys::{
|
||||
AugSchemeMPLAggregateVerify, AugSchemeMPLFree, AugSchemeMPLSign, AugSchemeMPLVerify,
|
||||
BasicSchemeMPLAggregateVerify, BasicSchemeMPLFree, CoreMPLAggregatePubKeys,
|
||||
CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure,
|
||||
LegacySchemeMPLAggregateVerify, LegacySchemeMPLSign, LegacySchemeMPLVerify,
|
||||
LegacySchemeMPLVerifySecure, NewAugSchemeMPL, NewBasicSchemeMPL, NewLegacySchemeMPL,
|
||||
};
|
||||
|
||||
// TODO Split into modules
|
||||
use crate::{private_key::PrivateKey, G1Element, G2Element};
|
||||
|
||||
pub trait Scheme {
|
||||
fn as_mut_ptr(&self) -> *mut c_void;
|
||||
|
||||
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element;
|
||||
|
||||
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool;
|
||||
|
||||
fn verify_secure<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
message: &[u8],
|
||||
signature: &G2Element,
|
||||
) -> bool {
|
||||
let mut g1_pointers = public_keys
|
||||
.into_iter()
|
||||
.map(|g1| g1.c_element)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
unsafe {
|
||||
CoreMPLVerifySecure(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
signature.c_element,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_public_keys<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
) -> G1Element {
|
||||
let mut g1_pointers = public_keys
|
||||
.into_iter()
|
||||
.map(|g1| g1.c_element)
|
||||
.collect::<Vec<_>>();
|
||||
G1Element {
|
||||
c_element: unsafe {
|
||||
CoreMPLAggregatePubKeys(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_sigs<'a>(&self, sigs: impl IntoIterator<Item = &'a G2Element>) -> G2Element {
|
||||
let mut g2_pointers = sigs.into_iter().map(|g2| g2.c_element).collect::<Vec<_>>();
|
||||
G2Element {
|
||||
c_element: unsafe {
|
||||
CoreMPLAggregateSigs(
|
||||
self.as_mut_ptr(),
|
||||
g2_pointers.as_mut_ptr(),
|
||||
g2_pointers.len(),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_verify<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
messages: impl IntoIterator<Item = &'a [u8]>,
|
||||
signature: &G2Element,
|
||||
) -> bool;
|
||||
}
|
||||
|
||||
struct AggregateVerifyArgs {
|
||||
g1_pointers: Vec<*mut c_void>,
|
||||
messages_pointers: Vec<*const u8>,
|
||||
messages_lengths: Vec<usize>,
|
||||
}
|
||||
|
||||
// TODO put constructor inside struct?
|
||||
fn prepare_aggregate_verify_args<'a>(
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
messages: impl IntoIterator<Item = &'a [u8]>,
|
||||
) -> AggregateVerifyArgs {
|
||||
let g1_pointers = public_keys
|
||||
.into_iter()
|
||||
.map(|g1| g1.c_element)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut messages_pointers = Vec::new();
|
||||
let mut messages_lengths = Vec::new();
|
||||
|
||||
for m in messages.into_iter() {
|
||||
messages_pointers.push(m.as_ptr());
|
||||
messages_lengths.push(m.len());
|
||||
}
|
||||
|
||||
AggregateVerifyArgs {
|
||||
g1_pointers,
|
||||
messages_pointers,
|
||||
messages_lengths,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BasicSchemeMPL {
|
||||
scheme: *mut c_void,
|
||||
}
|
||||
|
||||
impl BasicSchemeMPL {
|
||||
pub fn new() -> Self {
|
||||
BasicSchemeMPL {
|
||||
scheme: unsafe { NewBasicSchemeMPL() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheme for BasicSchemeMPL {
|
||||
fn as_mut_ptr(&self) -> *mut c_void {
|
||||
self.scheme
|
||||
}
|
||||
|
||||
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element {
|
||||
G2Element {
|
||||
c_element: unsafe {
|
||||
CoreMPLSign(
|
||||
self.scheme,
|
||||
private_key.as_mut_ptr(),
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
|
||||
unsafe {
|
||||
CoreMPLVerify(
|
||||
self.scheme,
|
||||
public_key.c_element,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_verify<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
messages: impl IntoIterator<Item = &'a [u8]>,
|
||||
signature: &G2Element,
|
||||
) -> bool {
|
||||
let AggregateVerifyArgs {
|
||||
mut g1_pointers,
|
||||
mut messages_pointers,
|
||||
messages_lengths: mut messages_lengthes,
|
||||
} = prepare_aggregate_verify_args(public_keys, messages);
|
||||
|
||||
unsafe {
|
||||
BasicSchemeMPLAggregateVerify(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
messages_pointers.as_mut_ptr() as *mut _,
|
||||
messages_lengthes.as_mut_ptr() as *mut _,
|
||||
messages_pointers.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LegacySchemeMPL {
|
||||
scheme: *mut c_void,
|
||||
}
|
||||
|
||||
impl LegacySchemeMPL {
|
||||
pub fn new() -> Self {
|
||||
LegacySchemeMPL {
|
||||
scheme: unsafe { NewLegacySchemeMPL() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheme for LegacySchemeMPL {
|
||||
fn as_mut_ptr(&self) -> *mut c_void {
|
||||
self.scheme
|
||||
}
|
||||
|
||||
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element {
|
||||
G2Element {
|
||||
c_element: unsafe {
|
||||
LegacySchemeMPLSign(
|
||||
self.scheme,
|
||||
private_key.as_mut_ptr(),
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
|
||||
unsafe {
|
||||
LegacySchemeMPLVerify(
|
||||
self.scheme,
|
||||
public_key.c_element,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_secure<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
message: &[u8],
|
||||
signature: &G2Element,
|
||||
) -> bool {
|
||||
let mut g1_pointers = public_keys
|
||||
.into_iter()
|
||||
.map(|g1| g1.c_element)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
unsafe {
|
||||
LegacySchemeMPLVerifySecure(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
signature.c_element,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_verify<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
messages: impl IntoIterator<Item = &'a [u8]>,
|
||||
signature: &G2Element,
|
||||
) -> bool {
|
||||
let AggregateVerifyArgs {
|
||||
mut g1_pointers,
|
||||
mut messages_pointers,
|
||||
messages_lengths: mut messages_lengthes,
|
||||
} = prepare_aggregate_verify_args(public_keys, messages);
|
||||
|
||||
unsafe {
|
||||
LegacySchemeMPLAggregateVerify(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
messages_pointers.as_mut_ptr() as *mut _,
|
||||
messages_lengthes.as_mut_ptr() as *mut _,
|
||||
messages_pointers.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BasicSchemeMPL {
|
||||
fn drop(&mut self) {
|
||||
unsafe { BasicSchemeMPLFree(self.scheme) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AugSchemeMPL {
|
||||
scheme: *mut c_void,
|
||||
}
|
||||
|
||||
impl AugSchemeMPL {
|
||||
pub fn new() -> Self {
|
||||
AugSchemeMPL {
|
||||
scheme: unsafe { NewAugSchemeMPL() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheme for AugSchemeMPL {
|
||||
fn as_mut_ptr(&self) -> *mut c_void {
|
||||
self.scheme
|
||||
}
|
||||
|
||||
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element {
|
||||
G2Element {
|
||||
c_element: unsafe {
|
||||
AugSchemeMPLSign(
|
||||
self.scheme,
|
||||
private_key.as_mut_ptr(),
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
|
||||
unsafe {
|
||||
AugSchemeMPLVerify(
|
||||
self.scheme,
|
||||
public_key.c_element,
|
||||
message.as_ptr() as *const _,
|
||||
message.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn aggregate_verify<'a>(
|
||||
&self,
|
||||
public_keys: impl IntoIterator<Item = &'a G1Element>,
|
||||
messages: impl IntoIterator<Item = &'a [u8]>,
|
||||
signature: &G2Element,
|
||||
) -> bool {
|
||||
let AggregateVerifyArgs {
|
||||
mut g1_pointers,
|
||||
mut messages_pointers,
|
||||
mut messages_lengths,
|
||||
} = prepare_aggregate_verify_args(public_keys, messages);
|
||||
|
||||
unsafe {
|
||||
AugSchemeMPLAggregateVerify(
|
||||
self.as_mut_ptr(),
|
||||
g1_pointers.as_mut_ptr(),
|
||||
g1_pointers.len(),
|
||||
messages_pointers.as_mut_ptr() as *mut _,
|
||||
messages_lengths.as_mut_ptr() as *mut _,
|
||||
messages_pointers.len(),
|
||||
signature.c_element,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AugSchemeMPL {
|
||||
fn drop(&mut self) {
|
||||
unsafe { AugSchemeMPLFree(self.scheme) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn verify_aggregate(scheme: impl Scheme) {
|
||||
let seed1 = b"seedweedseedweedseedweedseedweed";
|
||||
let seed2 = b"weedseedweedseedweedseedweedseed";
|
||||
let seed3 = b"seedseedseedseedweedweedweedweed";
|
||||
let seed4 = b"weedweedweedweedweedweedweedweed";
|
||||
|
||||
let private_key_1 =
|
||||
PrivateKey::key_gen(&scheme, seed1).expect("unable to generate private key");
|
||||
let private_key_2 =
|
||||
PrivateKey::key_gen(&scheme, seed2).expect("unable to generate private key");
|
||||
let private_key_3 =
|
||||
PrivateKey::key_gen(&scheme, seed3).expect("unable to generate private key");
|
||||
let private_key_4 =
|
||||
PrivateKey::key_gen(&scheme, seed4).expect("unable to generate private key");
|
||||
|
||||
let public_key_1 = private_key_1
|
||||
.g1_element()
|
||||
.expect("unable to get public key");
|
||||
let public_key_2 = private_key_2
|
||||
.g1_element()
|
||||
.expect("unable to get public key");
|
||||
let public_key_3 = private_key_3
|
||||
.g1_element()
|
||||
.expect("unable to get public key");
|
||||
let public_key_4 = private_key_4
|
||||
.g1_element()
|
||||
.expect("unable to get public key");
|
||||
|
||||
let message_1 = b"ayya";
|
||||
let message_2 = b"ayyb";
|
||||
let message_3 = b"ayyc";
|
||||
let message_4 = b"ayyd";
|
||||
|
||||
let signature_1 = scheme.sign(&private_key_1, message_1);
|
||||
let signature_2 = scheme.sign(&private_key_2, message_2);
|
||||
let signature_3 = scheme.sign(&private_key_3, message_3);
|
||||
let signature_4 = scheme.sign(&private_key_4, message_4);
|
||||
|
||||
let signature_agg = scheme.aggregate_sigs([&signature_1, &signature_2, &signature_3]);
|
||||
|
||||
let verify = scheme.aggregate_verify(
|
||||
[&public_key_1, &public_key_2, &public_key_3],
|
||||
[message_1.as_ref(), message_2.as_ref(), message_3.as_ref()],
|
||||
&signature_agg,
|
||||
);
|
||||
assert!(verify);
|
||||
|
||||
// Arbitrary trees of aggregates
|
||||
let signature_agg_final = scheme.aggregate_sigs([&signature_agg, &signature_4]);
|
||||
let verify_final = scheme.aggregate_verify(
|
||||
[&public_key_1, &public_key_2, &public_key_3, &public_key_4],
|
||||
[
|
||||
message_1.as_ref(),
|
||||
message_2.as_ref(),
|
||||
message_3.as_ref(),
|
||||
message_4.as_ref(),
|
||||
],
|
||||
&signature_agg_final,
|
||||
);
|
||||
assert!(verify_final);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_aggregate_aug() {
|
||||
verify_aggregate(AugSchemeMPL::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_aggregate_basic() {
|
||||
verify_aggregate(BasicSchemeMPL::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_aggregate_legacy() {
|
||||
verify_aggregate(LegacySchemeMPL::new());
|
||||
}
|
||||
}
|
71
src/dashbls/rust-bindings/bls-signatures/src/utils.rs
Normal file
71
src/dashbls/rust-bindings/bls-signatures/src/utils.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use core::slice;
|
||||
use std::{
|
||||
ffi::{c_void, CStr},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use bls_dash_sys::{GetLastErrorMsg, SecAllocBytes, SecFree};
|
||||
|
||||
use crate::BlsError;
|
||||
|
||||
pub(crate) fn c_err_to_result<T, F>(f: F) -> Result<T, BlsError>
|
||||
where
|
||||
F: FnOnce(&mut bool) -> T,
|
||||
{
|
||||
let mut did_error = false;
|
||||
let result = f(&mut did_error);
|
||||
|
||||
if did_error {
|
||||
let error_message = unsafe { CStr::from_ptr(GetLastErrorMsg()) };
|
||||
Err(BlsError {
|
||||
msg: String::from_utf8_lossy(error_message.to_bytes()).into_owned(),
|
||||
})
|
||||
} else {
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SecureBox {
|
||||
c_sec_alloc: *mut u8,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl SecureBox {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new(len: usize) -> Self {
|
||||
SecureBox {
|
||||
c_sec_alloc: unsafe { SecAllocBytes(len) },
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn from_ptr(ptr: *mut u8, len: usize) -> Self {
|
||||
SecureBox {
|
||||
c_sec_alloc: ptr,
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
// Somewhere it returns *mut c_void
|
||||
pub(crate) fn as_mut_ptr(&mut self) -> *mut c_void {
|
||||
self.c_sec_alloc as *mut c_void
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.c_sec_alloc, self.len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SecureBox {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SecureBox {
|
||||
fn drop(&mut self) {
|
||||
unsafe { SecFree(self.as_mut_ptr()) }
|
||||
}
|
||||
}
|
7
src/dashbls/rust-bindings/example/Cargo.toml
Normal file
7
src/dashbls/rust-bindings/example/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "example"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bls-signatures = { path = "../bls-signatures" }
|
51
src/dashbls/rust-bindings/example/src/main.rs
Normal file
51
src/dashbls/rust-bindings/example/src/main.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use bls_signatures::{bip32::ExtendedPrivateKey, LegacySchemeMPL, Scheme};
|
||||
|
||||
const SEED: &'static [u8] = b"seedweedseedweedseedweedseedweed";
|
||||
|
||||
fn check_bip32_hd_keys() {
|
||||
println!("Check BIP32 hierarchical deterministic keys work");
|
||||
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(SEED).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let private_child = private_key.private_child(1337);
|
||||
let private_grandchild = private_child.private_child(420);
|
||||
|
||||
let public_child = public_key.public_child(1337);
|
||||
let public_grandchild = public_child.public_child(420);
|
||||
|
||||
assert_eq!(
|
||||
public_grandchild,
|
||||
private_grandchild
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key")
|
||||
);
|
||||
}
|
||||
|
||||
fn check_bip32_legacy_scheme() {
|
||||
println!("Check BIP32 signing works");
|
||||
|
||||
let private_key =
|
||||
ExtendedPrivateKey::from_seed(SEED).expect("cannot generate extended private key");
|
||||
let public_key = private_key
|
||||
.extended_public_key()
|
||||
.expect("cannot get extended public key");
|
||||
|
||||
let scheme = LegacySchemeMPL::new();
|
||||
let message = b"dash is og";
|
||||
let signature = scheme.sign(&private_key.private_key(), message);
|
||||
|
||||
assert!(scheme.verify(&public_key.public_key(), message, &signature));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Run some checks to see if everything is linked up to original BLS library:");
|
||||
|
||||
check_bip32_hd_keys();
|
||||
check_bip32_legacy_scheme();
|
||||
|
||||
println!("All checks passed!");
|
||||
}
|
41
src/dashbls/setjmp_patch.diff
Normal file
41
src/dashbls/setjmp_patch.diff
Normal file
@ -0,0 +1,41 @@
|
||||
diff --git a/include/relic_err.h b/include/relic_err.h
|
||||
index e16f71fe..a4adb107 100644
|
||||
--- a/include/relic_err.h
|
||||
+++ b/include/relic_err.h
|
||||
@@ -33,7 +33,6 @@
|
||||
#define RLC_ERR_H
|
||||
|
||||
#include <stdint.h>
|
||||
-#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -43,6 +42,10 @@
|
||||
#include "relic_util.h"
|
||||
#include "relic_label.h"
|
||||
|
||||
+#ifdef CHECK
|
||||
+#include <setjmp.h>
|
||||
+#endif
|
||||
+
|
||||
/*============================================================================*/
|
||||
/* Constant definitions */
|
||||
/*============================================================================*/
|
||||
@@ -94,6 +97,8 @@ enum errors {
|
||||
*/
|
||||
typedef int err_t;
|
||||
|
||||
+#ifdef CHECK
|
||||
+
|
||||
/**
|
||||
* Type that describes an error status, including the error code and the program
|
||||
* location where the error occurred.
|
||||
@@ -107,6 +112,8 @@ typedef struct _sts_t {
|
||||
int block;
|
||||
} sts_t;
|
||||
|
||||
+#endif
|
||||
+
|
||||
/*============================================================================*/
|
||||
/* Macro definitions */
|
||||
/*============================================================================*/
|
@ -11,8 +11,7 @@ add_library(dashbls
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extendedpublickey.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/legacy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp)
|
||||
|
||||
target_include_directories(dashbls
|
||||
PUBLIC
|
||||
|
@ -98,6 +98,14 @@ G1Element G1Element::FromNative(const g1_t element)
|
||||
return ele;
|
||||
}
|
||||
|
||||
G1Element G1Element::Copy() {
|
||||
G1Element ele;
|
||||
g1_copy(ele.p, this->p);
|
||||
|
||||
return ele;
|
||||
}
|
||||
|
||||
|
||||
G1Element G1Element::FromMessage(const std::vector<uint8_t>& message,
|
||||
const uint8_t* dst,
|
||||
int dst_len)
|
||||
@ -246,6 +254,7 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy)
|
||||
|
||||
if (fLegacy) {
|
||||
std::memcpy(buffer + 1, bytes.begin(), G2Element::SIZE);
|
||||
buffer[0] = 0x00;
|
||||
} else {
|
||||
std::memcpy(buffer + 1, bytes.begin() + G2Element::SIZE / 2, G2Element::SIZE / 2);
|
||||
std::memcpy(buffer + 1 + G2Element::SIZE / 2, bytes.begin(), G2Element::SIZE / 2);
|
||||
@ -358,6 +367,14 @@ void G2Element::ToNative(g2_t output) const {
|
||||
g2_copy(output, (g2_st*)q);
|
||||
}
|
||||
|
||||
G2Element G2Element::Copy() {
|
||||
G2Element ele;
|
||||
g2_copy(ele.q, this->q);
|
||||
|
||||
return ele;
|
||||
}
|
||||
|
||||
|
||||
G2Element G2Element::Negate() const
|
||||
{
|
||||
G2Element ans;
|
||||
|
@ -56,7 +56,7 @@ void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expec
|
||||
|
||||
TEST_CASE("class PrivateKey") {
|
||||
uint8_t buffer[PrivateKey::PRIVATE_KEY_SIZE];
|
||||
memcmp(buffer, getRandomSeed().data(), PrivateKey::PRIVATE_KEY_SIZE);
|
||||
memcpy(buffer, getRandomSeed().data(), PrivateKey::PRIVATE_KEY_SIZE);
|
||||
SECTION("Copy {constructor|assignment operator}") {
|
||||
PrivateKey pk1 = PrivateKey::RandomPrivateKey();
|
||||
PrivateKey pk2 = PrivateKey::RandomPrivateKey();
|
||||
|
@ -638,7 +638,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
|
||||
newList.SetHeight(nHeight);
|
||||
}
|
||||
|
||||
newList.SetBlockHash(block.GetHash());
|
||||
newList.SetBlockHash(pindex->GetBlockHash());
|
||||
|
||||
oldList = GetListForBlock(pindex->pprev);
|
||||
diff = oldList.BuildDiff(newList);
|
||||
@ -677,10 +677,10 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDeterministicMNManager::UndoBlock(const CBlock& block, const CBlockIndex* pindex)
|
||||
bool CDeterministicMNManager::UndoBlock(const CBlockIndex* pindex)
|
||||
{
|
||||
int nHeight = pindex->nHeight;
|
||||
uint256 blockHash = block.GetHash();
|
||||
uint256 blockHash = pindex->GetBlockHash();
|
||||
|
||||
CDeterministicMNList curList;
|
||||
CDeterministicMNList prevList;
|
||||
|
@ -595,7 +595,7 @@ public:
|
||||
|
||||
bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state,
|
||||
const CCoinsViewCache& view, bool fJustCheck) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool UndoBlock(const CBlock& block, const CBlockIndex* pindex);
|
||||
bool UndoBlock(const CBlockIndex* pindex);
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex* pindex);
|
||||
|
||||
|
@ -11,9 +11,9 @@
|
||||
#include <script/standard.h>
|
||||
#include <util/underlying.h>
|
||||
|
||||
maybe_error CProRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
|
||||
maybe_error CProRegTx::IsTriviallyValid(bool is_basic_scheme_active) const
|
||||
{
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_basic_scheme_active)) {
|
||||
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
|
||||
}
|
||||
if (!IsValidMnType(nType)) {
|
||||
@ -87,9 +87,9 @@ std::string CProRegTx::ToString() const
|
||||
nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), addr.ToString(), (double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort);
|
||||
}
|
||||
|
||||
maybe_error CProUpServTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
|
||||
maybe_error CProUpServTx::IsTriviallyValid(bool is_basic_scheme_active) const
|
||||
{
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_basic_scheme_active)) {
|
||||
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
|
||||
}
|
||||
|
||||
@ -108,9 +108,9 @@ std::string CProUpServTx::ToString() const
|
||||
nVersion, ToUnderlying(nType), proTxHash.ToString(), addr.ToString(), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort);
|
||||
}
|
||||
|
||||
maybe_error CProUpRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
|
||||
maybe_error CProUpRegTx::IsTriviallyValid(bool is_basic_scheme_active) const
|
||||
{
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_basic_scheme_active)) {
|
||||
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
|
||||
}
|
||||
if (nMode != 0) {
|
||||
@ -141,9 +141,9 @@ std::string CProUpRegTx::ToString() const
|
||||
nVersion, proTxHash.ToString(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee);
|
||||
}
|
||||
|
||||
maybe_error CProUpRevTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
|
||||
maybe_error CProUpRevTx::IsTriviallyValid(bool is_basic_scheme_active) const
|
||||
{
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
|
||||
if (nVersion == 0 || nVersion > GetVersion(is_basic_scheme_active)) {
|
||||
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq:
|
||||
}
|
||||
}
|
||||
|
||||
if (!deterministicMNManager->UndoBlock(block, pindex)) {
|
||||
if (!deterministicMNManager->UndoBlock(pindex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2416,7 +2416,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*::coinJoinServer)), std::chrono::seconds{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1});
|
||||
#ifdef ENABLE_WALLET
|
||||
} else if(CCoinJoinClientOptions::IsEnabled()) {
|
||||
} else {
|
||||
node.scheduler->scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*node.mempool), std::ref(*node.connman)), std::chrono::seconds{1});
|
||||
#endif // ENABLE_WALLET
|
||||
}
|
||||
|
@ -135,9 +135,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||
bool fDIP0008Active_context = nHeight >= chainparams.GetConsensus().DIP0008Height;
|
||||
|
||||
pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus(), chainparams.BIP9CheckMasternodesUpgraded());
|
||||
// -regtest only: allow overriding block.nVersion with
|
||||
// Non-mainnet only: allow overriding block.nVersion with
|
||||
// -blockversion=N to test forking scenarios
|
||||
if (chainparams.MineBlocksOnDemand())
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN)
|
||||
pblock->nVersion = gArgs.GetArg("-blockversion", pblock->nVersion);
|
||||
|
||||
pblock->nTime = GetAdjustedTime();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QDebug>
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
// Amount column is right-aligned it contains numbers
|
||||
@ -73,14 +74,18 @@ public:
|
||||
void refreshWallet(interfaces::Wallet& wallet)
|
||||
{
|
||||
qDebug() << "TransactionTablePriv::refreshWallet";
|
||||
cachedWallet.clear();
|
||||
{
|
||||
parent->beginResetModel();
|
||||
try {
|
||||
cachedWallet.clear();
|
||||
for (const auto& wtx : wallet.getWalletTxs()) {
|
||||
if (TransactionRecord::showTransaction()) {
|
||||
cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, wtx));
|
||||
}
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
QMessageBox::critical(nullptr, PACKAGE_NAME, QString("Failed to refresh wallet table: ") + QString::fromStdString(e.what()));
|
||||
}
|
||||
parent->endResetModel();
|
||||
}
|
||||
|
||||
/* Update our model of the wallet incrementally, to synchronize our model of the wallet
|
||||
@ -242,6 +247,11 @@ TransactionTableModel::~TransactionTableModel()
|
||||
delete priv;
|
||||
}
|
||||
|
||||
void TransactionTableModel::refreshWallet()
|
||||
{
|
||||
priv->refreshWallet(walletModel->wallet());
|
||||
}
|
||||
|
||||
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
|
||||
void TransactionTableModel::updateAmountColumnTitle()
|
||||
{
|
||||
@ -802,18 +812,24 @@ static void ShowProgress(TransactionTableModel *ttm, const std::string &title, i
|
||||
if (nProgress == 100)
|
||||
{
|
||||
fQueueNotifications = false;
|
||||
if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
|
||||
bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
|
||||
assert(invoked);
|
||||
}
|
||||
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
|
||||
{
|
||||
if (vQueueNotifications.size() - i <= 10) {
|
||||
bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
|
||||
if (vQueueNotifications.size() < 10000) {
|
||||
if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
|
||||
bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
|
||||
assert(invoked);
|
||||
}
|
||||
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
|
||||
{
|
||||
if (vQueueNotifications.size() - i <= 10) {
|
||||
bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
|
||||
assert(invoked);
|
||||
}
|
||||
|
||||
vQueueNotifications[i].invoke(ttm);
|
||||
vQueueNotifications[i].invoke(ttm);
|
||||
}
|
||||
} else {
|
||||
// it's much faster to just refresh the whole thing instead
|
||||
bool invoked = QMetaObject::invokeMethod(ttm, "refreshWallet", Qt::QueuedConnection);
|
||||
assert(invoked);
|
||||
}
|
||||
std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ private:
|
||||
QVariant txAddressDecoration(const TransactionRecord *wtx) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
/* Refresh the whole wallet, helpful for huge notification queues */
|
||||
void refreshWallet();
|
||||
/* New transaction, or transaction changed status */
|
||||
void updateTransaction(const QString &hash, int status, bool showTransaction);
|
||||
void updateAddressBook(const QString &address, const QString &label,
|
||||
|
@ -196,10 +196,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "echojson", 9, "arg9" },
|
||||
{ "rescanblockchain", 0, "start_height"},
|
||||
{ "rescanblockchain", 1, "stop_height"},
|
||||
{ "wipewallettxes", 0, "keep_confirmed"},
|
||||
{ "createwallet", 1, "disable_private_keys"},
|
||||
{ "createwallet", 2, "blank"},
|
||||
{ "createwallet", 4, "avoid_reuse"},
|
||||
{ "upgradetohd", 3, "rescan"},
|
||||
{ "createwallet", 5, "load_on_startup"},
|
||||
{ "loadwallet", 1, "load_on_startup"},
|
||||
{ "unloadwallet", 1, "load_on_startup"},
|
||||
|
@ -1204,6 +1204,7 @@ static void protx_list_help(const JSONRPCRequest& request)
|
||||
" registered - List all ProTx which are registered at the given chain height.\n"
|
||||
" This will also include ProTx which failed PoSe verification.\n"
|
||||
" valid - List only ProTx which are active/valid at the given chain height.\n"
|
||||
" hpmn - List only ProTx corresponding to HPMNs at the given chain height.\n"
|
||||
#ifdef ENABLE_WALLET
|
||||
" wallet - List only ProTx which are found in your wallet at the given chain height.\n"
|
||||
" This will also include ProTx which failed PoSe verification.\n"
|
||||
@ -1349,7 +1350,7 @@ static UniValue protx_list(const JSONRPCRequest& request)
|
||||
}
|
||||
});
|
||||
#endif
|
||||
} else if (type == "valid" || type == "registered") {
|
||||
} else if (type == "valid" || type == "registered" || type == "hpmn") {
|
||||
if (request.params.size() > 3) {
|
||||
protx_list_help(request);
|
||||
}
|
||||
@ -1365,7 +1366,9 @@ static UniValue protx_list(const JSONRPCRequest& request)
|
||||
|
||||
CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(::ChainActive()[height]);
|
||||
bool onlyValid = type == "valid";
|
||||
bool onlyHPMN = type == "hpmn";
|
||||
mnList.ForEachMN(onlyValid, [&](const auto& dmn) {
|
||||
if (onlyHPMN && dmn.nType != MnType::HighPerformance) return;
|
||||
ret.push_back(BuildDMNListEntry(wallet.get(), dmn, detailed));
|
||||
});
|
||||
} else {
|
||||
|
@ -37,6 +37,7 @@ static void masternode_list_help(const JSONRPCRequest& request)
|
||||
"Available modes:\n"
|
||||
" addr - Print ip address associated with a masternode (can be additionally filtered, partial match)\n"
|
||||
" recent - Print info in JSON format for active and recently banned masternodes (can be additionally filtered, partial match)\n"
|
||||
" hpmn - Print info in JSON format for HPMNs only\n"
|
||||
" full - Print info in format 'status payee lastpaidtime lastpaidblock IP'\n"
|
||||
" (can be additionally filtered, partial match)\n"
|
||||
" info - Print info in format 'status payee IP'\n"
|
||||
@ -581,7 +582,7 @@ static UniValue masternodelist(const JSONRPCRequest& request)
|
||||
strMode != "owneraddress" && strMode != "votingaddress" &&
|
||||
strMode != "lastpaidtime" && strMode != "lastpaidblock" &&
|
||||
strMode != "payee" && strMode != "pubkeyoperator" &&
|
||||
strMode != "status" && strMode != "recent"))
|
||||
strMode != "status" && strMode != "recent" && strMode != "hpmn"))
|
||||
{
|
||||
masternode_list_help(request);
|
||||
}
|
||||
@ -609,6 +610,7 @@ static UniValue masternodelist(const JSONRPCRequest& request)
|
||||
};
|
||||
|
||||
bool showRecentMnsOnly = strMode == "recent";
|
||||
bool showHPMNsOnly = strMode == "hpmn";
|
||||
int tipHeight = WITH_LOCK(cs_main, return ::ChainActive().Tip()->nHeight);
|
||||
mnList.ForEachMN(false, [&](auto& dmn) {
|
||||
if (showRecentMnsOnly && mnList.IsMNPoSeBanned(dmn)) {
|
||||
@ -616,6 +618,9 @@ static UniValue masternodelist(const JSONRPCRequest& request)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (showHPMNsOnly && dmn.nType != MnType::HighPerformance) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strOutpoint = dmn.collateralOutpoint.ToStringShort();
|
||||
Coin coin;
|
||||
@ -663,7 +668,7 @@ static UniValue masternodelist(const JSONRPCRequest& request)
|
||||
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
|
||||
strOutpoint.find(strFilter) == std::string::npos) return;
|
||||
obj.pushKV(strOutpoint, strInfo);
|
||||
} else if (strMode == "json" || strMode == "recent") {
|
||||
} else if (strMode == "json" || strMode == "recent" || strMode == "hpmn") {
|
||||
std::ostringstream streamInfo;
|
||||
streamInfo << dmn.proTxHash.ToString() << " " <<
|
||||
dmn.pdmnState->addr.ToString() << " " <<
|
||||
|
@ -48,28 +48,28 @@ BOOST_AUTO_TEST_CASE(trivialvalidation_valid)
|
||||
BOOST_CHECK_EQUAL(txType, "proregtx");
|
||||
CProRegTx ptx;
|
||||
BOOST_CHECK(GetTxPayload(tx, ptx, false));
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_PROVIDER_UPDATE_SERVICE: {
|
||||
BOOST_CHECK_EQUAL(txType, "proupservtx");
|
||||
CProUpServTx ptx;
|
||||
BOOST_CHECK(GetTxPayload(tx, ptx, false));
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR: {
|
||||
BOOST_CHECK_EQUAL(txType, "proupregtx");
|
||||
CProUpRegTx ptx;
|
||||
BOOST_CHECK(GetTxPayload(tx, ptx, false));
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
break;
|
||||
}
|
||||
case TRANSACTION_PROVIDER_UPDATE_REVOKE: {
|
||||
BOOST_CHECK_EQUAL(txType, "prouprevtx");
|
||||
CProUpRevTx ptx;
|
||||
BOOST_CHECK(GetTxPayload(tx, ptx, false));
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(!ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(trivialvalidation_invalid)
|
||||
if (txType == "proregtx") {
|
||||
CProRegTx ptx;
|
||||
if (GetTxPayload(tx, ptx, false)) {
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
} else {
|
||||
BOOST_CHECK(tx.nType != TRANSACTION_PROVIDER_REGISTER || ptx.nVersion == 0);
|
||||
}
|
||||
@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(trivialvalidation_invalid)
|
||||
else if (txType == "proupservtx") {
|
||||
CProUpServTx ptx;
|
||||
if (GetTxPayload(tx, ptx, false)) {
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
} else {
|
||||
BOOST_CHECK(tx.nType != TRANSACTION_PROVIDER_UPDATE_SERVICE || ptx.nVersion == 0);
|
||||
}
|
||||
@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(trivialvalidation_invalid)
|
||||
else if (txType == "proupregtx") {
|
||||
CProUpRegTx ptx;
|
||||
if (GetTxPayload(tx, ptx, false)) {
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
}
|
||||
else {
|
||||
BOOST_CHECK(tx.nType != TRANSACTION_PROVIDER_UPDATE_REGISTRAR || ptx.nVersion == 0);
|
||||
@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(trivialvalidation_invalid)
|
||||
else if (txType == "prouprevtx") {
|
||||
CProUpRevTx ptx;
|
||||
if (GetTxPayload(tx, ptx, false)) {
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(bls::bls_legacy_scheme.load()).did_err);
|
||||
BOOST_CHECK(ptx.IsTriviallyValid(!bls::bls_legacy_scheme.load()).did_err);
|
||||
} else {
|
||||
BOOST_CHECK(tx.nType != TRANSACTION_PROVIDER_UPDATE_REVOKE || ptx.nVersion == 0);
|
||||
}
|
||||
|
@ -365,6 +365,15 @@ CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns,
|
||||
|
||||
TestChainSetup::~TestChainSetup()
|
||||
{
|
||||
// Allow tx index to catch up with the block index cause otherwise
|
||||
// we might be destroying it while scheduler still has some work for it
|
||||
// e.g. via BlockConnected signal
|
||||
int64_t time_start = GetTimeMillis();
|
||||
while (!g_txindex->BlockUntilSyncedToCurrentChain()) {
|
||||
static constexpr int64_t timeout_ms = 10 * 1000;
|
||||
assert(time_start + timeout_ms > GetTimeMillis());
|
||||
UninterruptibleSleep(std::chrono::milliseconds{100});
|
||||
}
|
||||
g_txindex->Interrupt();
|
||||
g_txindex->Stop();
|
||||
g_txindex.reset();
|
||||
|
@ -70,6 +70,18 @@ bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& va
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if settings file is empty
|
||||
if (file.peek() == std::ifstream::traits_type::eof()) {
|
||||
// In that case delete it and return true: it will be created with default value later
|
||||
file.close();
|
||||
if (!boost::filesystem::remove(path)) {
|
||||
// Return false only if it failed to delete the empty settings file
|
||||
errors.emplace_back(strprintf("Unable to delete empty settings file %s", path.string()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SettingsValue in;
|
||||
if (!in.read(std::string{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()})) {
|
||||
errors.emplace_back(strprintf("Unable to parse settings file %s", path.string()));
|
||||
|
@ -2665,67 +2665,66 @@ static UniValue upgradetohd(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command");
|
||||
}
|
||||
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
// Do not do anything to HD wallets
|
||||
if (pwallet->IsHDEnabled()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot upgrade a wallet to HD if it is already upgraded to HD.");
|
||||
}
|
||||
|
||||
if (!pwallet->SetMaxVersion(FEATURE_HD)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot downgrade wallet");
|
||||
}
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
||||
}
|
||||
|
||||
bool prev_encrypted = pwallet->IsCrypted();
|
||||
|
||||
SecureString secureWalletPassphrase;
|
||||
secureWalletPassphrase.reserve(100);
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
||||
if (request.params[2].isNull()) {
|
||||
if (prev_encrypted) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Cannot upgrade encrypted wallet to HD without the wallet passphrase");
|
||||
}
|
||||
} else {
|
||||
secureWalletPassphrase = request.params[2].get_str().c_str();
|
||||
if (!pwallet->Unlock(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "The wallet passphrase entered was incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
bool generate_mnemonic = request.params[0].isNull() || request.params[0].get_str().empty();
|
||||
|
||||
SecureString secureMnemonic;
|
||||
secureMnemonic.reserve(256);
|
||||
if (!generate_mnemonic) {
|
||||
if (pwallet->chain().isInitialBlockDownload()) {
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set mnemonic while still in Initial Block Download");
|
||||
{
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
// Do not do anything to HD wallets
|
||||
if (pwallet->IsHDEnabled()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot upgrade a wallet to HD if it is already upgraded to HD.");
|
||||
}
|
||||
secureMnemonic = request.params[0].get_str().c_str();
|
||||
}
|
||||
|
||||
SecureString secureMnemonicPassphrase;
|
||||
secureMnemonicPassphrase.reserve(256);
|
||||
if (!request.params[1].isNull()) {
|
||||
secureMnemonicPassphrase = request.params[1].get_str().c_str();
|
||||
}
|
||||
|
||||
pwallet->WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
pwallet->SetMinVersion(FEATURE_HD);
|
||||
|
||||
if (prev_encrypted) {
|
||||
if (!spk_man->GenerateNewHDChainEncrypted(secureMnemonic, secureMnemonicPassphrase, secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
|
||||
if (!pwallet->SetMaxVersion(FEATURE_HD)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot downgrade wallet");
|
||||
}
|
||||
} else {
|
||||
spk_man->GenerateNewHDChain(secureMnemonic, secureMnemonicPassphrase);
|
||||
if (!secureWalletPassphrase.empty()) {
|
||||
if (!pwallet->EncryptWallet(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to encrypt HD wallet");
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
||||
}
|
||||
|
||||
bool prev_encrypted = pwallet->IsCrypted();
|
||||
|
||||
SecureString secureWalletPassphrase;
|
||||
secureWalletPassphrase.reserve(100);
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make request.params[0] mlock()'d to begin with.
|
||||
if (request.params[2].isNull()) {
|
||||
if (prev_encrypted) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Cannot upgrade encrypted wallet to HD without the wallet passphrase");
|
||||
}
|
||||
} else {
|
||||
secureWalletPassphrase = request.params[2].get_str().c_str();
|
||||
if (!pwallet->Unlock(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "The wallet passphrase entered was incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
SecureString secureMnemonic;
|
||||
secureMnemonic.reserve(256);
|
||||
if (!generate_mnemonic) {
|
||||
secureMnemonic = request.params[0].get_str().c_str();
|
||||
}
|
||||
|
||||
SecureString secureMnemonicPassphrase;
|
||||
secureMnemonicPassphrase.reserve(256);
|
||||
if (!request.params[1].isNull()) {
|
||||
secureMnemonicPassphrase = request.params[1].get_str().c_str();
|
||||
}
|
||||
|
||||
pwallet->WalletLogPrintf("Upgrading wallet to HD\n");
|
||||
pwallet->SetMinVersion(FEATURE_HD);
|
||||
|
||||
if (prev_encrypted) {
|
||||
if (!spk_man->GenerateNewHDChainEncrypted(secureMnemonic, secureMnemonicPassphrase, secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
|
||||
}
|
||||
} else {
|
||||
spk_man->GenerateNewHDChain(secureMnemonic, secureMnemonicPassphrase);
|
||||
if (!secureWalletPassphrase.empty()) {
|
||||
if (!pwallet->EncryptWallet(secureWalletPassphrase)) {
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to encrypt HD wallet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2737,7 +2736,16 @@ static UniValue upgradetohd(const JSONRPCRequest& request)
|
||||
if (!reserver.reserve()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
|
||||
}
|
||||
pwallet->ScanForWalletTransactions(pwallet->chain().getBlockHash(0), {}, reserver, true);
|
||||
CWallet::ScanResult result = pwallet->ScanForWalletTransactions(pwallet->chain().getBlockHash(0), {}, reserver, true);
|
||||
switch (result.status) {
|
||||
case CWallet::ScanResult::SUCCESS:
|
||||
break;
|
||||
case CWallet::ScanResult::FAILURE:
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
|
||||
case CWallet::ScanResult::USER_ABORT:
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3564,6 +3572,74 @@ static UniValue rescanblockchain(const JSONRPCRequest& request)
|
||||
return response;
|
||||
}
|
||||
|
||||
static UniValue wipewallettxes(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"wipewallettxes",
|
||||
"\nWipe wallet transactions.\n"
|
||||
"Note: Use \"rescanblockchain\" to initiate the scanning progress and recover wallet transactions.\n",
|
||||
{
|
||||
{"keep_confirmed", RPCArg::Type::BOOL, /* default */ "false", "Do not wipe confirmed transactions"},
|
||||
},
|
||||
RPCResult{RPCResult::Type::NONE, "", ""},
|
||||
RPCExamples{
|
||||
HelpExampleCli("wipewallettxes", "")
|
||||
+ HelpExampleRpc("wipewallettxes", "")
|
||||
},
|
||||
}.Check(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
WalletRescanReserver reserver(pwallet);
|
||||
if (!reserver.reserve()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort rescan or wait.");
|
||||
}
|
||||
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
bool keep_confirmed{false};
|
||||
if (!request.params[0].isNull()) {
|
||||
keep_confirmed = request.params[0].get_bool();
|
||||
}
|
||||
|
||||
const size_t WALLET_SIZE{pwallet->mapWallet.size()};
|
||||
const size_t STEPS{20};
|
||||
const size_t BATCH_SIZE = std::max(WALLET_SIZE / STEPS, size_t(1000));
|
||||
|
||||
pwallet->ShowProgress(strprintf("%s " + _("Wiping wallet transactions...").translated, pwallet->GetDisplayName()), 0);
|
||||
|
||||
for (size_t progress = 0; progress < STEPS; ++progress) {
|
||||
std::vector<uint256> vHashIn;
|
||||
std::vector<uint256> vHashOut;
|
||||
size_t count{0};
|
||||
|
||||
for (auto& [txid, wtx] : pwallet->mapWallet) {
|
||||
if (progress < STEPS - 1 && ++count > BATCH_SIZE) break;
|
||||
if (keep_confirmed && wtx.m_confirm.status == CWalletTx::CONFIRMED) continue;
|
||||
vHashIn.push_back(txid);
|
||||
}
|
||||
|
||||
if (vHashIn.size() > 0 && pwallet->ZapSelectTx(vHashIn, vHashOut) != DBErrors::LOAD_OK) {
|
||||
pwallet->ShowProgress(strprintf("%s " + _("Wiping wallet transactions...").translated, pwallet->GetDisplayName()), 100);
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not properly delete transactions.");
|
||||
}
|
||||
|
||||
CHECK_NONFATAL(vHashOut.size() == vHashIn.size());
|
||||
|
||||
if (pwallet->IsAbortingRescan() || pwallet->chain().shutdownRequested()) {
|
||||
pwallet->ShowProgress(strprintf("%s " + _("Wiping wallet transactions...").translated, pwallet->GetDisplayName()), 100);
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Wiping was aborted by user.");
|
||||
}
|
||||
|
||||
pwallet->ShowProgress(strprintf("%s " + _("Wiping wallet transactions...").translated, pwallet->GetDisplayName()), std::max(1, std::min(99, int(progress * 100 / STEPS))));
|
||||
}
|
||||
|
||||
pwallet->ShowProgress(strprintf("%s " + _("Wiping wallet transactions...").translated, pwallet->GetDisplayName()), 100);
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
class DescribeWalletAddressVisitor
|
||||
{
|
||||
public:
|
||||
@ -4166,6 +4242,7 @@ static const CRPCCommand commands[] =
|
||||
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout","mixingonly"} },
|
||||
{ "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
|
||||
{ "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs"} },
|
||||
{ "wallet", "wipewallettxes", &wipewallettxes, {"keep_confirmed"} },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <coinjoin/client.h>
|
||||
#include <logging.h>
|
||||
#include <script/descriptor.h>
|
||||
#include <shutdown.h>
|
||||
#include <util/bip32.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/system.h>
|
||||
@ -1374,14 +1375,27 @@ bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
|
||||
{
|
||||
// don't create extra internal keys
|
||||
missingInternal = 0;
|
||||
} else {
|
||||
nTargetSize *= 2;
|
||||
}
|
||||
|
||||
const int64_t total_missing = missingInternal + missingExternal;
|
||||
if (total_missing == 0) return true;
|
||||
|
||||
constexpr int64_t PROGRESS_REPORT_INTERVAL = 1; // in seconds
|
||||
const bool should_show_progress = total_missing > 100;
|
||||
const std::string strMsg = _("Topping up keypool...").translated;
|
||||
|
||||
int64_t progress_report_time = GetTime();
|
||||
WalletLogPrintf("%s\n", strMsg);
|
||||
if (should_show_progress) {
|
||||
uiInterface.ShowProgress(strMsg, 0, false);
|
||||
}
|
||||
|
||||
bool fInternal = false;
|
||||
int64_t current_index{0};
|
||||
WalletBatch batch(m_storage.GetDatabase());
|
||||
for (int64_t i = missingInternal + missingExternal; i--;)
|
||||
{
|
||||
if (i < missingInternal) {
|
||||
|
||||
for (current_index = 0; current_index < total_missing; ++current_index) {
|
||||
if (current_index == missingExternal) {
|
||||
fInternal = true;
|
||||
}
|
||||
|
||||
@ -1389,15 +1403,20 @@ bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
|
||||
CPubKey pubkey(GenerateNewKey(batch, 0, fInternal));
|
||||
AddKeypoolPubkeyWithDB(pubkey, fInternal, batch);
|
||||
|
||||
if (missingInternal + missingExternal > 0) {
|
||||
WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n",
|
||||
missingInternal + missingExternal, missingInternal,
|
||||
setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size());
|
||||
if (GetTime() >= progress_report_time + PROGRESS_REPORT_INTERVAL) {
|
||||
const double dProgress = 100.f * current_index / total_missing;
|
||||
progress_report_time = GetTime();
|
||||
WalletLogPrintf("Still topping up. At key %lld. Progress=%f\n", current_index, dProgress);
|
||||
if (should_show_progress) {
|
||||
uiInterface.ShowProgress(strMsg, static_cast<int>(dProgress), false);
|
||||
}
|
||||
}
|
||||
|
||||
double dProgress = 100.f * m_max_keypool_index / (nTargetSize + 1);
|
||||
std::string strMsg = strprintf(_("Loading wallet... (%3.2f %%)").translated, dProgress);
|
||||
uiInterface.InitMessage(strMsg);
|
||||
if (ShutdownRequested()) break;
|
||||
}
|
||||
WalletLogPrintf("Keypool added %d keys, size=%u (%u internal)\n",
|
||||
current_index + 1, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size());
|
||||
if (should_show_progress) {
|
||||
uiInterface.ShowProgress("", 100, false);
|
||||
}
|
||||
}
|
||||
NotifyCanGetAddressesChanged();
|
||||
|
@ -1884,7 +1884,6 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
|
||||
|
||||
WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
|
||||
|
||||
fAbortRescan = false;
|
||||
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
|
||||
uint256 tip_hash;
|
||||
// The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
|
||||
@ -3667,6 +3666,9 @@ void CWallet::AutoLockMasternodeCollaterals()
|
||||
DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
WalletLogPrintf("ZapSelectTx started for %d transactions...\n", vHashIn.size());
|
||||
|
||||
DBErrors nZapSelectTxRet = WalletBatch(*database).ZapSelectTx(vHashIn, vHashOut);
|
||||
for (uint256 hash : vHashOut) {
|
||||
const auto& it = mapWallet.find(hash);
|
||||
@ -3690,6 +3692,8 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
|
||||
|
||||
MarkDirty();
|
||||
|
||||
WalletLogPrintf("ZapSelectTx completed for %d transactions.\n", vHashOut.size());
|
||||
|
||||
return DBErrors::LOAD_OK;
|
||||
}
|
||||
|
||||
|
@ -654,7 +654,7 @@ private:
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool fForMixingOnly = false, bool accept_no_keys = false);
|
||||
|
||||
std::atomic<bool> fAbortRescan{false};
|
||||
std::atomic<bool> fAbortRescan{false}; // reset by WalletRescanReserver::reserve()
|
||||
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
|
||||
std::atomic<int64_t> m_scanning_start{0};
|
||||
std::atomic<double> m_scanning_progress{0};
|
||||
@ -1306,6 +1306,7 @@ public:
|
||||
}
|
||||
m_wallet->m_scanning_start = GetTimeMillis();
|
||||
m_wallet->m_scanning_progress = 0;
|
||||
m_wallet->fAbortRescan = false;
|
||||
m_could_reserve = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
|
||||
WalletShowInfo(wallet_instance.get());
|
||||
wallet_instance->Close();
|
||||
}
|
||||
} else if (command == "info" || command == "salvage") {
|
||||
} else if (command == "info" || command == "salvage" || command == "wipetxes") {
|
||||
if (command == "info") {
|
||||
std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ false);
|
||||
if (!wallet_instance) return false;
|
||||
@ -135,6 +135,32 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
|
||||
#else
|
||||
tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
|
||||
return false;
|
||||
#endif
|
||||
} else if (command == "wipetxes") {
|
||||
#ifdef USE_BDB
|
||||
std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ false);
|
||||
if (wallet_instance == nullptr) return false;
|
||||
|
||||
std::vector<uint256> vHash;
|
||||
std::vector<uint256> vHashOut;
|
||||
|
||||
LOCK(wallet_instance->cs_wallet);
|
||||
|
||||
for (auto& [txid, _] : wallet_instance->mapWallet) {
|
||||
vHash.push_back(txid);
|
||||
}
|
||||
|
||||
if (wallet_instance->ZapSelectTx(vHash, vHashOut) != DBErrors::LOAD_OK) {
|
||||
tfm::format(std::cerr, "Could not properly delete transactions");
|
||||
wallet_instance->Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
wallet_instance->Close();
|
||||
return vHashOut.size() == vHash.size();
|
||||
#else
|
||||
tfm::format(std::cerr, "Wipetxes command is not available as BDB support is not compiled");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
|
41
test/functional/rpc_wipewallettxes.py
Normal file
41
test/functional/rpc_wipewallettxes.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2023 The Dash Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test transaction wiping using the wipewallettxes RPC."""
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error
|
||||
|
||||
|
||||
class WipeWalletTxesTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Test that wipewallettxes removes txes and rescanblockchain is able to recover them")
|
||||
self.nodes[0].generate(101)
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
self.nodes[0].generate(1)
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 103)
|
||||
self.nodes[0].wipewallettxes()
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 0)
|
||||
self.nodes[0].rescanblockchain()
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 103)
|
||||
|
||||
self.log.info("Test that wipewallettxes removes txes but keeps confirmed ones when asked to")
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 104)
|
||||
self.nodes[0].wipewallettxes(True)
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 103)
|
||||
self.nodes[0].rescanblockchain()
|
||||
assert_equal(self.nodes[0].getwalletinfo()["txcount"], 103)
|
||||
assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", self.nodes[0].gettransaction, txid)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
WipeWalletTxesTest().main()
|
@ -239,6 +239,7 @@ BASE_SCRIPTS = [
|
||||
'wallet_create_tx.py',
|
||||
'p2p_fingerprint.py',
|
||||
'rpc_platform_filter.py',
|
||||
'rpc_wipewallettxes.py',
|
||||
'feature_dip0020_activation.py',
|
||||
'feature_uacomment.py',
|
||||
'wallet_coinbase_category.py',
|
||||
|
@ -228,6 +228,31 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
|
||||
self.assert_tool_output('', '-wallet=salvage', 'salvage')
|
||||
|
||||
def test_wipe(self):
|
||||
out = textwrap.dedent('''\
|
||||
Wallet info
|
||||
===========
|
||||
Encrypted: no
|
||||
HD (hd seed available): yes
|
||||
Keypool Size: 2
|
||||
Transactions: 1
|
||||
Address Book: 1
|
||||
''')
|
||||
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
|
||||
|
||||
self.assert_tool_output('', '-wallet=' + self.default_wallet_name, 'wipetxes')
|
||||
|
||||
out = textwrap.dedent('''\
|
||||
Wallet info
|
||||
===========
|
||||
Encrypted: no
|
||||
HD (hd seed available): yes
|
||||
Keypool Size: 2
|
||||
Transactions: 0
|
||||
Address Book: 1
|
||||
''')
|
||||
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
|
||||
|
||||
def run_test(self):
|
||||
self.wallet_path = os.path.join(self.nodes[0].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename)
|
||||
self.test_invalid_tool_commands_and_args()
|
||||
@ -238,6 +263,7 @@ class ToolWalletTest(BitcoinTestFramework):
|
||||
self.test_getwalletinfo_on_different_wallet()
|
||||
if self.is_bdb_compiled():
|
||||
self.test_salvage()
|
||||
self.test_wipe()
|
||||
|
||||
if __name__ == '__main__':
|
||||
ToolWalletTest().main()
|
||||
|
Loading…
Reference in New Issue
Block a user