Merge pull request #131 from MyHush/danger
Update Hush emission schedule code
This commit is contained in:
@@ -1,33 +1,218 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright 2019 The Hush developers
|
||||
# Copyright 2019-2020 The Hush developers
|
||||
# Released under the GPLv3
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
|
||||
my $supply = 0.0;
|
||||
my $block = 0;
|
||||
my $satoshis = 100_000_000;
|
||||
my $amount = int(12.5*$satoshis);
|
||||
my $block = 0; # Block 0 in Hush Smart chains is the BTC genesis block
|
||||
my $puposhis = 100_000_000;
|
||||
my $subsidy0 = 1_250_000_000;
|
||||
my $halvings = 0;
|
||||
my $initial = 6178674 * $puposhis;
|
||||
my $interval = 1_680_000; # ~4 years of 75s blocks
|
||||
my $stop = shift || -1;
|
||||
my $totalfr = 0; # total paid out to FR address
|
||||
|
||||
# Usage: ./hush_supply &> supply.csv
|
||||
|
||||
# Use this to calculate when supply hits a certain value
|
||||
#while ($supply <= 21_000_000*$satoshis) {
|
||||
# Use this to calculate when block rewards end
|
||||
while ($halvings <= 64 && $amount >= 1) {
|
||||
$block++;
|
||||
if ($block < 5) {
|
||||
$amount = 40_000 * $satoshis;
|
||||
} else {
|
||||
# Halving every 840000 blocks
|
||||
if ($block % 840_000 == 0) {
|
||||
$amount /= 2;
|
||||
$halvings++;
|
||||
}
|
||||
$amount = int(12.5*$satoshis) / (2**$halvings);
|
||||
}
|
||||
$supply += $amount;
|
||||
# block, current supply, block reward amount, number of halvings
|
||||
printf "%s,%s,%s,%s\n", $block,$supply / $satoshis, $amount / $satoshis, $halvings;
|
||||
if ($stop eq 'help' or $stop =~ m/-h/) {
|
||||
die <<HELP;
|
||||
# Simulate the total supply on Hush v3 mainnet
|
||||
# Block Reward: Total Coinbase In Block
|
||||
# Subsidy : Coinbase Earned by Miner
|
||||
# FR : Founders Reward (10%)
|
||||
# Block Reward = Subsidy + FR
|
||||
Usage: ./hush_supply &> supply.csv
|
||||
./hush_supply HEIGHT &> supply.csv # stop at HEIGHT
|
||||
# This will generate CSV in the form of:
|
||||
# block, supply, reward, subsidy, fr, totalfr, halvings
|
||||
HELP
|
||||
}
|
||||
|
||||
|
||||
printf "# block, supply, reward, subsidy, fr, totalfr, halvings\n";
|
||||
|
||||
# Block Reward Amounts in puposhis
|
||||
# The non-integral amounts cannot be represented exactly
|
||||
# 12.5 * 100000000 = 1250000000
|
||||
# 12.5 * 100000000 / 2 = 625000000
|
||||
# 12.5 * 100000000 / 4 = 312500000
|
||||
# 12.5 * 100000000 / 8 = 156250000
|
||||
# 12.5 * 100000000 / 16 = 78125000
|
||||
# 12.5 * 100000000 / 32 = 39062500
|
||||
# 12.5 * 100000000 / 64 = 19531250
|
||||
# 12.5 * 100000000 / 128 = 9765625
|
||||
# 12.5 * 100000000 / 256 = 4882812.5
|
||||
# 12.5 * 100000000 / 512 = 2441406.25
|
||||
# 12.5 * 100000000 / 1024 = 1220703.125
|
||||
# 12.5 * 100000000 / 2048 = 610351.5625
|
||||
# 12.5 * 100000000 / 4096 = 305175.78125
|
||||
# 12.5 * 100000000 / 8192 = 152587.890625
|
||||
# 12.5 * 100000000 / 16384 = 76293.9453125
|
||||
# 12.5 * 100000000 / 32768 = 38146.97265625
|
||||
# 12.5 * 100000000 / 65536 = 19073.486328125
|
||||
|
||||
# Hush Halving Heights and Block Rewards
|
||||
# 1,12500000000,340000
|
||||
# 2,312500000,2020000
|
||||
# 3,156250000,3700000
|
||||
# 4,78125000,5380000
|
||||
# 5,39062500,7060000
|
||||
# 6,19531250,8740000
|
||||
# 7,9765625,10420000
|
||||
# 8,4882812,12100000
|
||||
# 9,2441406,13780000
|
||||
# 10,1220703,15460000
|
||||
# 11,610351,17140000
|
||||
# 12,305175,18820000
|
||||
# 13,152587,20500000
|
||||
# 14,76293,22180000
|
||||
# 15,38146,23860000
|
||||
# 16,19073,25540000
|
||||
# 17,9536,27220000
|
||||
# 18,4768,28900000
|
||||
# 19,2384,30580000
|
||||
# 20,1192,32260000
|
||||
# 21,596,33940000
|
||||
# 22,298,35620000
|
||||
# 23,149,37300000
|
||||
# 24,74,38980000
|
||||
# 25,37,40660000
|
||||
# 26,18,42340000
|
||||
# 27,9,44020000
|
||||
# 28,4,45700000
|
||||
# 29,2,47380000
|
||||
# 30,1,49060000
|
||||
# 31,0,50740000
|
||||
|
||||
|
||||
sub hush_block_reward
|
||||
{
|
||||
my $reward = 0;
|
||||
my $height = shift;
|
||||
my $halvings = 0;
|
||||
|
||||
if ($height >= 50740000) {
|
||||
$reward = 0;
|
||||
$halvings = 31;
|
||||
} elsif ($height >= 49060000) {
|
||||
$reward = 1;
|
||||
$halvings = 30;
|
||||
} elsif ($height >= 47380000) {
|
||||
$reward = 1;
|
||||
$halvings = 29;
|
||||
} elsif ($height >= 45700000) {
|
||||
$reward = 2;
|
||||
$halvings = 28;
|
||||
} elsif ($height >= 44020000) {
|
||||
$reward = 4;
|
||||
$halvings = 27;
|
||||
} elsif ($height >= 42340000) {
|
||||
$reward = 9;
|
||||
$halvings = 26;
|
||||
} elsif ($height >= 40660000) {
|
||||
$reward = 18;
|
||||
$halvings = 25;
|
||||
} elsif ($height >= 38980000) {
|
||||
$reward = 37;
|
||||
$halvings = 24;
|
||||
} elsif ($height >= 37380000) {
|
||||
$reward = 74;
|
||||
$halvings = 23;
|
||||
} elsif ($height >= 35620000) {
|
||||
$reward = 149;
|
||||
$halvings = 22;
|
||||
} elsif ($height >= 33940000) {
|
||||
$reward = 298;
|
||||
$halvings = 21;
|
||||
} elsif ($height >= 32260001) {
|
||||
$reward = 596;
|
||||
$halvings = 20;
|
||||
} elsif ($height >= 30580000) {
|
||||
$reward = 1192;
|
||||
$halvings = 19;
|
||||
} elsif ($height >= 28900000) {
|
||||
$reward = 2384;
|
||||
$halvings = 18;
|
||||
} elsif ($height >= 27220000) {
|
||||
$reward = 4768;
|
||||
$halvings = 17;
|
||||
} elsif ($height >= 25540000) {
|
||||
$reward = 9536;
|
||||
$halvings = 16;
|
||||
} elsif ($height >= 23860000) {
|
||||
$reward = 19073; # 0.486328125 deviation
|
||||
$halvings = 15;
|
||||
} elsif ($height >= 22180000) {
|
||||
$reward = 38146; # 0.97265625 deviation
|
||||
$halvings = 14;
|
||||
} elsif ($height >= 20500000) {
|
||||
$reward = 76293; # 0.9453125 deviation
|
||||
$halvings = 13;
|
||||
} elsif ($height >= 18820000) {
|
||||
$reward = 152587; # 0.890625 deviation
|
||||
$halvings = 12;
|
||||
} elsif ($height >= 17140000) {
|
||||
$reward = 305175; # 0.78125sat deviation
|
||||
$halvings = 11;
|
||||
} elsif ($height >= 15460000) {
|
||||
$reward = 610351; # 0.5625sat deviation
|
||||
$halvings = 10;
|
||||
} elsif ($height >= 13780000) {
|
||||
$reward = 1220703; # 0.125sat deviation
|
||||
$halvings = 9
|
||||
} elsif ($height >= 12100000) {
|
||||
$reward = 2441406; # 0.25sat deviation
|
||||
$halvings = 8
|
||||
} elsif ($height >= 10420000) {
|
||||
$reward = 4882812; # 0.5sat deviation
|
||||
$halvings = 7;
|
||||
} elsif ($height >= 8740000) {
|
||||
$reward = 9765625; # last exact reward
|
||||
$halvings = 6;
|
||||
} elsif ($height >= 7060000) {
|
||||
$reward = 19531250; # 0.1953125 HUSH
|
||||
$halvings = 5;
|
||||
} elsif ($height >= 5380000) {
|
||||
$reward = 39062500; # 0.390625 HUSH
|
||||
$halvings = 4;
|
||||
} elsif ($height >= 3700000) {
|
||||
$reward = 78125000; # 0.78125 HUSH
|
||||
$halvings = 3;
|
||||
} elsif ($height >= 2020000) {
|
||||
$reward = 156250000; # 1.5625 HUSH
|
||||
$halvings = 2;
|
||||
} elsif ($height >= 340000) {
|
||||
$reward = 312500000; # 3.125 HUSH
|
||||
$halvings = 1;
|
||||
} elsif ($height >= 128) {
|
||||
$reward = 1250000000; # 12.5 HUSH
|
||||
}
|
||||
|
||||
return ($reward,$halvings);
|
||||
}
|
||||
|
||||
# Block reward is 0 at the 31st halving
|
||||
while ($halvings <= 30) {
|
||||
$block++;
|
||||
my ($reward,$halvings) = hush_block_reward($block);
|
||||
my $fr = int($reward / 10);
|
||||
my $subsidy = $reward - $fr;
|
||||
|
||||
if($block == 1) {
|
||||
# initial airdrop of funds from HUSH v2 network @ Block 500000
|
||||
$reward = $initial;
|
||||
$subsidy= $reward;
|
||||
$fr = 0;
|
||||
}
|
||||
$supply += $reward;
|
||||
$totalfr += $fr;
|
||||
|
||||
# all values in puposhis
|
||||
# block, current supply, block reward amount, fr, totalfr, number of halvings
|
||||
printf "%d,%d,%d,%d,%d,%d,%d\n", $block, $supply, $reward, $subsidy, $fr, $totalfr, $halvings;
|
||||
exit(0) if $block == $stop;
|
||||
exit(0) if ($block > 128 && $reward == 0);
|
||||
exit(-1) if ($supply >= 21_000_000*$puposhis);
|
||||
}
|
||||
|
||||
33
contrib/hush_supply_old
Executable file
33
contrib/hush_supply_old
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright 2019-2020 The Hush developers
|
||||
# Released under the GPLv3
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
my $supply = 0.0;
|
||||
my $block = 0;
|
||||
my $satoshis = 100_000_000;
|
||||
my $amount = int(12.5*$satoshis);
|
||||
my $halvings = 0;
|
||||
|
||||
# Usage: ./hush_supply &> supply.csv
|
||||
|
||||
# Use this to calculate when supply hits a certain value
|
||||
#while ($supply <= 21_000_000*$satoshis) {
|
||||
# Use this to calculate when block rewards end
|
||||
while ($halvings <= 64 && $amount >= 1) {
|
||||
$block++;
|
||||
if ($block < 5) {
|
||||
$amount = 40_000 * $satoshis;
|
||||
} else {
|
||||
# Halving every 840000 blocks
|
||||
if ($block % 840_000 == 0) {
|
||||
$amount /= 2;
|
||||
$halvings++;
|
||||
}
|
||||
$amount = int(12.5*$satoshis) / (2**$halvings);
|
||||
}
|
||||
$supply += $amount;
|
||||
# block, current supply, block reward amount, number of halvings
|
||||
printf "%s,%s,%s,%s\n", $block,$supply / $satoshis, $amount / $satoshis, $halvings;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10.
|
||||
.TH HUSH-CLI "1" "July 2020" "hush-cli v3.5.0" "User Commands"
|
||||
.TH HUSH-CLI "1" "September 2020" "hush-cli v3.5.0" "User Commands"
|
||||
.SH NAME
|
||||
hush-cli \- manual page for hush-cli v3.5.0
|
||||
.SH DESCRIPTION
|
||||
Komodo RPC client version v3.5.0\-beta6\-a59803c32\-dirty
|
||||
Komodo RPC client version v3.5.0\-beta6\-fab0f9494\-dirty
|
||||
.PP
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://myhush.org/security/>.
|
||||
@@ -71,7 +71,7 @@ Timeout in seconds during HTTP requests, or 0 for no timeout. (default:
|
||||
Read extra arguments from standard input, one per line until EOF/Ctrl\-D
|
||||
(recommended for sensitive information such as passphrases)
|
||||
.SH COPYRIGHT
|
||||
Hush Daemon version v3.5.0-beta6-a59803c32-dirty
|
||||
Hush Daemon version v3.5.0-beta6-fab0f9494-dirty
|
||||
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://myhush.org/security/>.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10.
|
||||
.TH HUSH-TX "1" "July 2020" "hush-tx v3.5.0" "User Commands"
|
||||
.TH HUSH-TX "1" "September 2020" "hush-tx v3.5.0" "User Commands"
|
||||
.SH NAME
|
||||
hush-tx \- manual page for hush-tx v3.5.0
|
||||
.SH DESCRIPTION
|
||||
Hush komodo\-tx utility version v3.5.0\-beta6\-a59803c32\-dirty
|
||||
Hush komodo\-tx utility version v3.5.0\-beta6\-fab0f9494\-dirty
|
||||
.SS "Usage:"
|
||||
.TP
|
||||
komodo\-tx [options] <hex\-tx> [commands]
|
||||
@@ -84,7 +84,7 @@ set=NAME:JSON\-STRING
|
||||
.IP
|
||||
Set register NAME to given JSON\-STRING
|
||||
.SH COPYRIGHT
|
||||
Hush Daemon version v3.5.0-beta6-a59803c32-dirty
|
||||
Hush Daemon version v3.5.0-beta6-fab0f9494-dirty
|
||||
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://myhush.org/security/>.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10.
|
||||
.TH HUSHD "1" "July 2020" "hushd v3.5.0" "User Commands"
|
||||
.TH HUSHD "1" "September 2020" "hushd v3.5.0" "User Commands"
|
||||
.SH NAME
|
||||
hushd \- manual page for hushd v3.5.0
|
||||
.SH DESCRIPTION
|
||||
Found binary: ./komodod
|
||||
Hush Daemon version v3.5.0\-beta6\-a59803c32\-dirty
|
||||
Hush Daemon version v3.5.0\-beta6\-fab0f9494\-dirty
|
||||
.PP
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://myhush.org/security/>.
|
||||
@@ -114,6 +114,11 @@ Create new files with system default permissions, instead of umask 077
|
||||
Maintain a full transaction index, used by the getrawtransaction rpc
|
||||
call (default: 0)
|
||||
.HP
|
||||
\fB\-txsend=\fR<cmd>
|
||||
.IP
|
||||
Execute command to send a transaction instead of broadcasting (%s in cmd
|
||||
is replaced by transaction hex)
|
||||
.HP
|
||||
\fB\-addressindex\fR
|
||||
.IP
|
||||
Maintain a full address index, used to query for the balance, txids and
|
||||
@@ -346,7 +351,8 @@ Upgrade wallet to latest format on startup
|
||||
.HP
|
||||
\fB\-wallet=\fR<file>
|
||||
.IP
|
||||
Specify wallet file (within data directory) (default: wallet.dat)
|
||||
Specify wallet file absolute path or a path relative to the data
|
||||
directory (default: wallet.dat)
|
||||
.HP
|
||||
\fB\-walletbroadcast\fR
|
||||
.IP
|
||||
@@ -639,7 +645,7 @@ Starting supply, default is 0
|
||||
.IP
|
||||
Enforce transaction\-rate limit, default 0
|
||||
.SH COPYRIGHT
|
||||
Hush Daemon version v3.5.0-beta6-a59803c32-dirty
|
||||
Hush Daemon version v3.5.0-beta6-fab0f9494-dirty
|
||||
|
||||
In order to ensure you are adequately protecting your privacy when using Hush,
|
||||
please see <https://myhush.org/security/>.
|
||||
|
||||
51
qa/rpc-tests/feature_walletfile.py
Executable file
51
qa/rpc-tests/feature_walletfile.py
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2017 The Bitcoin Core developers
|
||||
# Copyright (c) 2019-2020 The Hush developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php
|
||||
"""Test wallet file location."""
|
||||
|
||||
import os
|
||||
|
||||
from test_framework.util import start_node, stop_node, assert_start_raises_init_error
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
class WalletFileTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def run_test(self):
|
||||
# test default wallet location
|
||||
assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet.dat"))
|
||||
|
||||
# test alternative wallet file name in datadir
|
||||
stop_node(self.nodes[0], 0)
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=altwallet.dat"])
|
||||
assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "altwallet.dat"))
|
||||
|
||||
# test wallet file outside datadir
|
||||
tempname = os.path.join(self.options.tmpdir, "outsidewallet.dat")
|
||||
stop_node(self.nodes[0], 0)
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % tempname])
|
||||
assert os.path.isfile(tempname)
|
||||
|
||||
# test the case where absolute path does not exist
|
||||
assert not os.path.isdir("/this_directory_must_not_exist")
|
||||
invalidpath = os.path.join("/this_directory_must_not_exist/", "foo.dat")
|
||||
stop_node(self.nodes[0], 0)
|
||||
assert_start_raises_init_error(0, "-wallet=%s" % invalidpath,
|
||||
"Error: Absolute path %s does not exist")
|
||||
|
||||
# relative path does not exist
|
||||
invalidpath = os.path.join("wallet", "foo.dat")
|
||||
assert_start_raises_init_error(0, "-wallet=%s" % invalidpath,
|
||||
"Error: Relative path %s does not exist")
|
||||
|
||||
# create dir and retry
|
||||
os.mkdir(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet"))
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % invalidpath])
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletFileTest().main()
|
||||
@@ -462,7 +462,7 @@ libbitcoin_server_a_SOURCES += rpc/testtransactions.cpp
|
||||
endif
|
||||
|
||||
|
||||
# cli: zcash-cli
|
||||
# cli
|
||||
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
libbitcoin_cli_a_SOURCES = \
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -79,4 +80,4 @@ struct CMempoolAddressDeltaKeyCompare
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ADDRESSINDEX_H
|
||||
#endif // BITCOIN_ADDRESSINDEX_H
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
@@ -16,7 +17,7 @@
|
||||
#ifndef BITCOIN_ALERTKEYS_H
|
||||
#define BITCOIN_ALERTKEYS_H
|
||||
|
||||
// REMINDER: DO NOT COMMIT YOUR PRIVATE KEYS TO THE GIT REPOSITORY!
|
||||
// REMINDER: DO NOT COMMIT YOUR PRIVATE KEYS TO THE GIT REPOSITORY, lulz
|
||||
|
||||
const char* pszPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
const char* pszTestNetPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016 The Zcash developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016 The Zcash developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define CLIENT_VERSION_MAJOR 3
|
||||
#define CLIENT_VERSION_MINOR 5
|
||||
#define CLIENT_VERSION_REVISION 0
|
||||
#define CLIENT_VERSION_BUILD 5
|
||||
#define CLIENT_VERSION_BUILD 50
|
||||
|
||||
//! Set to true for release, false for prerelease or test build
|
||||
#define CLIENT_VERSION_IS_RELEASE true
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2011-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
66
src/crypto/bip39/Makefile
Normal file
66
src/crypto/bip39/Makefile
Normal file
@@ -0,0 +1,66 @@
|
||||
CC ?= gcc
|
||||
|
||||
OPTFLAGS ?= -O3 -g
|
||||
|
||||
CFLAGS += $(OPTFLAGS) \
|
||||
-std=gnu99 \
|
||||
-W \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wimplicit-function-declaration \
|
||||
-Wredundant-decls \
|
||||
-Wstrict-prototypes \
|
||||
-Wundef \
|
||||
-Wshadow \
|
||||
-Wpointer-arith \
|
||||
-Wformat \
|
||||
-Wreturn-type \
|
||||
-Wsign-compare \
|
||||
-Wmultichar \
|
||||
-Wformat-nonliteral \
|
||||
-Winit-self \
|
||||
-Wuninitialized \
|
||||
-Wformat-security \
|
||||
-Werror
|
||||
|
||||
VALGRIND ?= 1
|
||||
|
||||
CFLAGS += -I.
|
||||
CFLAGS += -DVALGRIND=$(VALGRIND)
|
||||
CFLAGS += $(shell pkg-config --cflags openssl)
|
||||
|
||||
# disable certain optimizations and features when small footprint is required
|
||||
ifdef SMALL
|
||||
CFLAGS += -DUSE_PRECOMPUTED_CP=0
|
||||
endif
|
||||
|
||||
SRCS = bignum.c ecdsa.c curves.c secp256k1.c nist256p1.c rand.c hmac.c bip32.c bip39.c pbkdf2.c base58.c base32.c
|
||||
#SRCS += address.c
|
||||
#SRCS += script.c
|
||||
SRCS += ripemd160.c
|
||||
SRCS += sha2.c
|
||||
SRCS += sha3.c
|
||||
SRCS += hasher.c
|
||||
#SRCS += aes/aescrypt.c aes/aeskey.c aes/aestab.c aes/aes_modes.c
|
||||
#SRCS += ed25519-donna/curve25519-donna-32bit.c ed25519-donna/curve25519-donna-helpers.c ed25519-donna/modm-donna-32bit.c
|
||||
#SRCS += ed25519-donna/ed25519-donna-basepoint-table.c ed25519-donna/ed25519-donna-32bit-tables.c ed25519-donna/ed25519-donna-impl-base.c
|
||||
#SRCS += ed25519-donna/ed25519.c ed25519-donna/curve25519-donna-scalarmult-base.c ed25519-donna/ed25519-sha3.c ed25519-donna/ed25519-keccak.c
|
||||
#SRCS += blake256.c
|
||||
#SRCS += blake2b.c blake2s.c
|
||||
#SRCS += chacha20poly1305/chacha20poly1305.c chacha20poly1305/chacha_merged.c chacha20poly1305/poly1305-donna.c chacha20poly1305/rfc7539.c
|
||||
SRCS += memzero.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
TESTLIBS = $(shell pkg-config --libs check) -lpthread -lm
|
||||
TESTSSLLIBS = $(shell pkg-config --libs openssl)
|
||||
|
||||
all: hasher.o bip39.o memzero.o pbkdf2.o base58.o base32.o
|
||||
@echo "Created object files, donezo"
|
||||
|
||||
%.o: %.c %.h options.h
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
|
||||
3
src/crypto/bip39/README.md
Normal file
3
src/crypto/bip39/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# trezor-firmware bip39
|
||||
|
||||
Imported from https://github.com/trezor/trezor-firmware/commit/047fcffde1f8530d3aee279b731e5e5f5901590a
|
||||
233
src/crypto/bip39/base32.c
Normal file
233
src/crypto/bip39/base32.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, E1PRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "base32.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const char *BASE32_ALPHABET_RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789";
|
||||
|
||||
static inline void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out);
|
||||
static inline bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet);
|
||||
static inline void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out);
|
||||
|
||||
static inline int base32_encode_character(uint8_t decoded, const char *alphabet);
|
||||
static inline int base32_decode_character(char encoded, const char *alphabet);
|
||||
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet) {
|
||||
size_t length = base32_encoded_length(inlen);
|
||||
if (outlen <= length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
base32_encode_unsafe(in, inlen, (uint8_t *) out);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_encode_character(out[i], alphabet);
|
||||
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
out[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
out[length] = '\0';
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet) {
|
||||
size_t length = base32_decoded_length(inlen);
|
||||
if (outlen < length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!base32_decode_unsafe((uint8_t *) in, inlen, (uint8_t *) out, alphabet)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 5, j += 8) {
|
||||
base32_5to8(&in[i], 5, &out[j]);
|
||||
}
|
||||
|
||||
if (remainder) base32_5to8(&in[i], remainder, &out[j]);
|
||||
}
|
||||
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 8, j += 5) {
|
||||
if (!base32_8to5(&in[i], 8, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t base32_encoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
|
||||
return (inlen / 5) * 8 + (remainder * 8 + 4) / 5;
|
||||
}
|
||||
|
||||
size_t base32_decoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
|
||||
return (inlen / 8) * 5 + (remainder * 5) / 8;
|
||||
}
|
||||
|
||||
void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out) {
|
||||
if (length >= 1) {
|
||||
out[0] = (in[0] >> 3);
|
||||
out[1] = (in[0] & 7) << 2;
|
||||
}
|
||||
|
||||
if (length >= 2) {
|
||||
out[1] |= (in[1] >> 6);
|
||||
out[2] = (in[1] >> 1) & 31;
|
||||
out[3] = (in[1] & 1) << 4;
|
||||
}
|
||||
|
||||
if (length >= 3) {
|
||||
out[3] |= (in[2] >> 4);
|
||||
out[4] = (in[2] & 15) << 1;
|
||||
}
|
||||
|
||||
if (length >= 4) {
|
||||
out[4] |= (in[3] >> 7);
|
||||
out[5] = (in[3] >> 2) & 31;
|
||||
out[6] = (in[3] & 3) << 3;
|
||||
}
|
||||
|
||||
if (length >= 5) {
|
||||
out[6] |= (in[4] >> 5);
|
||||
out[7] = (in[4] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet) {
|
||||
if (length == 1 || length == 3 || length == 6 || length > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alphabet) {
|
||||
uint8_t decoded[length];
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_decode_character(in[i], alphabet);
|
||||
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
decoded[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
base32_8to5_raw(decoded, length, out);
|
||||
} else {
|
||||
base32_8to5_raw(in, length, out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out) {
|
||||
if (length >= 2) {
|
||||
out[0] = (in[0] << 3);
|
||||
out[0] |= (in[1] >> 2);
|
||||
}
|
||||
|
||||
if (length >= 4) {
|
||||
out[1] = (in[1] & 3) << 6;
|
||||
out[1] |= (in[2] << 1);
|
||||
out[1] |= (in[3] >> 4);
|
||||
}
|
||||
|
||||
if (length >= 5) {
|
||||
out[2] = (in[3] & 15) << 4;
|
||||
out[2] |= (in[4] >> 1);
|
||||
}
|
||||
|
||||
if (length >= 7) {
|
||||
out[3] = (in[4] & 1) << 7;
|
||||
out[3] |= (in[5] << 2);
|
||||
out[3] |= (in[6] >> 3);
|
||||
}
|
||||
|
||||
if (length >= 8) {
|
||||
out[4] = (in[6] & 7) << 5;
|
||||
out[4] |= (in[7] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
int base32_encode_character(uint8_t decoded, const char *alphabet) {
|
||||
if (decoded >> 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (decoded < 26) {
|
||||
return 'A' + decoded;
|
||||
} else {
|
||||
return '2' - 26 + decoded;
|
||||
}
|
||||
}
|
||||
|
||||
return alphabet[decoded];
|
||||
}
|
||||
|
||||
int base32_decode_character(char encoded, const char *alphabet) {
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (encoded >= 'A' && encoded <= 'Z') {
|
||||
return encoded - 'A';
|
||||
} else if (encoded >= 'a' && encoded <= 'z') {
|
||||
return encoded - 'a';
|
||||
} else if (encoded >= '2' && encoded <= '7') {
|
||||
return encoded - '2' + 26;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *occurrence = strchr(alphabet, encoded);
|
||||
|
||||
if (occurrence) {
|
||||
return occurrence - alphabet;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
41
src/crypto/bip39/base32.h
Normal file
41
src/crypto/bip39/base32.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BASE32_H__
|
||||
#define __BASE32_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern const char *BASE32_ALPHABET_RFC4648;
|
||||
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet);
|
||||
void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out);
|
||||
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet);
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet);
|
||||
|
||||
size_t base32_encoded_length(size_t inlen);
|
||||
size_t base32_decoded_length(size_t inlen);
|
||||
|
||||
#endif
|
||||
285
src/crypto/bip39/base58.c
Normal file
285
src/crypto/bip39/base58.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
* Copyright (c) 2012-2014 Luke Dashjr
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include "base58.h"
|
||||
#include "sha2.h"
|
||||
#include "ripemd160.h"
|
||||
#include "memzero.h"
|
||||
|
||||
const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
const int8_t b58digits_map[] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
|
||||
-1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
|
||||
22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
|
||||
-1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
|
||||
47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
|
||||
};
|
||||
|
||||
bool b58tobin(void *bin, size_t *binszp, const char *b58)
|
||||
{
|
||||
size_t binsz = *binszp;
|
||||
|
||||
if (binsz == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char *b58u = (const unsigned char*)b58;
|
||||
unsigned char *binu = bin;
|
||||
size_t outisz = (binsz + 3) / 4;
|
||||
uint32_t outi[outisz];
|
||||
uint64_t t;
|
||||
uint32_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
size_t b58sz;
|
||||
|
||||
b58sz = strlen(b58);
|
||||
|
||||
memzero(outi, sizeof(outi));
|
||||
|
||||
// Leading zeros, just count
|
||||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
|
||||
++zerocount;
|
||||
|
||||
for ( ; i < b58sz; ++i)
|
||||
{
|
||||
if (b58u[i] & 0x80)
|
||||
// High-bit set on invalid digit
|
||||
return false;
|
||||
if (b58digits_map[b58u[i]] == -1)
|
||||
// Invalid base58 digit
|
||||
return false;
|
||||
c = (unsigned)b58digits_map[b58u[i]];
|
||||
for (j = outisz; j--; )
|
||||
{
|
||||
t = ((uint64_t)outi[j]) * 58 + c;
|
||||
c = (t & 0x3f00000000) >> 32;
|
||||
outi[j] = t & 0xffffffff;
|
||||
}
|
||||
if (c)
|
||||
// Output number too big (carry to the next int32)
|
||||
return false;
|
||||
if (outi[0] & zeromask)
|
||||
// Output number too big (last int32 filled too far)
|
||||
return false;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
switch (bytesleft) {
|
||||
case 3:
|
||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
||||
//-fallthrough
|
||||
case 2:
|
||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
||||
//-fallthrough
|
||||
case 1:
|
||||
*(binu++) = (outi[0] & 0xff);
|
||||
++j;
|
||||
//-fallthrough
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (; j < outisz; ++j)
|
||||
{
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
}
|
||||
|
||||
// Count canonical base58 byte count
|
||||
binu = bin;
|
||||
for (i = 0; i < binsz; ++i)
|
||||
{
|
||||
if (binu[i]) {
|
||||
if (zerocount > i) {
|
||||
/* result too large */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
--*binszp;
|
||||
}
|
||||
*binszp += zerocount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4)
|
||||
return -4;
|
||||
hasher_Raw(hasher_type, bin, binsz - 4, buf);
|
||||
if (memcmp(&binc[binsz - 4], buf, 4))
|
||||
return -1;
|
||||
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
|
||||
{} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1')
|
||||
return -3;
|
||||
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
|
||||
{
|
||||
const uint8_t *bin = data;
|
||||
int carry;
|
||||
ssize_t i, j, high, zcount = 0;
|
||||
size_t size;
|
||||
|
||||
while (zcount < (ssize_t)binsz && !bin[zcount])
|
||||
++zcount;
|
||||
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t buf[size];
|
||||
memzero(buf, size);
|
||||
|
||||
for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j)
|
||||
{
|
||||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
|
||||
{
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < (ssize_t)size && !buf[j]; ++j);
|
||||
|
||||
if (*b58sz <= zcount + size - j)
|
||||
{
|
||||
*b58sz = zcount + size - j + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zcount)
|
||||
memset(b58, '1', zcount);
|
||||
for (i = zcount; j < (ssize_t)size; ++i, ++j)
|
||||
b58[i] = b58digits_ordered[buf[j]];
|
||||
b58[i] = '\0';
|
||||
*b58sz = i + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int base58_encode_check(const uint8_t *data, int datalen, HasherType hasher_type, char *str, int strsize)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
hasher_Raw(hasher_type, data, datalen, hash);
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
}
|
||||
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58check(nd, res, hasher_type, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
}
|
||||
|
||||
#if USE_GRAPHENE
|
||||
int b58gphcheck(const void *bin, size_t binsz, const char *base58str)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4)
|
||||
return -4;
|
||||
ripemd160(bin, binsz - 4, buf); // No double SHA256, but a single RIPEMD160
|
||||
if (memcmp(&binc[binsz - 4], buf, 4))
|
||||
return -1;
|
||||
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
|
||||
{} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1')
|
||||
return -3;
|
||||
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
ripemd160(data, datalen, hash); // No double SHA256, but a single RIPEMD160
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
}
|
||||
|
||||
int base58gph_decode_check(const char *str, uint8_t *data, int datalen)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58gphcheck(nd, res, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
}
|
||||
#endif
|
||||
49
src/crypto/bip39/base58.h
Normal file
49
src/crypto/bip39/base58.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BASE58_H__
|
||||
#define __BASE58_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
extern const char b58digits_ordered[];
|
||||
extern const int8_t b58digits_map[];
|
||||
|
||||
int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize);
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen);
|
||||
|
||||
// Private
|
||||
bool b58tobin(void *bin, size_t *binszp, const char *b58);
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str);
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz);
|
||||
|
||||
#if USE_GRAPHENE
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize);
|
||||
int base58gph_decode_check(const char *str, uint8_t *data, int datalen);
|
||||
int b58gphcheck(const void *bin, size_t binsz, const char *base58str);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
112
src/crypto/bip39/bip32.h
Normal file
112
src/crypto/bip39/bip32.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BIP32_H__
|
||||
#define __BIP32_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "ecdsa.h"
|
||||
#include "ed25519-donna/ed25519.h"
|
||||
#include "options.h"
|
||||
|
||||
typedef struct {
|
||||
const char *bip32_name; // string for generating BIP32 xprv from seed
|
||||
const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519
|
||||
|
||||
HasherType hasher_base58;
|
||||
HasherType hasher_sign;
|
||||
HasherType hasher_pubkey;
|
||||
HasherType hasher_script;
|
||||
} curve_info;
|
||||
|
||||
typedef struct {
|
||||
uint32_t depth;
|
||||
uint32_t child_num;
|
||||
uint8_t chain_code[32];
|
||||
|
||||
uint8_t private_key[32];
|
||||
uint8_t private_key_extension[32];
|
||||
|
||||
uint8_t public_key[33];
|
||||
const curve_info *curve;
|
||||
} HDNode;
|
||||
|
||||
int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out);
|
||||
|
||||
int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out);
|
||||
|
||||
int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out);
|
||||
|
||||
#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000))
|
||||
|
||||
int hdnode_private_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
#if USE_CARDANO
|
||||
int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i);
|
||||
int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out);
|
||||
#endif
|
||||
|
||||
int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code);
|
||||
|
||||
int hdnode_public_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat);
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint);
|
||||
#endif
|
||||
|
||||
uint32_t hdnode_fingerprint(HDNode *node);
|
||||
|
||||
void hdnode_fill_public_key(HDNode *node);
|
||||
|
||||
#if USE_ETHEREUM
|
||||
int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash);
|
||||
#endif
|
||||
|
||||
#if USE_NEM
|
||||
int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address);
|
||||
int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key);
|
||||
int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);
|
||||
int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);
|
||||
#endif
|
||||
|
||||
int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
|
||||
int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size);
|
||||
|
||||
int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);
|
||||
|
||||
int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);
|
||||
|
||||
int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint);
|
||||
|
||||
void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw);
|
||||
void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize);
|
||||
|
||||
const curve_info *get_curve_by_name(const char *curve_name);
|
||||
|
||||
#endif
|
||||
283
src/crypto/bip39/bip39.c
Normal file
283
src/crypto/bip39/bip39.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bip39.h"
|
||||
#include "bip39_english.h"
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
#include "pbkdf2.h"
|
||||
#include "rand.h"
|
||||
#include "sha2.h"
|
||||
|
||||
#if USE_BIP39_CACHE
|
||||
|
||||
int BIP39_WORDS = 2048;
|
||||
|
||||
static int bip39_cache_index = 0;
|
||||
|
||||
static CONFIDENTIAL struct {
|
||||
bool set;
|
||||
char mnemonic[256];
|
||||
char passphrase[64];
|
||||
uint8_t seed[512 / 8];
|
||||
} bip39_cache[BIP39_CACHE_SIZE];
|
||||
|
||||
#endif
|
||||
|
||||
const char *mnemonic_generate(int strength) {
|
||||
if (strength % 32 || strength < 128 || strength > 256) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t data[32] = {0};
|
||||
random_buffer(data, 32);
|
||||
const char *r = mnemonic_from_data(data, strength / 8);
|
||||
memzero(data, sizeof(data));
|
||||
return r;
|
||||
}
|
||||
|
||||
static CONFIDENTIAL char mnemo[24 * 10];
|
||||
|
||||
const char *mnemonic_from_data(const uint8_t *data, int len) {
|
||||
if (len % 4 || len < 16 || len > 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
|
||||
sha256_Raw(data, len, bits);
|
||||
// checksum
|
||||
bits[len] = bits[0];
|
||||
// data
|
||||
memcpy(bits, data, len);
|
||||
|
||||
int mlen = len * 3 / 4;
|
||||
|
||||
int i = 0, j = 0, idx = 0;
|
||||
char *p = mnemo;
|
||||
for (i = 0; i < mlen; i++) {
|
||||
idx = 0;
|
||||
for (j = 0; j < 11; j++) {
|
||||
idx <<= 1;
|
||||
idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
|
||||
}
|
||||
strcpy(p, wordlist[idx]);
|
||||
p += strlen(wordlist[idx]);
|
||||
*p = (i < mlen - 1) ? ' ' : 0;
|
||||
p++;
|
||||
}
|
||||
memzero(bits, sizeof(bits));
|
||||
|
||||
return mnemo;
|
||||
}
|
||||
|
||||
void mnemonic_clear(void) { memzero(mnemo, sizeof(mnemo)); }
|
||||
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) {
|
||||
if (!mnemonic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i = 0, n = 0;
|
||||
|
||||
while (mnemonic[i]) {
|
||||
if (mnemonic[i] == ' ') {
|
||||
n++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
|
||||
// check number of words
|
||||
if (n != 12 && n != 18 && n != 24) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char current_word[10] = {0};
|
||||
uint32_t j = 0, k = 0, ki = 0, bi = 0;
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
|
||||
memzero(bits, sizeof(bits));
|
||||
i = 0;
|
||||
while (mnemonic[i]) {
|
||||
j = 0;
|
||||
while (mnemonic[i] != ' ' && mnemonic[i] != 0) {
|
||||
if (j >= sizeof(current_word) - 1) {
|
||||
return 0;
|
||||
}
|
||||
current_word[j] = mnemonic[i];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
current_word[j] = 0;
|
||||
if (mnemonic[i] != 0) {
|
||||
i++;
|
||||
}
|
||||
k = 0;
|
||||
for (;;) {
|
||||
if (!wordlist[k]) { // word not found
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k
|
||||
for (ki = 0; ki < 11; ki++) {
|
||||
if (k & (1 << (10 - ki))) {
|
||||
bits[bi / 8] |= 1 << (7 - (bi % 8));
|
||||
}
|
||||
bi++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
if (bi != n * 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(entropy, bits, sizeof(bits));
|
||||
return n * 11;
|
||||
}
|
||||
|
||||
int mnemonic_check(const char *mnemonic) {
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
int seed_len = mnemonic_to_entropy(mnemonic, bits);
|
||||
if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {
|
||||
return 0;
|
||||
}
|
||||
int words = seed_len / 11;
|
||||
|
||||
uint8_t checksum = bits[words * 4 / 3];
|
||||
sha256_Raw(bits, words * 4 / 3, bits);
|
||||
if (words == 12) {
|
||||
return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits
|
||||
} else if (words == 18) {
|
||||
return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits
|
||||
} else if (words == 24) {
|
||||
return bits[0] == checksum; // compare 8 bits
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase,
|
||||
uint8_t seed[512 / 8],
|
||||
void (*progress_callback)(uint32_t current,
|
||||
uint32_t total)) {
|
||||
int mnemoniclen = strlen(mnemonic);
|
||||
int passphraselen = strnlen(passphrase, 256);
|
||||
#if USE_BIP39_CACHE
|
||||
// check cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
for (int i = 0; i < BIP39_CACHE_SIZE; i++) {
|
||||
if (!bip39_cache[i].set) continue;
|
||||
if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
|
||||
if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
|
||||
// found the correct entry
|
||||
memcpy(seed, bip39_cache[i].seed, 512 / 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uint8_t salt[8 + 256] = {0};
|
||||
memcpy(salt, "mnemonic", 8);
|
||||
memcpy(salt + 8, passphrase, passphraselen);
|
||||
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt,
|
||||
passphraselen + 8, 1);
|
||||
if (progress_callback) {
|
||||
progress_callback(0, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
|
||||
if (progress_callback) {
|
||||
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16,
|
||||
BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, seed);
|
||||
memzero(salt, sizeof(salt));
|
||||
#if USE_BIP39_CACHE
|
||||
// store to cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
bip39_cache[bip39_cache_index].set = true;
|
||||
strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);
|
||||
strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);
|
||||
memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);
|
||||
bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// binary search for finding the word in the wordlist
|
||||
int mnemonic_find_word(const char *word) {
|
||||
int lo = 0, hi = BIP39_WORDS - 1;
|
||||
while (lo <= hi) {
|
||||
int mid = lo + (hi - lo) / 2;
|
||||
int cmp = strcmp(word, wordlist[mid]);
|
||||
if (cmp == 0) {
|
||||
return mid;
|
||||
}
|
||||
if (cmp > 0) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *mnemonic_complete_word(const char *prefix, int len) {
|
||||
// we need to perform linear search,
|
||||
// because we want to return the first match
|
||||
for (const char *const *w = wordlist; *w != 0; w++) {
|
||||
if (strncmp(*w, prefix, len) == 0) {
|
||||
return *w;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *mnemonic_get_word(int index) {
|
||||
if (index >= 0 && index < BIP39_WORDS) {
|
||||
return wordlist[index];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mnemonic_word_completion_mask(const char *prefix, int len) {
|
||||
if (len <= 0) {
|
||||
return 0x3ffffff; // all letters (bits 1-26 set)
|
||||
}
|
||||
uint32_t res = 0;
|
||||
for (const char *const *w = wordlist; *w != 0; w++) {
|
||||
const char *word = *w;
|
||||
if (strncmp(word, prefix, len) == 0 && word[len] >= 'a' &&
|
||||
word[len] <= 'z') {
|
||||
res |= 1 << (word[len] - 'a');
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
44
src/crypto/bip39/bip39.h
Normal file
44
src/crypto/bip39/bip39.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BIP39_H__
|
||||
#define __BIP39_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BIP39_PBKDF2_ROUNDS 2048
|
||||
|
||||
const char *mnemonic_generate(int strength); // strength in bits
|
||||
const char *mnemonic_from_data(const uint8_t *data, int len);
|
||||
void mnemonic_clear(void);
|
||||
|
||||
int mnemonic_check(const char *mnemonic);
|
||||
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy);
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total));
|
||||
|
||||
const char * const *mnemonic_wordlist(void);
|
||||
|
||||
#endif
|
||||
2074
src/crypto/bip39/bip39_english.h
Normal file
2074
src/crypto/bip39/bip39_english.h
Normal file
File diff suppressed because it is too large
Load Diff
29
src/crypto/bip39/bip39_mnemonic.c
Normal file
29
src/crypto/bip39/bip39_mnemonic.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "bip39.h"
|
||||
#include <sodium.h>
|
||||
|
||||
// NOTE: We must override this to implement actual RNG!
|
||||
void random_buffer(uint8_t *buf, size_t len) {
|
||||
if( len > 0 ) {
|
||||
randombytes_buf(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *this = argv[0];
|
||||
if (argc > 1) {
|
||||
fprintf(stderr, "Usage: %s\n", this);
|
||||
return 1;
|
||||
}
|
||||
if (sodium_init() == -1) {
|
||||
fprintf(stderr, "libsodium init failed! :(\n");
|
||||
return 1;
|
||||
}
|
||||
int strength = 256;
|
||||
const char *mnemonic = mnemonic_generate(strength);
|
||||
printf("%s\n", mnemonic);
|
||||
return 0;
|
||||
}
|
||||
87
src/crypto/bip39/bip39bruteforce.c
Normal file
87
src/crypto/bip39/bip39bruteforce.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "bip39.h"
|
||||
#include "bip32.h"
|
||||
#include "ecdsa.h"
|
||||
#include "curves.h"
|
||||
|
||||
char iter[256];
|
||||
uint8_t seed[512 / 8];
|
||||
uint8_t addr[21], pubkeyhash[20];
|
||||
int count = 0, found = 0;
|
||||
HDNode node;
|
||||
clock_t start;
|
||||
|
||||
// around 280 tries per second
|
||||
|
||||
// testing data:
|
||||
//
|
||||
// mnemonic: "all all all all all all all all all all all all"
|
||||
// address: "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL"
|
||||
// passphrase: ""
|
||||
//
|
||||
// mnemonic: "all all all all all all all all all all all all"
|
||||
// address: "1N3uJ5AU3FTYQ1ZQgTMtYmgSvMBmQiGVBS"
|
||||
// passphrase: "testing"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n");
|
||||
return 1;
|
||||
}
|
||||
const char *address = argv[1];
|
||||
const char *mnemonic, *item;
|
||||
if (argc == 3) {
|
||||
mnemonic = argv[2];
|
||||
item = "passphrase";
|
||||
} else {
|
||||
mnemonic = NULL;
|
||||
item = "mnemonic";
|
||||
}
|
||||
if (mnemonic && !mnemonic_check(mnemonic)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic);
|
||||
return 2;
|
||||
}
|
||||
if (!ecdsa_address_decode(address, 0, HASHER_SHA2, addr)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid address\n", address);
|
||||
return 3;
|
||||
}
|
||||
printf("Reading %ss from stdin ...\n", item);
|
||||
start = clock();
|
||||
for (;;) {
|
||||
if (fgets(iter, 256, stdin) == NULL) break;
|
||||
int len = strlen(iter);
|
||||
if (len <= 0) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
iter[len - 1] = 0;
|
||||
if (mnemonic) {
|
||||
mnemonic_to_seed(mnemonic, iter, seed, NULL);
|
||||
} else {
|
||||
mnemonic_to_seed(iter, "", seed, NULL);
|
||||
}
|
||||
hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node);
|
||||
hdnode_private_ckd_prime(&node, 44);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_fill_public_key(&node);
|
||||
ecdsa_get_pubkeyhash(node.public_key, HASHER_SHA2, pubkeyhash);
|
||||
if (memcmp(addr + 1, pubkeyhash, 20) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float dur = (float)(clock() - start) / CLOCKS_PER_SEC;
|
||||
printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur, (float)count/dur);
|
||||
if (found) {
|
||||
printf("Correct %s found! :-)\n\"%s\"\n", item, iter);
|
||||
return 0;
|
||||
}
|
||||
printf("Correct %s not found. :-(\n", item);
|
||||
return 4;
|
||||
}
|
||||
53
src/crypto/bip39/blake256.h
Normal file
53
src/crypto/bip39/blake256.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2014-2017, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#ifndef __BLAKE256_H__
|
||||
#define __BLAKE256_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define BLAKE256_DIGEST_LENGTH 32
|
||||
#define BLAKE256_BLOCK_LENGTH 64
|
||||
|
||||
typedef struct {
|
||||
uint32_t h[8], s[4], t[2];
|
||||
size_t buflen;
|
||||
uint8_t nullt;
|
||||
uint8_t buf[64];
|
||||
} BLAKE256_CTX;
|
||||
|
||||
void blake256_Init(BLAKE256_CTX *);
|
||||
void blake256_Update(BLAKE256_CTX *, const uint8_t *, size_t);
|
||||
void blake256_Final(BLAKE256_CTX *, uint8_t *);
|
||||
|
||||
void blake256(const uint8_t *, size_t, uint8_t *);
|
||||
|
||||
#endif /* __BLAKE256_H__ */
|
||||
39
src/crypto/bip39/blake2_common.h
Normal file
39
src/crypto/bip39/blake2_common.h
Normal file
@@ -0,0 +1,39 @@
|
||||
static inline uint32_t load32( const void *src )
|
||||
{
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline uint64_t load64( const void *src )
|
||||
{
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline void store16( void *dst, uint16_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline void store32( void *dst, uint32_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline void store64( void *dst, uint64_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
41
src/crypto/bip39/blake2b.h
Normal file
41
src/crypto/bip39/blake2b.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef __BLAKE2B_H__
|
||||
#define __BLAKE2B_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct __blake2b_state
|
||||
{
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
#define BLAKE2B_CTX blake2b_state
|
||||
#define BLAKE2B_BLOCK_LENGTH BLAKE2B_BLOCKBYTES
|
||||
#define BLAKE2B_DIGEST_LENGTH BLAKE2B_OUTBYTES
|
||||
#define BLAKE2B_KEY_LENGTH BLAKE2B_KEYBYTES
|
||||
|
||||
int blake2b_Init(blake2b_state *S, size_t outlen);
|
||||
int blake2b_InitKey(blake2b_state *S, size_t outlen, const void *key, size_t keylen);
|
||||
int blake2b_InitPersonal(blake2b_state *S, size_t outlen, const void *personal, size_t personal_len);
|
||||
int blake2b_Update(blake2b_state *S, const void *pin, size_t inlen);
|
||||
int blake2b_Final(blake2b_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2b(const uint8_t *msg, uint32_t msg_len, void *out, size_t outlen);
|
||||
int blake2b_Key(const uint8_t *msg, uint32_t msg_len, const void *key, size_t keylen, void *out, size_t outlen);
|
||||
|
||||
#endif
|
||||
41
src/crypto/bip39/blake2s.h
Normal file
41
src/crypto/bip39/blake2s.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef __BLAKE2S_H__
|
||||
#define __BLAKE2S_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
typedef struct __blake2s_state
|
||||
{
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
uint32_t buflen;
|
||||
uint8_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
#define BLAKE2S_CTX blake2s_state
|
||||
#define BLAKE2S_BLOCK_LENGTH BLAKE2S_BLOCKBYTES
|
||||
#define BLAKE2S_DIGEST_LENGTH BLAKE2S_OUTBYTES
|
||||
#define BLAKE2S_KEY_LENGTH BLAKE2S_KEYBYTES
|
||||
|
||||
int blake2s_Init(blake2s_state *S, size_t outlen);
|
||||
int blake2s_InitKey(blake2s_state *S, size_t outlen, const void *key, size_t keylen);
|
||||
int blake2s_InitPersonal(blake2s_state *S, size_t outlen, const void *personal, size_t personal_len);
|
||||
int blake2s_Update(blake2s_state *S, const void *pin, size_t inlen);
|
||||
int blake2s_Final(blake2s_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2s(const uint8_t *msg, uint32_t msg_len, void *out, size_t outlen);
|
||||
int blake2s_Key(const uint8_t *msg, uint32_t msg_len, const void *key, size_t keylen, void *out, size_t outlen);
|
||||
|
||||
#endif
|
||||
144
src/crypto/bip39/hasher.c
Normal file
144
src/crypto/bip39/hasher.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hasher.h"
|
||||
#include "ripemd160.h"
|
||||
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size) {
|
||||
hasher->type = type;
|
||||
hasher->param = param;
|
||||
hasher->param_size = param_size;
|
||||
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Init(&hasher->ctx.sha2);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
#endif
|
||||
sha3_256_Init(&hasher->ctx.sha3);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Init(&hasher->ctx.blake);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Init(&hasher->ctx.groestl);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
blake2b_Init(&hasher->ctx.blake2b, 32);
|
||||
break;
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_InitPersonal(&hasher->ctx.blake2b, 32, hasher->param, hasher->param_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Init(Hasher *hasher, HasherType type) {
|
||||
hasher_InitParam(hasher, type, NULL, 0);
|
||||
}
|
||||
|
||||
void hasher_Reset(Hasher *hasher) {
|
||||
hasher_InitParam(hasher, hasher->type, hasher->param, hasher->param_size);
|
||||
}
|
||||
|
||||
void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length) {
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Update(&hasher->ctx.sha2, data, length);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
#endif
|
||||
sha3_Update(&hasher->ctx.sha3, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Update(&hasher->ctx.blake, data, length);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Update(&hasher->ctx.groestl, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Update(&hasher->ctx.blake2b, data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]) {
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
break;
|
||||
case HASHER_SHA2D:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
sha3_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
keccak_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
#endif
|
||||
case HASHER_BLAKE:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
break;
|
||||
case HASHER_BLAKED:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
hasher_Raw(HASHER_BLAKE, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_DoubleTrunc(&hasher->ctx.groestl, hash);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Final(&hasher->ctx.blake2b, hash, 32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]) {
|
||||
Hasher hasher;
|
||||
|
||||
hasher_Init(&hasher, type);
|
||||
hasher_Update(&hasher, data, length);
|
||||
hasher_Final(&hasher, hash);
|
||||
}
|
||||
80
src/crypto/bip39/hasher.h
Normal file
80
src/crypto/bip39/hasher.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __HASHER_H__
|
||||
#define __HASHER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha3.h"
|
||||
#include "blake256.h"
|
||||
#include "groestl.h"
|
||||
#include "blake2b.h"
|
||||
|
||||
#define HASHER_DIGEST_LENGTH 32
|
||||
|
||||
typedef enum {
|
||||
HASHER_SHA2,
|
||||
HASHER_SHA2D,
|
||||
HASHER_SHA2_RIPEMD,
|
||||
|
||||
HASHER_SHA3,
|
||||
#if USE_KECCAK
|
||||
HASHER_SHA3K,
|
||||
#endif
|
||||
|
||||
HASHER_BLAKE,
|
||||
HASHER_BLAKED,
|
||||
HASHER_BLAKE_RIPEMD,
|
||||
|
||||
HASHER_GROESTLD_TRUNC, /* Double Groestl512 hasher truncated to 256 bits */
|
||||
|
||||
HASHER_BLAKE2B,
|
||||
HASHER_BLAKE2B_PERSONAL,
|
||||
} HasherType;
|
||||
|
||||
typedef struct {
|
||||
HasherType type;
|
||||
|
||||
union {
|
||||
SHA256_CTX sha2; // for HASHER_SHA2{,D}
|
||||
SHA3_CTX sha3; // for HASHER_SHA3{,K}
|
||||
BLAKE256_CTX blake; // for HASHER_BLAKE{,D}
|
||||
GROESTL512_CTX groestl; // for HASHER_GROESTLD_TRUNC
|
||||
BLAKE2B_CTX blake2b; // for HASHER_BLAKE2B{,_PERSONAL}
|
||||
} ctx;
|
||||
|
||||
const void *param;
|
||||
uint32_t param_size;
|
||||
} Hasher;
|
||||
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size);
|
||||
void hasher_Init(Hasher *hasher, HasherType type);
|
||||
void hasher_Reset(Hasher *hasher);
|
||||
void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length);
|
||||
void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]);
|
||||
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]);
|
||||
|
||||
#endif
|
||||
176
src/crypto/bip39/hmac.c
Normal file
176
src/crypto/bip39/hmac.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
sha256_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha256_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) {
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);
|
||||
sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
static CONFIDENTIAL HMAC_SHA256_CTX hctx;
|
||||
hmac_sha256_Init(&hctx, key, keylen);
|
||||
hmac_sha256_Update(&hctx, msg, msglen);
|
||||
hmac_sha256_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint32_t *opad_digest, uint32_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA256_CTX context;
|
||||
sha256_Init(&context);
|
||||
sha256_Update(&context, key, keylen);
|
||||
sha256_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
uint32_t data = 0;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
sha512_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha512_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) {
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);
|
||||
sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
HMAC_SHA512_CTX hctx = {0};
|
||||
hmac_sha512_Init(&hctx, key, keylen);
|
||||
hmac_sha512_Update(&hctx, msg, msglen);
|
||||
hmac_sha512_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint64_t *opad_digest, uint64_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA512_CTX context;
|
||||
sha512_Init(&context);
|
||||
sha512_Update(&context, key, keylen);
|
||||
sha512_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
uint64_t data = 0;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE64(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
52
src/crypto/bip39/hmac.h
Normal file
52
src/crypto/bip39/hmac.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __HMAC_H__
|
||||
#define __HMAC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _HMAC_SHA256_CTX {
|
||||
uint8_t o_key_pad[SHA256_BLOCK_LENGTH];
|
||||
SHA256_CTX ctx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _HMAC_SHA512_CTX {
|
||||
uint8_t o_key_pad[SHA512_BLOCK_LENGTH];
|
||||
SHA512_CTX ctx;
|
||||
} HMAC_SHA512_CTX;
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen);
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest);
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen);
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest);
|
||||
|
||||
#endif
|
||||
130
src/crypto/bip39/hmac_drbg.c
Normal file
130
src/crypto/bip39/hmac_drbg.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Andrew R. Kozlik
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hmac_drbg.h"
|
||||
#include <string.h>
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
static void update_k(HMAC_DRBG_CTX *ctx, uint8_t domain, const uint8_t *data1,
|
||||
size_t len1, const uint8_t *data2, size_t len2) {
|
||||
// Computes K = HMAC(K, V || domain || data1 || data 2).
|
||||
|
||||
// First hash operation of HMAC.
|
||||
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
|
||||
if (len1 + len2 == 0) {
|
||||
ctx->v[8] = 0x00800000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
|
||||
sha256_Transform(ctx->idig, ctx->v, h);
|
||||
ctx->v[8] = 0x80000000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
} else {
|
||||
SHA256_CTX sha_ctx = {0};
|
||||
memcpy(sha_ctx.state, ctx->idig, SHA256_DIGEST_LENGTH);
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(ctx->v[i], sha_ctx.buffer[i]);
|
||||
#else
|
||||
sha_ctx.buffer[i] = ctx->v[i];
|
||||
#endif
|
||||
}
|
||||
((uint8_t *)sha_ctx.buffer)[SHA256_DIGEST_LENGTH] = domain;
|
||||
sha_ctx.bitcount = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
|
||||
sha256_Update(&sha_ctx, data1, len1);
|
||||
sha256_Update(&sha_ctx, data2, len2);
|
||||
sha256_Final(&sha_ctx, (uint8_t *)h);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++)
|
||||
REVERSE32(h[i], h[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Second hash operation of HMAC.
|
||||
h[8] = 0x80000000;
|
||||
h[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
sha256_Transform(ctx->odig, h, h);
|
||||
|
||||
// Precompute the inner digest and outer digest of K.
|
||||
h[8] = 0;
|
||||
h[15] = 0;
|
||||
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
|
||||
h[i] ^= 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
|
||||
|
||||
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
|
||||
h[i] = h[i] ^ 0x36363636 ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
|
||||
memzero(h, sizeof(h));
|
||||
}
|
||||
|
||||
static void update_v(HMAC_DRBG_CTX *ctx) {
|
||||
sha256_Transform(ctx->idig, ctx->v, ctx->v);
|
||||
sha256_Transform(ctx->odig, ctx->v, ctx->v);
|
||||
}
|
||||
|
||||
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *entropy,
|
||||
size_t entropy_len, const uint8_t *nonce,
|
||||
size_t nonce_len) {
|
||||
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
|
||||
|
||||
// Precompute the inner digest and outer digest of K = 0x00 ... 0x00.
|
||||
memset(h, 0x36, sizeof(h));
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
|
||||
memset(h, 0x5c, sizeof(h));
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
|
||||
|
||||
// Let V = 0x01 ... 0x01.
|
||||
memset(ctx->v, 1, SHA256_DIGEST_LENGTH);
|
||||
for (size_t i = 9; i < 15; i++) ctx->v[i] = 0;
|
||||
ctx->v[8] = 0x80000000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
|
||||
hmac_drbg_reseed(ctx, entropy, entropy_len, nonce, nonce_len);
|
||||
|
||||
memzero(h, sizeof(h));
|
||||
}
|
||||
|
||||
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *entropy, size_t len,
|
||||
const uint8_t *addin, size_t addin_len) {
|
||||
update_k(ctx, 0, entropy, len, addin, addin_len);
|
||||
update_v(ctx);
|
||||
if (len == 0) return;
|
||||
update_k(ctx, 1, entropy, len, addin, addin_len);
|
||||
update_v(ctx);
|
||||
}
|
||||
|
||||
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len) {
|
||||
size_t i = 0;
|
||||
while (i < len) {
|
||||
update_v(ctx);
|
||||
for (size_t j = 0; j < 8 && i < len; j++) {
|
||||
uint32_t r = ctx->v[j];
|
||||
for (int k = 24; k >= 0 && i < len; k -= 8) {
|
||||
buf[i++] = (r >> k) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
update_k(ctx, 0, NULL, 0, NULL, 0);
|
||||
update_v(ctx);
|
||||
}
|
||||
43
src/crypto/bip39/hmac_drbg.h
Normal file
43
src/crypto/bip39/hmac_drbg.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Andrew R. Kozlik
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __HMAC_DRBG_H__
|
||||
#define __HMAC_DRBG_H__
|
||||
|
||||
#include <sha2.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// HMAC based Deterministic Random Bit Generator with SHA-256
|
||||
|
||||
typedef struct _HMAC_DRBG_CTX {
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t v[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
} HMAC_DRBG_CTX;
|
||||
|
||||
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
|
||||
const uint8_t *nonce, size_t nonce_len);
|
||||
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
|
||||
const uint8_t *addin, size_t addin_len);
|
||||
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len);
|
||||
|
||||
#endif
|
||||
66
src/crypto/bip39/memzero.c
Normal file
66
src/crypto/bip39/memzero.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef __STDC_WANT_LIB_EXT1__
|
||||
#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface.
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
#include <strings.h>
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
// C11's bounds-checking interface.
|
||||
#if defined(__STDC_LIB_EXT1__)
|
||||
#define HAVE_MEMSET_S 1
|
||||
#endif
|
||||
|
||||
// GNU C Library version 2.25 or later.
|
||||
#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
// Newlib
|
||||
#if defined( __NEWLIB__)
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
// FreeBSD version 11.0 or later.
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 1100037
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
// OpenBSD version 5.5 or later.
|
||||
#if defined(__OpenBSD__) && OpenBSD >= 201405
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
// NetBSD version 7.2 or later.
|
||||
#if defined(__NetBSD__) && __NetBSD_Version__ >= 702000000
|
||||
#define HAVE_EXPLICIT_MEMSET 1
|
||||
#endif
|
||||
|
||||
// Adapted from https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130
|
||||
|
||||
void memzero(void *const pnt, const size_t len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SecureZeroMemory(pnt, len);
|
||||
#elif defined(HAVE_MEMSET_S)
|
||||
memset_s(pnt, (rsize_t) len, 0, (rsize_t) len);
|
||||
#elif defined(HAVE_EXPLICIT_BZERO)
|
||||
explicit_bzero(pnt, len);
|
||||
#elif defined(HAVE_EXPLICIT_MEMSET)
|
||||
explicit_memset(pnt, 0, len);
|
||||
#else
|
||||
volatile unsigned char *volatile pnt_ =
|
||||
(volatile unsigned char *volatile) pnt;
|
||||
size_t i = (size_t) 0U;
|
||||
|
||||
while (i < len) {
|
||||
pnt_[i++] = 0U;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
8
src/crypto/bip39/memzero.h
Normal file
8
src/crypto/bip39/memzero.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __MEMZERO_H__
|
||||
#define __MEMZERO_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void memzero(void * const pnt, const size_t len);
|
||||
|
||||
#endif
|
||||
99
src/crypto/bip39/options.h
Normal file
99
src/crypto/bip39/options.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __OPTIONS_H__
|
||||
#define __OPTIONS_H__
|
||||
|
||||
// use precomputed Curve Points (some scalar multiples of curve base point G)
|
||||
#ifndef USE_PRECOMPUTED_CP
|
||||
#define USE_PRECOMPUTED_CP 1
|
||||
#endif
|
||||
|
||||
// use fast inverse method
|
||||
#ifndef USE_INVERSE_FAST
|
||||
#define USE_INVERSE_FAST 1
|
||||
#endif
|
||||
|
||||
// support for printing bignum256 structures via printf
|
||||
#ifndef USE_BN_PRINT
|
||||
#define USE_BN_PRINT 0
|
||||
#endif
|
||||
|
||||
// use deterministic signatures
|
||||
#ifndef USE_RFC6979
|
||||
#define USE_RFC6979 1
|
||||
#endif
|
||||
|
||||
// implement BIP32 caching
|
||||
#ifndef USE_BIP32_CACHE
|
||||
#define USE_BIP32_CACHE 1
|
||||
#define BIP32_CACHE_SIZE 10
|
||||
#define BIP32_CACHE_MAXDEPTH 8
|
||||
#endif
|
||||
|
||||
// support constructing BIP32 nodes from ed25519 and curve25519 curves.
|
||||
#ifndef USE_BIP32_25519_CURVES
|
||||
#define USE_BIP32_25519_CURVES 1
|
||||
#endif
|
||||
|
||||
// implement BIP39 caching
|
||||
#ifndef USE_BIP39_CACHE
|
||||
#define USE_BIP39_CACHE 1
|
||||
#define BIP39_CACHE_SIZE 4
|
||||
#endif
|
||||
|
||||
// support Ethereum operations
|
||||
#ifndef USE_ETHEREUM
|
||||
#define USE_ETHEREUM 0
|
||||
#endif
|
||||
|
||||
// support Graphene operations (STEEM, BitShares)
|
||||
#ifndef USE_GRAPHENE
|
||||
#define USE_GRAPHENE 0
|
||||
#endif
|
||||
|
||||
// support NEM operations
|
||||
#ifndef USE_NEM
|
||||
#define USE_NEM 0
|
||||
#endif
|
||||
|
||||
// support MONERO operations
|
||||
#ifndef USE_MONERO
|
||||
#define USE_MONERO 0
|
||||
#endif
|
||||
|
||||
// support CARDANO operations
|
||||
#ifndef USE_CARDANO
|
||||
#define USE_CARDANO 0
|
||||
#endif
|
||||
|
||||
// support Keccak hashing
|
||||
#ifndef USE_KECCAK
|
||||
#define USE_KECCAK 1
|
||||
#endif
|
||||
|
||||
// add way how to mark confidential data
|
||||
#ifndef CONFIDENTIAL
|
||||
#define CONFIDENTIAL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
179
src/crypto/bip39/pbkdf2.c
Normal file
179
src/crypto/bip39/pbkdf2.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "pbkdf2.h"
|
||||
#include <string.h>
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA256_CTX ctx = {0};
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x80000000;
|
||||
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
|
||||
sha256_Update(&ctx, salt, saltlen);
|
||||
sha256_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha256_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha256_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH / sizeof(uint32_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA256_CTX pctx = {0};
|
||||
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha256_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha256_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA512_CTX ctx = {0};
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x8000000000000000;
|
||||
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
|
||||
ctx.bitcount[1] = 0;
|
||||
sha512_Update(&ctx, salt, saltlen);
|
||||
sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha512_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha512_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA512_CTX pctx = {0};
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha512_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA512_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/crypto/bip39/pbkdf2.h
Normal file
56
src/crypto/bip39/pbkdf2.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __PBKDF2_H__
|
||||
#define __PBKDF2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA256_CTX {
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA512_CTX {
|
||||
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA512_CTX;
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations);
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations);
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);
|
||||
|
||||
#endif
|
||||
81
src/crypto/bip39/rand.c
Normal file
81
src/crypto/bip39/rand.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "rand.h"
|
||||
|
||||
#ifndef RAND_PLATFORM_INDEPENDENT
|
||||
|
||||
#pragma message( \
|
||||
"NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.")
|
||||
|
||||
// The following code is not supposed to be used in a production environment.
|
||||
// It's included only to make the library testable.
|
||||
// The message above tries to prevent any accidental use outside of the test
|
||||
// environment.
|
||||
//
|
||||
// You are supposed to replace the random8() and random32() function with your
|
||||
// own secure code. There is also a possibility to replace the random_buffer()
|
||||
// function as it is defined as a weak symbol.
|
||||
|
||||
static uint32_t seed = 0;
|
||||
|
||||
void random_reseed(const uint32_t value) { seed = value; }
|
||||
|
||||
uint32_t random32(void) {
|
||||
// Linear congruential generator from Numerical Recipes
|
||||
// https://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
seed = 1664525 * seed + 1013904223;
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif /* RAND_PLATFORM_INDEPENDENT */
|
||||
|
||||
//
|
||||
// The following code is platform independent
|
||||
//
|
||||
|
||||
void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) {
|
||||
uint32_t r = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i % 4 == 0) {
|
||||
r = random32();
|
||||
}
|
||||
buf[i] = (r >> ((i % 4) * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t random_uniform(uint32_t n) {
|
||||
uint32_t x = 0, max = 0xFFFFFFFF - (0xFFFFFFFF % n);
|
||||
while ((x = random32()) >= max)
|
||||
;
|
||||
return x / (max / n);
|
||||
}
|
||||
|
||||
void random_permute(char *str, size_t len) {
|
||||
for (int i = len - 1; i >= 1; i--) {
|
||||
int j = random_uniform(i + 1);
|
||||
char t = str[j];
|
||||
str[j] = str[i];
|
||||
str[i] = t;
|
||||
}
|
||||
}
|
||||
37
src/crypto/bip39/rand.h
Normal file
37
src/crypto/bip39/rand.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __RAND_H__
|
||||
#define __RAND_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void random_reseed(const uint32_t value);
|
||||
uint32_t random32(void);
|
||||
void random_buffer(uint8_t *buf, size_t len);
|
||||
|
||||
uint32_t random_uniform(uint32_t n);
|
||||
void random_permute(char *buf, size_t len);
|
||||
|
||||
#endif
|
||||
38
src/crypto/bip39/secp256k1.h
Normal file
38
src/crypto/bip39/secp256k1.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __SECP256K1_H__
|
||||
#define __SECP256K1_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ecdsa.h"
|
||||
#include "bip32.h"
|
||||
|
||||
extern const ecdsa_curve secp256k1;
|
||||
extern const curve_info secp256k1_info;
|
||||
extern const curve_info secp256k1_decred_info;
|
||||
extern const curve_info secp256k1_groestl_info;
|
||||
extern const curve_info secp256k1_smart_info;
|
||||
|
||||
#endif
|
||||
1283
src/crypto/bip39/sha2.c
Normal file
1283
src/crypto/bip39/sha2.c
Normal file
File diff suppressed because it is too large
Load Diff
116
src/crypto/bip39/sha2.h
Normal file
116
src/crypto/bip39/sha2.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2001 Aaron D. Gifford
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SHA2_H__
|
||||
#define __SHA2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SHA1_BLOCK_LENGTH 64
|
||||
#define SHA1_DIGEST_LENGTH 20
|
||||
#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
|
||||
#define SHA256_BLOCK_LENGTH 64
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
|
||||
#define SHA512_BLOCK_LENGTH 128
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
|
||||
|
||||
typedef struct _SHA1_CTX {
|
||||
uint32_t state[5];
|
||||
uint64_t bitcount;
|
||||
uint32_t buffer[SHA1_BLOCK_LENGTH/sizeof(uint32_t)];
|
||||
} SHA1_CTX;
|
||||
typedef struct _SHA256_CTX {
|
||||
uint32_t state[8];
|
||||
uint64_t bitcount;
|
||||
uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
|
||||
} SHA256_CTX;
|
||||
typedef struct _SHA512_CTX {
|
||||
uint64_t state[8];
|
||||
uint64_t bitcount[2];
|
||||
uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
|
||||
} SHA512_CTX;
|
||||
|
||||
/*** ENDIAN REVERSAL MACROS *******************************************/
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define REVERSE32(w,x) { \
|
||||
uint32_t tmp = (w); \
|
||||
tmp = (tmp >> 16) | (tmp << 16); \
|
||||
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
|
||||
}
|
||||
#define REVERSE64(w,x) { \
|
||||
uint64_t tmp = (w); \
|
||||
tmp = (tmp >> 32) | (tmp << 32); \
|
||||
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
|
||||
((tmp & 0x00ff00ff00ff00ffULL) << 8); \
|
||||
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
|
||||
((tmp & 0x0000ffff0000ffffULL) << 16); \
|
||||
}
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
||||
extern const uint32_t sha256_initial_hash_value[8];
|
||||
extern const uint64_t sha512_initial_hash_value[8];
|
||||
|
||||
void sha1_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
|
||||
void sha1_Init(SHA1_CTX *);
|
||||
void sha1_Update(SHA1_CTX*, const uint8_t*, size_t);
|
||||
void sha1_Final(SHA1_CTX*, uint8_t[SHA1_DIGEST_LENGTH]);
|
||||
char* sha1_End(SHA1_CTX*, char[SHA1_DIGEST_STRING_LENGTH]);
|
||||
void sha1_Raw(const uint8_t*, size_t, uint8_t[SHA1_DIGEST_LENGTH]);
|
||||
char* sha1_Data(const uint8_t*, size_t, char[SHA1_DIGEST_STRING_LENGTH]);
|
||||
|
||||
void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
|
||||
void sha256_Init(SHA256_CTX *);
|
||||
void sha256_Update(SHA256_CTX*, const uint8_t*, size_t);
|
||||
void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]);
|
||||
char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||
void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]);
|
||||
char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||
|
||||
void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out);
|
||||
void sha512_Init(SHA512_CTX*);
|
||||
void sha512_Update(SHA512_CTX*, const uint8_t*, size_t);
|
||||
void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]);
|
||||
char* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
|
||||
void sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]);
|
||||
char* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
|
||||
|
||||
#endif
|
||||
397
src/crypto/bip39/sha3.c
Normal file
397
src/crypto/bip39/sha3.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha3.h"
|
||||
#include "memzero.h"
|
||||
|
||||
#define I64(x) x##LL
|
||||
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
|
||||
#define le2me_64(x) (x)
|
||||
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
|
||||
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
|
||||
|
||||
/* constants */
|
||||
#define NumberOfRounds 24
|
||||
|
||||
/* SHA3 (Keccak) constants for 24 rounds */
|
||||
static uint64_t keccak_round_constants[NumberOfRounds] = {
|
||||
I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
|
||||
I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
|
||||
I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
|
||||
I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
|
||||
I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
|
||||
I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
|
||||
};
|
||||
|
||||
/* Initializing a sha3 context for given number of output bits */
|
||||
static void keccak_Init(SHA3_CTX *ctx, unsigned bits)
|
||||
{
|
||||
/* NB: The Keccak capacity parameter = bits * 2 */
|
||||
unsigned rate = 1600 - bits * 2;
|
||||
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
ctx->block_size = rate / 8;
|
||||
assert(rate <= 1600 && (rate % 64) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_224_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 224);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_256_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_384_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 384);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_512_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 512);
|
||||
}
|
||||
|
||||
/* Keccak theta() transformation */
|
||||
static void keccak_theta(uint64_t *A)
|
||||
{
|
||||
unsigned int x = 0;
|
||||
uint64_t C[5] = {0}, D[5] = {0};
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
|
||||
}
|
||||
D[0] = ROTL64(C[1], 1) ^ C[4];
|
||||
D[1] = ROTL64(C[2], 1) ^ C[0];
|
||||
D[2] = ROTL64(C[3], 1) ^ C[1];
|
||||
D[3] = ROTL64(C[4], 1) ^ C[2];
|
||||
D[4] = ROTL64(C[0], 1) ^ C[3];
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
A[x] ^= D[x];
|
||||
A[x + 5] ^= D[x];
|
||||
A[x + 10] ^= D[x];
|
||||
A[x + 15] ^= D[x];
|
||||
A[x + 20] ^= D[x];
|
||||
}
|
||||
}
|
||||
|
||||
/* Keccak pi() transformation */
|
||||
static void keccak_pi(uint64_t *A)
|
||||
{
|
||||
uint64_t A1 = 0;
|
||||
A1 = A[1];
|
||||
A[ 1] = A[ 6];
|
||||
A[ 6] = A[ 9];
|
||||
A[ 9] = A[22];
|
||||
A[22] = A[14];
|
||||
A[14] = A[20];
|
||||
A[20] = A[ 2];
|
||||
A[ 2] = A[12];
|
||||
A[12] = A[13];
|
||||
A[13] = A[19];
|
||||
A[19] = A[23];
|
||||
A[23] = A[15];
|
||||
A[15] = A[ 4];
|
||||
A[ 4] = A[24];
|
||||
A[24] = A[21];
|
||||
A[21] = A[ 8];
|
||||
A[ 8] = A[16];
|
||||
A[16] = A[ 5];
|
||||
A[ 5] = A[ 3];
|
||||
A[ 3] = A[18];
|
||||
A[18] = A[17];
|
||||
A[17] = A[11];
|
||||
A[11] = A[ 7];
|
||||
A[ 7] = A[10];
|
||||
A[10] = A1;
|
||||
/* note: A[ 0] is left as is */
|
||||
}
|
||||
|
||||
/* Keccak chi() transformation */
|
||||
static void keccak_chi(uint64_t *A)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < 25; i += 5) {
|
||||
uint64_t A0 = A[0 + i], A1 = A[1 + i];
|
||||
A[0 + i] ^= ~A1 & A[2 + i];
|
||||
A[1 + i] ^= ~A[2 + i] & A[3 + i];
|
||||
A[2 + i] ^= ~A[3 + i] & A[4 + i];
|
||||
A[3 + i] ^= ~A[4 + i] & A0;
|
||||
A[4 + i] ^= ~A0 & A1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sha3_permutation(uint64_t *state)
|
||||
{
|
||||
int round = 0;
|
||||
for (round = 0; round < NumberOfRounds; round++)
|
||||
{
|
||||
keccak_theta(state);
|
||||
|
||||
/* apply Keccak rho() transformation */
|
||||
state[ 1] = ROTL64(state[ 1], 1);
|
||||
state[ 2] = ROTL64(state[ 2], 62);
|
||||
state[ 3] = ROTL64(state[ 3], 28);
|
||||
state[ 4] = ROTL64(state[ 4], 27);
|
||||
state[ 5] = ROTL64(state[ 5], 36);
|
||||
state[ 6] = ROTL64(state[ 6], 44);
|
||||
state[ 7] = ROTL64(state[ 7], 6);
|
||||
state[ 8] = ROTL64(state[ 8], 55);
|
||||
state[ 9] = ROTL64(state[ 9], 20);
|
||||
state[10] = ROTL64(state[10], 3);
|
||||
state[11] = ROTL64(state[11], 10);
|
||||
state[12] = ROTL64(state[12], 43);
|
||||
state[13] = ROTL64(state[13], 25);
|
||||
state[14] = ROTL64(state[14], 39);
|
||||
state[15] = ROTL64(state[15], 41);
|
||||
state[16] = ROTL64(state[16], 45);
|
||||
state[17] = ROTL64(state[17], 15);
|
||||
state[18] = ROTL64(state[18], 21);
|
||||
state[19] = ROTL64(state[19], 8);
|
||||
state[20] = ROTL64(state[20], 18);
|
||||
state[21] = ROTL64(state[21], 2);
|
||||
state[22] = ROTL64(state[22], 61);
|
||||
state[23] = ROTL64(state[23], 56);
|
||||
state[24] = ROTL64(state[24], 14);
|
||||
|
||||
keccak_pi(state);
|
||||
keccak_chi(state);
|
||||
|
||||
/* apply iota(state, round) */
|
||||
*state ^= keccak_round_constants[round];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process the specified block of data.
|
||||
*
|
||||
* @param hash the algorithm state
|
||||
* @param block the message block to process
|
||||
* @param block_size the size of the processed block in bytes
|
||||
*/
|
||||
static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
|
||||
{
|
||||
/* expanded loop */
|
||||
hash[ 0] ^= le2me_64(block[ 0]);
|
||||
hash[ 1] ^= le2me_64(block[ 1]);
|
||||
hash[ 2] ^= le2me_64(block[ 2]);
|
||||
hash[ 3] ^= le2me_64(block[ 3]);
|
||||
hash[ 4] ^= le2me_64(block[ 4]);
|
||||
hash[ 5] ^= le2me_64(block[ 5]);
|
||||
hash[ 6] ^= le2me_64(block[ 6]);
|
||||
hash[ 7] ^= le2me_64(block[ 7]);
|
||||
hash[ 8] ^= le2me_64(block[ 8]);
|
||||
/* if not sha3-512 */
|
||||
if (block_size > 72) {
|
||||
hash[ 9] ^= le2me_64(block[ 9]);
|
||||
hash[10] ^= le2me_64(block[10]);
|
||||
hash[11] ^= le2me_64(block[11]);
|
||||
hash[12] ^= le2me_64(block[12]);
|
||||
/* if not sha3-384 */
|
||||
if (block_size > 104) {
|
||||
hash[13] ^= le2me_64(block[13]);
|
||||
hash[14] ^= le2me_64(block[14]);
|
||||
hash[15] ^= le2me_64(block[15]);
|
||||
hash[16] ^= le2me_64(block[16]);
|
||||
/* if not sha3-256 */
|
||||
if (block_size > 136) {
|
||||
hash[17] ^= le2me_64(block[17]);
|
||||
#ifdef FULL_SHA3_FAMILY_SUPPORT
|
||||
/* if not sha3-224 */
|
||||
if (block_size > 144) {
|
||||
hash[18] ^= le2me_64(block[18]);
|
||||
hash[19] ^= le2me_64(block[19]);
|
||||
hash[20] ^= le2me_64(block[20]);
|
||||
hash[21] ^= le2me_64(block[21]);
|
||||
hash[22] ^= le2me_64(block[22]);
|
||||
hash[23] ^= le2me_64(block[23]);
|
||||
hash[24] ^= le2me_64(block[24]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make a permutation of the hash */
|
||||
sha3_permutation(hash);
|
||||
}
|
||||
|
||||
#define SHA3_FINALIZED 0x80000000
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size)
|
||||
{
|
||||
size_t idx = (size_t)ctx->rest;
|
||||
size_t block_size = (size_t)ctx->block_size;
|
||||
|
||||
if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
|
||||
ctx->rest = (unsigned)((ctx->rest + size) % block_size);
|
||||
|
||||
/* fill partial block */
|
||||
if (idx) {
|
||||
size_t left = block_size - idx;
|
||||
memcpy((char*)ctx->message + idx, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= block_size) {
|
||||
uint64_t *aligned_message_block = NULL;
|
||||
if (IS_ALIGNED_64(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (uint64_t*)(void*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, block_size);
|
||||
aligned_message_block = ctx->message;
|
||||
}
|
||||
|
||||
sha3_process_block(ctx->hash, aligned_message_block, block_size);
|
||||
msg += block_size;
|
||||
size -= block_size;
|
||||
}
|
||||
if (size) {
|
||||
memcpy(ctx->message, msg, size); /* save leftovers */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void sha3_Final(SHA3_CTX *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x06;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
}
|
||||
|
||||
#if USE_KECCAK
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void keccak_Final(SHA3_CTX *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x01;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
}
|
||||
|
||||
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
keccak_256_Init(&ctx);
|
||||
keccak_Update(&ctx, data, len);
|
||||
keccak_Final(&ctx, digest);
|
||||
}
|
||||
|
||||
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
keccak_512_Init(&ctx);
|
||||
keccak_Update(&ctx, data, len);
|
||||
keccak_Final(&ctx, digest);
|
||||
}
|
||||
#endif /* USE_KECCAK */
|
||||
|
||||
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
sha3_256_Init(&ctx);
|
||||
sha3_Update(&ctx, data, len);
|
||||
sha3_Final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
sha3_512_Init(&ctx);
|
||||
sha3_Update(&ctx, data, len);
|
||||
sha3_Final(&ctx, digest);
|
||||
}
|
||||
89
src/crypto/bip39/sha3.h
Normal file
89
src/crypto/bip39/sha3.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#ifndef __SHA3_H__
|
||||
#define __SHA3_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha3_224_hash_size 28
|
||||
#define sha3_256_hash_size 32
|
||||
#define sha3_384_hash_size 48
|
||||
#define sha3_512_hash_size 64
|
||||
#define sha3_max_permutation_size 25
|
||||
#define sha3_max_rate_in_qwords 24
|
||||
|
||||
#define SHA3_224_BLOCK_LENGTH 144
|
||||
#define SHA3_256_BLOCK_LENGTH 136
|
||||
#define SHA3_384_BLOCK_LENGTH 104
|
||||
#define SHA3_512_BLOCK_LENGTH 72
|
||||
|
||||
#define SHA3_224_DIGEST_LENGTH sha3_224_hash_size
|
||||
#define SHA3_256_DIGEST_LENGTH sha3_256_hash_size
|
||||
#define SHA3_384_DIGEST_LENGTH sha3_384_hash_size
|
||||
#define SHA3_512_DIGEST_LENGTH sha3_512_hash_size
|
||||
|
||||
/**
|
||||
* SHA3 Algorithm context.
|
||||
*/
|
||||
typedef struct SHA3_CTX
|
||||
{
|
||||
/* 1600 bits algorithm hashing state */
|
||||
uint64_t hash[sha3_max_permutation_size];
|
||||
/* 1536-bit buffer for leftovers */
|
||||
uint64_t message[sha3_max_rate_in_qwords];
|
||||
/* count of bytes in the message[] buffer */
|
||||
unsigned rest;
|
||||
/* size of a message block processed at once */
|
||||
unsigned block_size;
|
||||
} SHA3_CTX;
|
||||
|
||||
/* methods for calculating the hash function */
|
||||
|
||||
void sha3_224_Init(SHA3_CTX *ctx);
|
||||
void sha3_256_Init(SHA3_CTX *ctx);
|
||||
void sha3_384_Init(SHA3_CTX *ctx);
|
||||
void sha3_512_Init(SHA3_CTX *ctx);
|
||||
void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size);
|
||||
void sha3_Final(SHA3_CTX *ctx, unsigned char* result);
|
||||
|
||||
#if USE_KECCAK
|
||||
#define keccak_224_Init sha3_224_Init
|
||||
#define keccak_256_Init sha3_256_Init
|
||||
#define keccak_384_Init sha3_384_Init
|
||||
#define keccak_512_Init sha3_512_Init
|
||||
#define keccak_Update sha3_Update
|
||||
void keccak_Final(SHA3_CTX *ctx, unsigned char* result);
|
||||
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
#endif
|
||||
|
||||
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __SHA3_H__ */
|
||||
21
src/crypto/ctaes/COPYING
Normal file
21
src/crypto/ctaes/COPYING
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Pieter Wuille
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
41
src/crypto/ctaes/README.md
Normal file
41
src/crypto/ctaes/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
ctaes
|
||||
=====
|
||||
|
||||
Simple C module for constant-time AES encryption and decryption.
|
||||
|
||||
Features:
|
||||
* Simple, pure C code without any dependencies.
|
||||
* No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf.
|
||||
* Very small object code: slightly over 4k of executable code when compiled with -Os.
|
||||
* Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles:
|
||||
|
||||
| Algorithm | Key schedule | Encryption per byte | Decryption per byte |
|
||||
| --------- | ------------:| -------------------:| -------------------:|
|
||||
| AES-128 | 2.8k | 154 | 161 |
|
||||
| AES-192 | 3.1k | 169 | 181 |
|
||||
| AES-256 | 4.0k | 191 | 203 |
|
||||
|
||||
Build steps
|
||||
-----------
|
||||
|
||||
Object code:
|
||||
|
||||
$ gcc -O3 ctaes.c -c -o ctaes.o
|
||||
|
||||
Tests:
|
||||
|
||||
$ gcc -O3 ctaes.c test.c -o test
|
||||
|
||||
Benchmark:
|
||||
|
||||
$ gcc -O3 ctaes.c bench.c -o bench
|
||||
|
||||
Review
|
||||
------
|
||||
|
||||
Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip
|
||||
170
src/crypto/ctaes/bench.c
Normal file
170
src/crypto/ctaes/bench.c
Normal file
@@ -0,0 +1,170 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "sys/time.h"
|
||||
|
||||
#include "ctaes.h"
|
||||
|
||||
static double gettimedouble(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_usec * 0.000001 + tv.tv_sec;
|
||||
}
|
||||
|
||||
static void print_number(double x) {
|
||||
double y = x;
|
||||
int c = 0;
|
||||
if (y < 0.0) {
|
||||
y = -y;
|
||||
}
|
||||
while (y < 100.0) {
|
||||
y *= 10.0;
|
||||
c++;
|
||||
}
|
||||
printf("%.*f", c, x);
|
||||
}
|
||||
|
||||
static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
|
||||
int i;
|
||||
double min = HUGE_VAL;
|
||||
double sum = 0.0;
|
||||
double max = 0.0;
|
||||
for (i = 0; i < count; i++) {
|
||||
double begin, total;
|
||||
if (setup != NULL) {
|
||||
setup(data);
|
||||
}
|
||||
begin = gettimedouble();
|
||||
benchmark(data);
|
||||
total = gettimedouble() - begin;
|
||||
if (teardown != NULL) {
|
||||
teardown(data);
|
||||
}
|
||||
if (total < min) {
|
||||
min = total;
|
||||
}
|
||||
if (total > max) {
|
||||
max = total;
|
||||
}
|
||||
sum += total;
|
||||
}
|
||||
printf("%s: min ", name);
|
||||
print_number(min * 1000000000.0 / iter);
|
||||
printf("ns / avg ");
|
||||
print_number((sum / count) * 1000000000.0 / iter);
|
||||
printf("ns / max ");
|
||||
print_number(max * 1000000000.0 / iter);
|
||||
printf("ns\n");
|
||||
}
|
||||
|
||||
static void bench_AES128_init(void* data) {
|
||||
AES128_ctx* ctx = (AES128_ctx*)data;
|
||||
int i;
|
||||
for (i = 0; i < 50000; i++) {
|
||||
AES128_init(ctx, (unsigned char*)ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES128_encrypt_setup(void* data) {
|
||||
AES128_ctx* ctx = (AES128_ctx*)data;
|
||||
static const unsigned char key[16] = {0};
|
||||
AES128_init(ctx, key);
|
||||
}
|
||||
|
||||
static void bench_AES128_encrypt(void* data) {
|
||||
const AES128_ctx* ctx = (const AES128_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES128_encrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES128_decrypt(void* data) {
|
||||
const AES128_ctx* ctx = (const AES128_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES128_decrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES192_init(void* data) {
|
||||
AES192_ctx* ctx = (AES192_ctx*)data;
|
||||
int i;
|
||||
for (i = 0; i < 50000; i++) {
|
||||
AES192_init(ctx, (unsigned char*)ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES192_encrypt_setup(void* data) {
|
||||
AES192_ctx* ctx = (AES192_ctx*)data;
|
||||
static const unsigned char key[16] = {0};
|
||||
AES192_init(ctx, key);
|
||||
}
|
||||
|
||||
static void bench_AES192_encrypt(void* data) {
|
||||
const AES192_ctx* ctx = (const AES192_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES192_encrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES192_decrypt(void* data) {
|
||||
const AES192_ctx* ctx = (const AES192_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES192_decrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES256_init(void* data) {
|
||||
AES256_ctx* ctx = (AES256_ctx*)data;
|
||||
int i;
|
||||
for (i = 0; i < 50000; i++) {
|
||||
AES256_init(ctx, (unsigned char*)ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void bench_AES256_encrypt_setup(void* data) {
|
||||
AES256_ctx* ctx = (AES256_ctx*)data;
|
||||
static const unsigned char key[16] = {0};
|
||||
AES256_init(ctx, key);
|
||||
}
|
||||
|
||||
static void bench_AES256_encrypt(void* data) {
|
||||
const AES256_ctx* ctx = (const AES256_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES256_encrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static void bench_AES256_decrypt(void* data) {
|
||||
const AES256_ctx* ctx = (const AES256_ctx*)data;
|
||||
unsigned char scratch[16] = {0};
|
||||
int i;
|
||||
for (i = 0; i < 4000000 / 16; i++) {
|
||||
AES256_decrypt(ctx, 1, scratch, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
AES128_ctx ctx128;
|
||||
AES192_ctx ctx192;
|
||||
AES256_ctx ctx256;
|
||||
run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000);
|
||||
run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
|
||||
run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
|
||||
run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000);
|
||||
run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
|
||||
run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
|
||||
run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000);
|
||||
run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
|
||||
run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
|
||||
return 0;
|
||||
}
|
||||
556
src/crypto/ctaes/ctaes.c
Normal file
556
src/crypto/ctaes/ctaes.c
Normal file
@@ -0,0 +1,556 @@
|
||||
/*********************************************************************
|
||||
* Copyright (c) 2016 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
/* Constant time, unoptimized, concise, plain C, AES implementation
|
||||
* Based On:
|
||||
* Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM
|
||||
* http://www.iacr.org/archive/ches2009/57470001/57470001.pdf
|
||||
* But using 8 16-bit integers representing a single AES state rather than 8 128-bit
|
||||
* integers representing 8 AES states.
|
||||
*/
|
||||
|
||||
#include "ctaes.h"
|
||||
|
||||
/* Slice variable slice_i contains the i'th bit of the 16 state variables in this order:
|
||||
* 0 1 2 3
|
||||
* 4 5 6 7
|
||||
* 8 9 10 11
|
||||
* 12 13 14 15
|
||||
*/
|
||||
|
||||
/** Convert a byte to sliced form, storing it corresponding to given row and column in s */
|
||||
static void LoadByte(AES_state* s, unsigned char byte, int r, int c) {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
s->slice[i] |= (byte & 1) << (r * 4 + c);
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Load 16 bytes of data into 8 sliced integers */
|
||||
static void LoadBytes(AES_state *s, const unsigned char* data16) {
|
||||
int c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
int r;
|
||||
for (r = 0; r < 4; r++) {
|
||||
LoadByte(s, *(data16++), r, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Convert 8 sliced integers into 16 bytes of data */
|
||||
static void SaveBytes(unsigned char* data16, const AES_state *s) {
|
||||
int c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
int r;
|
||||
for (r = 0; r < 4; r++) {
|
||||
int b;
|
||||
uint8_t v = 0;
|
||||
for (b = 0; b < 8; b++) {
|
||||
v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b;
|
||||
}
|
||||
*(data16++) = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* S-box implementation based on the gate logic from:
|
||||
* Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box.
|
||||
* https://eprint.iacr.org/2011/332.pdf
|
||||
*/
|
||||
static void SubBytes(AES_state *s, int inv) {
|
||||
/* Load the bit slices */
|
||||
uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4];
|
||||
uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0];
|
||||
|
||||
uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16;
|
||||
uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D;
|
||||
uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40;
|
||||
uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54;
|
||||
uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63;
|
||||
|
||||
if (inv) {
|
||||
uint16_t R5, R13, R17, R18, R19;
|
||||
/* Undo linear postprocessing */
|
||||
T23 = U0 ^ U3;
|
||||
T22 = ~(U1 ^ U3);
|
||||
T2 = ~(U0 ^ U1);
|
||||
T1 = U3 ^ U4;
|
||||
T24 = ~(U4 ^ U7);
|
||||
R5 = U6 ^ U7;
|
||||
T8 = ~(U1 ^ T23);
|
||||
T19 = T22 ^ R5;
|
||||
T9 = ~(U7 ^ T1);
|
||||
T10 = T2 ^ T24;
|
||||
T13 = T2 ^ R5;
|
||||
T3 = T1 ^ R5;
|
||||
T25 = ~(U2 ^ T1);
|
||||
R13 = U1 ^ U6;
|
||||
T17 = ~(U2 ^ T19);
|
||||
T20 = T24 ^ R13;
|
||||
T4 = U4 ^ T8;
|
||||
R17 = ~(U2 ^ U5);
|
||||
R18 = ~(U5 ^ U6);
|
||||
R19 = ~(U2 ^ U4);
|
||||
D = U0 ^ R17;
|
||||
T6 = T22 ^ R17;
|
||||
T16 = R13 ^ R19;
|
||||
T27 = T1 ^ R18;
|
||||
T15 = T10 ^ T27;
|
||||
T14 = T10 ^ R18;
|
||||
T26 = T3 ^ T16;
|
||||
} else {
|
||||
/* Linear preprocessing. */
|
||||
T1 = U0 ^ U3;
|
||||
T2 = U0 ^ U5;
|
||||
T3 = U0 ^ U6;
|
||||
T4 = U3 ^ U5;
|
||||
T5 = U4 ^ U6;
|
||||
T6 = T1 ^ T5;
|
||||
T7 = U1 ^ U2;
|
||||
T8 = U7 ^ T6;
|
||||
T9 = U7 ^ T7;
|
||||
T10 = T6 ^ T7;
|
||||
T11 = U1 ^ U5;
|
||||
T12 = U2 ^ U5;
|
||||
T13 = T3 ^ T4;
|
||||
T14 = T6 ^ T11;
|
||||
T15 = T5 ^ T11;
|
||||
T16 = T5 ^ T12;
|
||||
T17 = T9 ^ T16;
|
||||
T18 = U3 ^ U7;
|
||||
T19 = T7 ^ T18;
|
||||
T20 = T1 ^ T19;
|
||||
T21 = U6 ^ U7;
|
||||
T22 = T7 ^ T21;
|
||||
T23 = T2 ^ T22;
|
||||
T24 = T2 ^ T10;
|
||||
T25 = T20 ^ T17;
|
||||
T26 = T3 ^ T16;
|
||||
T27 = T1 ^ T12;
|
||||
D = U7;
|
||||
}
|
||||
|
||||
/* Non-linear transformation (shared between the forward and backward case) */
|
||||
M1 = T13 & T6;
|
||||
M6 = T3 & T16;
|
||||
M11 = T1 & T15;
|
||||
M13 = (T4 & T27) ^ M11;
|
||||
M15 = (T2 & T10) ^ M11;
|
||||
M20 = T14 ^ M1 ^ (T23 & T8) ^ M13;
|
||||
M21 = (T19 & D) ^ M1 ^ T24 ^ M15;
|
||||
M22 = T26 ^ M6 ^ (T22 & T9) ^ M13;
|
||||
M23 = (T20 & T17) ^ M6 ^ M15 ^ T25;
|
||||
M25 = M22 & M20;
|
||||
M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25));
|
||||
M38 = M20 ^ M25 ^ (M21 | (M20 & M23));
|
||||
M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25));
|
||||
M40 = M22 ^ M25 ^ (M23 | (M21 & M22));
|
||||
M41 = M38 ^ M40;
|
||||
M42 = M37 ^ M39;
|
||||
M43 = M37 ^ M38;
|
||||
M44 = M39 ^ M40;
|
||||
M45 = M42 ^ M41;
|
||||
M46 = M44 & T6;
|
||||
M47 = M40 & T8;
|
||||
M48 = M39 & D;
|
||||
M49 = M43 & T16;
|
||||
M50 = M38 & T9;
|
||||
M51 = M37 & T17;
|
||||
M52 = M42 & T15;
|
||||
M53 = M45 & T27;
|
||||
M54 = M41 & T10;
|
||||
M55 = M44 & T13;
|
||||
M56 = M40 & T23;
|
||||
M57 = M39 & T19;
|
||||
M58 = M43 & T3;
|
||||
M59 = M38 & T22;
|
||||
M60 = M37 & T20;
|
||||
M61 = M42 & T1;
|
||||
M62 = M45 & T4;
|
||||
M63 = M41 & T2;
|
||||
|
||||
if (inv){
|
||||
/* Undo linear preprocessing */
|
||||
uint16_t P0 = M52 ^ M61;
|
||||
uint16_t P1 = M58 ^ M59;
|
||||
uint16_t P2 = M54 ^ M62;
|
||||
uint16_t P3 = M47 ^ M50;
|
||||
uint16_t P4 = M48 ^ M56;
|
||||
uint16_t P5 = M46 ^ M51;
|
||||
uint16_t P6 = M49 ^ M60;
|
||||
uint16_t P7 = P0 ^ P1;
|
||||
uint16_t P8 = M50 ^ M53;
|
||||
uint16_t P9 = M55 ^ M63;
|
||||
uint16_t P10 = M57 ^ P4;
|
||||
uint16_t P11 = P0 ^ P3;
|
||||
uint16_t P12 = M46 ^ M48;
|
||||
uint16_t P13 = M49 ^ M51;
|
||||
uint16_t P14 = M49 ^ M62;
|
||||
uint16_t P15 = M54 ^ M59;
|
||||
uint16_t P16 = M57 ^ M61;
|
||||
uint16_t P17 = M58 ^ P2;
|
||||
uint16_t P18 = M63 ^ P5;
|
||||
uint16_t P19 = P2 ^ P3;
|
||||
uint16_t P20 = P4 ^ P6;
|
||||
uint16_t P22 = P2 ^ P7;
|
||||
uint16_t P23 = P7 ^ P8;
|
||||
uint16_t P24 = P5 ^ P7;
|
||||
uint16_t P25 = P6 ^ P10;
|
||||
uint16_t P26 = P9 ^ P11;
|
||||
uint16_t P27 = P10 ^ P18;
|
||||
uint16_t P28 = P11 ^ P25;
|
||||
uint16_t P29 = P15 ^ P20;
|
||||
s->slice[7] = P13 ^ P22;
|
||||
s->slice[6] = P26 ^ P29;
|
||||
s->slice[5] = P17 ^ P28;
|
||||
s->slice[4] = P12 ^ P22;
|
||||
s->slice[3] = P23 ^ P27;
|
||||
s->slice[2] = P19 ^ P24;
|
||||
s->slice[1] = P14 ^ P23;
|
||||
s->slice[0] = P9 ^ P16;
|
||||
} else {
|
||||
/* Linear postprocessing */
|
||||
uint16_t L0 = M61 ^ M62;
|
||||
uint16_t L1 = M50 ^ M56;
|
||||
uint16_t L2 = M46 ^ M48;
|
||||
uint16_t L3 = M47 ^ M55;
|
||||
uint16_t L4 = M54 ^ M58;
|
||||
uint16_t L5 = M49 ^ M61;
|
||||
uint16_t L6 = M62 ^ L5;
|
||||
uint16_t L7 = M46 ^ L3;
|
||||
uint16_t L8 = M51 ^ M59;
|
||||
uint16_t L9 = M52 ^ M53;
|
||||
uint16_t L10 = M53 ^ L4;
|
||||
uint16_t L11 = M60 ^ L2;
|
||||
uint16_t L12 = M48 ^ M51;
|
||||
uint16_t L13 = M50 ^ L0;
|
||||
uint16_t L14 = M52 ^ M61;
|
||||
uint16_t L15 = M55 ^ L1;
|
||||
uint16_t L16 = M56 ^ L0;
|
||||
uint16_t L17 = M57 ^ L1;
|
||||
uint16_t L18 = M58 ^ L8;
|
||||
uint16_t L19 = M63 ^ L4;
|
||||
uint16_t L20 = L0 ^ L1;
|
||||
uint16_t L21 = L1 ^ L7;
|
||||
uint16_t L22 = L3 ^ L12;
|
||||
uint16_t L23 = L18 ^ L2;
|
||||
uint16_t L24 = L15 ^ L9;
|
||||
uint16_t L25 = L6 ^ L10;
|
||||
uint16_t L26 = L7 ^ L9;
|
||||
uint16_t L27 = L8 ^ L10;
|
||||
uint16_t L28 = L11 ^ L14;
|
||||
uint16_t L29 = L11 ^ L17;
|
||||
s->slice[7] = L6 ^ L24;
|
||||
s->slice[6] = ~(L16 ^ L26);
|
||||
s->slice[5] = ~(L19 ^ L28);
|
||||
s->slice[4] = L6 ^ L21;
|
||||
s->slice[3] = L20 ^ L22;
|
||||
s->slice[2] = L25 ^ L29;
|
||||
s->slice[1] = ~(L13 ^ L27);
|
||||
s->slice[0] = ~(L6 ^ L23);
|
||||
}
|
||||
}
|
||||
|
||||
#define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from))
|
||||
|
||||
#define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift))
|
||||
#define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift))
|
||||
|
||||
static void ShiftRows(AES_state* s) {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint16_t v = s->slice[i];
|
||||
s->slice[i] =
|
||||
(v & BIT_RANGE(0, 4)) |
|
||||
BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) |
|
||||
BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
|
||||
BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void InvShiftRows(AES_state* s) {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint16_t v = s->slice[i];
|
||||
s->slice[i] =
|
||||
(v & BIT_RANGE(0, 4)) |
|
||||
BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) |
|
||||
BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
|
||||
BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4)))
|
||||
|
||||
static void MixColumns(AES_state* s, int inv) {
|
||||
/* The MixColumns transform treats the bytes of the columns of the state as
|
||||
* coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them
|
||||
* by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo
|
||||
* x^4 + {01}.
|
||||
*
|
||||
* In the inverse transform, we multiply by the inverse of a(x),
|
||||
* a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to
|
||||
* a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code
|
||||
* (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna)
|
||||
*
|
||||
* In the bitsliced representation, a multiplication of every column by x
|
||||
* mod x^4 + 1 is simply a right rotation.
|
||||
*/
|
||||
|
||||
/* Shared for both directions is a multiplication by a(x), which can be
|
||||
* rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}).
|
||||
*
|
||||
* First compute s into the s? variables, (x^3 + {01}) * s into the s?_01
|
||||
* variables and (x^3 + x^2 + x)*s into the s?_123 variables.
|
||||
*/
|
||||
uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3];
|
||||
uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7];
|
||||
uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3);
|
||||
uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3);
|
||||
uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3);
|
||||
uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3);
|
||||
uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3);
|
||||
uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3);
|
||||
uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3);
|
||||
uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3);
|
||||
/* Now compute s = s?_123 + {02} * s?_01. */
|
||||
s->slice[0] = s7_01 ^ s0_123;
|
||||
s->slice[1] = s7_01 ^ s0_01 ^ s1_123;
|
||||
s->slice[2] = s1_01 ^ s2_123;
|
||||
s->slice[3] = s7_01 ^ s2_01 ^ s3_123;
|
||||
s->slice[4] = s7_01 ^ s3_01 ^ s4_123;
|
||||
s->slice[5] = s4_01 ^ s5_123;
|
||||
s->slice[6] = s5_01 ^ s6_123;
|
||||
s->slice[7] = s6_01 ^ s7_123;
|
||||
if (inv) {
|
||||
/* In the reverse direction, we further need to multiply by
|
||||
* {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}.
|
||||
*
|
||||
* First compute (x^2 + {01}) * s into the t?_02 variables: */
|
||||
uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2);
|
||||
uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2);
|
||||
uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2);
|
||||
uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2);
|
||||
uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2);
|
||||
uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2);
|
||||
uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2);
|
||||
uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2);
|
||||
/* And then update s += {04} * t?_02 */
|
||||
s->slice[0] ^= t6_02;
|
||||
s->slice[1] ^= t6_02 ^ t7_02;
|
||||
s->slice[2] ^= t0_02 ^ t7_02;
|
||||
s->slice[3] ^= t1_02 ^ t6_02;
|
||||
s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02;
|
||||
s->slice[5] ^= t3_02 ^ t7_02;
|
||||
s->slice[6] ^= t4_02;
|
||||
s->slice[7] ^= t5_02;
|
||||
}
|
||||
}
|
||||
|
||||
static void AddRoundKey(AES_state* s, const AES_state* round) {
|
||||
int b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
s->slice[b] ^= round->slice[b];
|
||||
}
|
||||
}
|
||||
|
||||
/** column_0(s) = column_c(a) */
|
||||
static void GetOneColumn(AES_state* s, const AES_state* a, int c) {
|
||||
int b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
s->slice[b] = (a->slice[b] >> c) & 0x1111;
|
||||
}
|
||||
}
|
||||
|
||||
/** column_c1(r) |= (column_0(s) ^= column_c2(a)) */
|
||||
static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) {
|
||||
int b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Rotate the rows in s one position upwards, and xor in r */
|
||||
static void KeySetupTransform(AES_state* s, const AES_state* r) {
|
||||
int b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b];
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */
|
||||
static void MultX(AES_state* s) {
|
||||
uint16_t top = s->slice[7];
|
||||
s->slice[7] = s->slice[6];
|
||||
s->slice[6] = s->slice[5];
|
||||
s->slice[5] = s->slice[4];
|
||||
s->slice[4] = s->slice[3] ^ top;
|
||||
s->slice[3] = s->slice[2] ^ top;
|
||||
s->slice[2] = s->slice[1];
|
||||
s->slice[1] = s->slice[0] ^ top;
|
||||
s->slice[0] = top;
|
||||
}
|
||||
|
||||
/** Expand the cipher key into the key schedule.
|
||||
*
|
||||
* state must be a pointer to an array of size nrounds + 1.
|
||||
* key must be a pointer to 4 * nkeywords bytes.
|
||||
*
|
||||
* AES128 uses nkeywords = 4, nrounds = 10
|
||||
* AES192 uses nkeywords = 6, nrounds = 12
|
||||
* AES256 uses nkeywords = 8, nrounds = 14
|
||||
*/
|
||||
static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* The one-byte round constant */
|
||||
AES_state rcon = {{1,0,0,0,0,0,0,0}};
|
||||
/* The number of the word being generated, modulo nkeywords */
|
||||
int pos = 0;
|
||||
/* The column representing the word currently being processed */
|
||||
AES_state column;
|
||||
|
||||
for (i = 0; i < nrounds + 1; i++) {
|
||||
int b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
rounds[i].slice[b] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* The first nkeywords round columns are just taken from the key directly. */
|
||||
for (i = 0; i < nkeywords; i++) {
|
||||
int r;
|
||||
for (r = 0; r < 4; r++) {
|
||||
LoadByte(&rounds[i >> 2], *(key++), r, i & 3);
|
||||
}
|
||||
}
|
||||
|
||||
GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3);
|
||||
|
||||
for (i = nkeywords; i < 4 * (nrounds + 1); i++) {
|
||||
/* Transform column */
|
||||
if (pos == 0) {
|
||||
SubBytes(&column, 0);
|
||||
KeySetupTransform(&column, &rcon);
|
||||
MultX(&rcon);
|
||||
} else if (nkeywords > 6 && pos == 4) {
|
||||
SubBytes(&column, 0);
|
||||
}
|
||||
if (++pos == nkeywords) pos = 0;
|
||||
KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) {
|
||||
AES_state s = {{0}};
|
||||
int round;
|
||||
|
||||
LoadBytes(&s, plain16);
|
||||
AddRoundKey(&s, rounds++);
|
||||
|
||||
for (round = 1; round < nrounds; round++) {
|
||||
SubBytes(&s, 0);
|
||||
ShiftRows(&s);
|
||||
MixColumns(&s, 0);
|
||||
AddRoundKey(&s, rounds++);
|
||||
}
|
||||
|
||||
SubBytes(&s, 0);
|
||||
ShiftRows(&s);
|
||||
AddRoundKey(&s, rounds);
|
||||
|
||||
SaveBytes(cipher16, &s);
|
||||
}
|
||||
|
||||
static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) {
|
||||
/* Most AES decryption implementations use the alternate scheme
|
||||
* (the Equivalent Inverse Cipher), which allows for more code reuse between
|
||||
* the encryption and decryption code, but requires separate setup for both.
|
||||
*/
|
||||
AES_state s = {{0}};
|
||||
int round;
|
||||
|
||||
rounds += nrounds;
|
||||
|
||||
LoadBytes(&s, cipher16);
|
||||
AddRoundKey(&s, rounds--);
|
||||
|
||||
for (round = 1; round < nrounds; round++) {
|
||||
InvShiftRows(&s);
|
||||
SubBytes(&s, 1);
|
||||
AddRoundKey(&s, rounds--);
|
||||
MixColumns(&s, 1);
|
||||
}
|
||||
|
||||
InvShiftRows(&s);
|
||||
SubBytes(&s, 1);
|
||||
AddRoundKey(&s, rounds);
|
||||
|
||||
SaveBytes(plain16, &s);
|
||||
}
|
||||
|
||||
void AES128_init(AES128_ctx* ctx, const unsigned char* key16) {
|
||||
AES_setup(ctx->rk, key16, 4, 10);
|
||||
}
|
||||
|
||||
void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
|
||||
while (blocks--) {
|
||||
AES_encrypt(ctx->rk, 10, cipher16, plain16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
|
||||
while (blocks--) {
|
||||
AES_decrypt(ctx->rk, 10, plain16, cipher16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void AES192_init(AES192_ctx* ctx, const unsigned char* key24) {
|
||||
AES_setup(ctx->rk, key24, 6, 12);
|
||||
}
|
||||
|
||||
void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
|
||||
while (blocks--) {
|
||||
AES_encrypt(ctx->rk, 12, cipher16, plain16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
|
||||
while (blocks--) {
|
||||
AES_decrypt(ctx->rk, 12, plain16, cipher16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void AES256_init(AES256_ctx* ctx, const unsigned char* key32) {
|
||||
AES_setup(ctx->rk, key32, 8, 14);
|
||||
}
|
||||
|
||||
void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
|
||||
while (blocks--) {
|
||||
AES_encrypt(ctx->rk, 14, cipher16, plain16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
|
||||
while (blocks--) {
|
||||
AES_decrypt(ctx->rk, 14, plain16, cipher16);
|
||||
cipher16 += 16;
|
||||
plain16 += 16;
|
||||
}
|
||||
}
|
||||
41
src/crypto/ctaes/ctaes.h
Normal file
41
src/crypto/ctaes/ctaes.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*********************************************************************
|
||||
* Copyright (c) 2016 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _CTAES_H_
|
||||
#define _CTAES_H_ 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t slice[8];
|
||||
} AES_state;
|
||||
|
||||
typedef struct {
|
||||
AES_state rk[11];
|
||||
} AES128_ctx;
|
||||
|
||||
typedef struct {
|
||||
AES_state rk[13];
|
||||
} AES192_ctx;
|
||||
|
||||
typedef struct {
|
||||
AES_state rk[15];
|
||||
} AES256_ctx;
|
||||
|
||||
void AES128_init(AES128_ctx* ctx, const unsigned char* key16);
|
||||
void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
|
||||
void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
|
||||
|
||||
void AES192_init(AES192_ctx* ctx, const unsigned char* key24);
|
||||
void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
|
||||
void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
|
||||
|
||||
void AES256_init(AES256_ctx* ctx, const unsigned char* key32);
|
||||
void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
|
||||
void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
|
||||
|
||||
#endif
|
||||
110
src/crypto/ctaes/test.c
Normal file
110
src/crypto/ctaes/test.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*********************************************************************
|
||||
* Copyright (c) 2016 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include "ctaes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct {
|
||||
int keysize;
|
||||
const char* key;
|
||||
const char* plain;
|
||||
const char* cipher;
|
||||
} ctaes_test;
|
||||
|
||||
static const ctaes_test ctaes_tests[] = {
|
||||
/* AES test vectors from FIPS 197. */
|
||||
{128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"},
|
||||
{192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"},
|
||||
{256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"},
|
||||
|
||||
/* AES-ECB test vectors from NIST sp800-38a. */
|
||||
{128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"},
|
||||
{128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"},
|
||||
{128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"},
|
||||
{128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"},
|
||||
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"},
|
||||
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"},
|
||||
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"},
|
||||
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"},
|
||||
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"},
|
||||
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"},
|
||||
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"},
|
||||
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"}
|
||||
};
|
||||
|
||||
static void from_hex(unsigned char* data, int len, const char* hex) {
|
||||
int p;
|
||||
for (p = 0; p < len; p++) {
|
||||
int v = 0;
|
||||
int n;
|
||||
for (n = 0; n < 2; n++) {
|
||||
assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f'));
|
||||
if (*hex >= '0' && *hex <= '9') {
|
||||
v |= (*hex - '0') << (4 * (1 - n));
|
||||
} else {
|
||||
v |= (*hex - 'a' + 10) << (4 * (1 - n));
|
||||
}
|
||||
hex++;
|
||||
}
|
||||
*(data++) = v;
|
||||
}
|
||||
assert(*hex == 0);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int i;
|
||||
int fail = 0;
|
||||
for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) {
|
||||
unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16];
|
||||
const ctaes_test* test = &ctaes_tests[i];
|
||||
assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256);
|
||||
from_hex(plain, 16, test->plain);
|
||||
from_hex(cipher, 16, test->cipher);
|
||||
switch (test->keysize) {
|
||||
case 128: {
|
||||
AES128_ctx ctx;
|
||||
from_hex(key, 16, test->key);
|
||||
AES128_init(&ctx, key);
|
||||
AES128_encrypt(&ctx, 1, ciphered, plain);
|
||||
AES128_decrypt(&ctx, 1, deciphered, cipher);
|
||||
break;
|
||||
}
|
||||
case 192: {
|
||||
AES192_ctx ctx;
|
||||
from_hex(key, 24, test->key);
|
||||
AES192_init(&ctx, key);
|
||||
AES192_encrypt(&ctx, 1, ciphered, plain);
|
||||
AES192_decrypt(&ctx, 1, deciphered, cipher);
|
||||
break;
|
||||
}
|
||||
case 256: {
|
||||
AES256_ctx ctx;
|
||||
from_hex(key, 32, test->key);
|
||||
AES256_init(&ctx, key);
|
||||
AES256_encrypt(&ctx, 1, ciphered, plain);
|
||||
AES256_decrypt(&ctx, 1, deciphered, cipher);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (memcmp(cipher, ciphered, 16)) {
|
||||
fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher);
|
||||
fail++;
|
||||
}
|
||||
if (memcmp(plain, deciphered, 16)) {
|
||||
fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
if (fail == 0) {
|
||||
fprintf(stderr, "All tests successful\n");
|
||||
} else {
|
||||
fprintf(stderr, "%i tests failed\n", fail);
|
||||
}
|
||||
return (fail != 0);
|
||||
}
|
||||
33
src/hushd
33
src/hushd
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2019 Hush developers
|
||||
# Copyright (c) 2019-2020 Hush developers
|
||||
|
||||
# set working directory to the location of this script
|
||||
# readlink -f does not always exist
|
||||
@@ -8,31 +8,41 @@ cd $DIR
|
||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
||||
cd $DIR
|
||||
|
||||
# Chain parameters
|
||||
NAME=HUSH3
|
||||
|
||||
# this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn
|
||||
SCRIPT=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac
|
||||
|
||||
# Chain parameters
|
||||
# First Pure Sapling Zcash Protocol chain!
|
||||
SAPLING=1
|
||||
|
||||
# We use 3 "eras" of different supply curves
|
||||
ERAS=3
|
||||
BLOCKTIME=150
|
||||
# 6250000 - (sprout pool at block 500,000)
|
||||
|
||||
# These values are historical and over-ridden by internals!
|
||||
# Do not change these values, change internals.
|
||||
BLOCKTIME=150 # Hush goes to 75s blocktime at Block 340K
|
||||
REWARD=0,1125000000,562500000
|
||||
HALVING=129,340000,840000
|
||||
PERC=11111111
|
||||
END=128,340000,5422111
|
||||
|
||||
# 6250000 - (Sprout pool at block 500,000)
|
||||
SUPPLY=6178674
|
||||
FOUNDERS=1
|
||||
REWARD=0,1125000000,562500000
|
||||
PERC=11111111
|
||||
HALVING=129,340000,840000
|
||||
# NOTE: keep in sync with komodo_bitcoind.h
|
||||
END=128,340000,5422111
|
||||
CLIENTNAME=GoldenSandtrout
|
||||
NODE1=188.165.212.101 # EU
|
||||
NODE2=64.120.113.130 # AR
|
||||
NODE3=209.58.144.205 # NA
|
||||
NODE4=94.130.35.94 # EU
|
||||
CCLIB=hush3
|
||||
# First Pure Sapling Zcash Protocol chain!
|
||||
SAPLING=1
|
||||
|
||||
# CryptoConditions/Custom Consensus params
|
||||
# CCs will effectively be turned off at Block 340K
|
||||
# since transparent outputs will not be allowed, except
|
||||
# for mining and dpow. CCs can be used on Hush Smart
|
||||
# Chains that do not define ac_private=1
|
||||
FAUCET=228
|
||||
HEIR=234
|
||||
CHANNEL=235
|
||||
@@ -53,7 +63,6 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
$KMD -ac_name=$NAME \
|
||||
-ac_sapling=$SAPLING \
|
||||
-ac_reward=$REWARD \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2019 Hush developers
|
||||
# Copyright (c) 2019-2020 Hush developers
|
||||
|
||||
# set working directory to the location of this script
|
||||
DIR="$( cd "$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" && pwd )"
|
||||
|
||||
13
src/init.cpp
13
src/init.cpp
@@ -392,6 +392,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"));
|
||||
#endif
|
||||
strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0));
|
||||
strUsage += HelpMessageOpt("-txsend=<cmd>", _("Execute command to send a transaction instead of broadcasting (%s in cmd is replaced by transaction hex)"));
|
||||
strUsage += HelpMessageOpt("-addressindex", strprintf(_("Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses (default: %u)"), DEFAULT_ADDRESSINDEX));
|
||||
strUsage += HelpMessageOpt("-timestampindex", strprintf(_("Maintain a timestamp index for block hashes, used to query blocks hashes by a range of timestamps (default: %u)"), DEFAULT_TIMESTAMPINDEX));
|
||||
strUsage += HelpMessageOpt("-spentindex", strprintf(_("Maintain a full spent index, used to query the spending txid and input index for an outpoint (default: %u)"), DEFAULT_SPENTINDEX));
|
||||
@@ -454,7 +455,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"),
|
||||
CURRENCY_UNIT, FormatMoney(maxTxFee)));
|
||||
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
|
||||
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
|
||||
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file absolute path or a path relative to the data directory") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
|
||||
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true));
|
||||
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
|
||||
strUsage += HelpMessageOpt("-whitelistaddress=<Raddress>", _("Enable the wallet filter for notary nodes and add one Raddress to the whitelist of the wallet filter. If -whitelistaddress= is used, then the wallet filter is automatically activated. Several Raddresses can be defined using several -whitelistaddress= (similar to -addnode). The wallet filter will filter the utxo to only ones coming from my own Raddress (derived from pubkey) and each Raddress defined using -whitelistaddress= this option is mostly for Notary Nodes)."));
|
||||
@@ -1118,6 +1119,16 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mapArgs.count("-txsend")) {
|
||||
if (GetBoolArg("-walletbroadcast", true)) {
|
||||
if (SoftSetBoolArg("-walletbroadcast", false)) {
|
||||
LogPrintf("%s: parameter interaction: -txsend=<cmd> -> setting -walletbroadcast=0\n", __func__);
|
||||
} else {
|
||||
return InitError(_("Wallet transaction broadcasting is incompatible with -txsend (for privacy)."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************* Step 3: parameter-to-internal-flags
|
||||
|
||||
fZdebug=GetBoolArg("-zdebug", false);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -23,8 +24,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
//#include "zcash/JoinSplit.hpp"
|
||||
|
||||
class CScheduler;
|
||||
class CWallet;
|
||||
|
||||
@@ -34,7 +33,6 @@ class thread_group;
|
||||
} // namespace boost
|
||||
|
||||
extern CWallet* pwalletMain;
|
||||
//extern ZCJoinSplit* pzcashParams;
|
||||
|
||||
void StartShutdown();
|
||||
bool ShutdownRequested();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
// komodo functions that interact with bitcoind C++
|
||||
// Hush + Komodo functions that interact with bitcoind C++
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include "consensus/params.h"
|
||||
//#include "primitives/nonce.h"
|
||||
#include "komodo_defs.h"
|
||||
#include "script/standard.h"
|
||||
#include "cc/CCinclude.h"
|
||||
@@ -1234,69 +1233,116 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
|
||||
|
||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
|
||||
|
||||
// This function defines the Hush Founders Reward (AKA Dev Tax)
|
||||
// 10% of all block rewards go towards Hush core team
|
||||
// If you do not like this, you are encouraged to fork the chain
|
||||
// or start your own Hush Smart Chain: https://github.com/myhush/hush-smart-chains
|
||||
// HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves.
|
||||
// You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25
|
||||
// but to tell the AC params, I need to say "11% of 11.25" is 1.25
|
||||
// 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually
|
||||
// Do not change this code unless you really know what you are doing.
|
||||
// Here Be Dragons! -- Duke Leto
|
||||
uint64_t hush_commission(int height)
|
||||
{
|
||||
// BR_END is the 31st halving
|
||||
int32_t starting_commission = 125000000, HALVING1 = GetArg("-z2zheight",340000),
|
||||
INTERVAL = GetArg("-ac_halving1",840000), TRANSITION = 129, BR_END = 50740000;
|
||||
int32_t commisions[] = {starting_commission, 31250000, 15625000, 78125000, 39062500, 19531250, 9765625, // these are exact
|
||||
4882812, 2441406, 1220703, 610351 // these have deviation from ideal BR
|
||||
// Just like BTC, BRs in the far future will be slightly less than
|
||||
// they should be because exact values are not integers, causing
|
||||
// slightly less coins to be actually mined
|
||||
};
|
||||
uint64_t commission = 0;
|
||||
|
||||
//TODO: Likely a bug hiding here or at the next halving :)
|
||||
//if( height >= HALVING1) {
|
||||
if( height > HALVING1) {
|
||||
// Block time going from 150s to 75s (half) means the interval between halvings
|
||||
// must be twice as often, i.e. 840000*2=1680000
|
||||
// 840000 is 4 years worth of 150s blocks
|
||||
// With 150s blocks, we have 210,000 blocks per year
|
||||
// With 75s blocks, we have 420,000 blocks per year
|
||||
INTERVAL = GetArg("-ac_halving2",1680000); // 4 years worth of 75s blocks
|
||||
fprintf(stderr,"%s: height=%d increasing interval to %d\n", __func__, height, INTERVAL);
|
||||
}
|
||||
|
||||
// Transition period of 128 blocks has BR=FR=0
|
||||
if (height < TRANSITION) {
|
||||
commission = 0;
|
||||
} else if (height < HALVING1) { // before 1st Halving @ Block 340000 (Nov 2020)
|
||||
commission = commisions[0];
|
||||
} else if (height < HALVING1+1*INTERVAL) { // before 2nd Halving @ Block 2020000
|
||||
commission = commisions[1];
|
||||
} else if (height < HALVING1+2*INTERVAL) { // before 3rd Halving @ Block 3700000
|
||||
commission = commisions[2];
|
||||
} else if (height < HALVING1+3*INTERVAL) { // before 4th Halving @ Block 5380000
|
||||
commission = commisions[3];
|
||||
} else if (height < HALVING1+4*INTERVAL) { // before 5th Halving @ Block 7060000
|
||||
commission = commisions[4];
|
||||
} else if (height < HALVING1+5*INTERVAL) { // before 6th Halving @ Block 8740000
|
||||
commission = commisions[5];
|
||||
} else if (height < HALVING1+6*INTERVAL) { // before 7th Halving @ Block 10420000
|
||||
commission = commisions[6];
|
||||
} else if (height < HALVING1+7*INTERVAL) { // before 8th Halving @ Block 12100000
|
||||
// TODO: Still true??? Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting
|
||||
commission = commisions[7];
|
||||
} else if (height < HALVING1+8*INTERVAL) { // before 9th Halving @ Block 13780000
|
||||
// BR should be zero before this halving happens
|
||||
commission = commisions[8];
|
||||
}
|
||||
// Explicitly set the last block reward
|
||||
// BR_END is the block with first zero block reward, which overrides
|
||||
// the -ac_end param on HUSH3
|
||||
if(height >= BR_END) {
|
||||
fprintf(stderr,"%s: HUSH block reward has gone to zero at height %d!!! It was a good run folks\n", __func__, height);
|
||||
commission = 0;
|
||||
}
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: commission=%lu,interval=%d at height %d\n", __func__, commission, INTERVAL, height);
|
||||
return commission;
|
||||
}
|
||||
|
||||
uint64_t komodo_commission(const CBlock *pblock,int32_t height)
|
||||
{
|
||||
static bool didinit = false,ishush3 = false;
|
||||
// LABS fungible chains, cannot have any block reward!
|
||||
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
|
||||
return(0);
|
||||
//fprintf(stderr,"%s at height=%d\n",__func__,height);
|
||||
static bool didinit = false, ishush3 = false;
|
||||
|
||||
if (!didinit) {
|
||||
ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||
didinit = true;
|
||||
fprintf(stderr,"%s: didinit ishush3=%d\n", __func__, ishush3);
|
||||
}
|
||||
|
||||
int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0;
|
||||
if ( ASSETCHAINS_FOUNDERS != 0 )
|
||||
{
|
||||
nSubsidy = GetBlockSubsidy(height,Params().GetConsensus());
|
||||
//fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION));
|
||||
if(fDebug)
|
||||
fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION));
|
||||
commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN);
|
||||
|
||||
if (ishush3) {
|
||||
int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111;
|
||||
// HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves.
|
||||
// You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25
|
||||
// but to tell the AC params, I need to say "11% of 11.25" is 1.25
|
||||
// 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually
|
||||
// Transition period of 128 blocks has BR=FR=0
|
||||
if (height < TRANSITION) {
|
||||
commission = 0;
|
||||
} else if (height < HALVING1) {
|
||||
commission = starting_commission;
|
||||
} else if (height < HALVING1+1*INTERVAL) {
|
||||
commission = starting_commission / 2;
|
||||
} else if (height < HALVING1+2*INTERVAL) {
|
||||
commission = starting_commission / 4;
|
||||
} else if (height < HALVING1+3*INTERVAL) {
|
||||
commission = starting_commission / 8;
|
||||
} else if (height < HALVING1+4*INTERVAL) {
|
||||
commission = starting_commission / 16;
|
||||
} else if (height < HALVING1+5*INTERVAL) {
|
||||
commission = starting_commission / 32;
|
||||
} else if (height < HALVING1+6*INTERVAL) { // Block 5380000
|
||||
// Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting
|
||||
commission = starting_commission / 64;
|
||||
} else if (height < HALVING1+7*INTERVAL) {
|
||||
// Block reward will be zero before this is ever reached
|
||||
commission = starting_commission / 128; // Block 6220000
|
||||
}
|
||||
commission = hush_commission(height);
|
||||
}
|
||||
|
||||
if ( ASSETCHAINS_FOUNDERS > 1 )
|
||||
{
|
||||
if ( (height % ASSETCHAINS_FOUNDERS) == 0 )
|
||||
{
|
||||
if ( ASSETCHAINS_FOUNDERS_REWARD == 0 )
|
||||
if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) {
|
||||
commission = commission * ASSETCHAINS_FOUNDERS;
|
||||
else
|
||||
} else {
|
||||
commission = ASSETCHAINS_FOUNDERS_REWARD;
|
||||
}
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: set commission=%lu at height %d with\n",__func__,commission, height);
|
||||
} else {
|
||||
commission = 0;
|
||||
}
|
||||
else commission = 0;
|
||||
}
|
||||
}
|
||||
else if ( pblock != 0 )
|
||||
{
|
||||
} else if ( pblock != 0 ) {
|
||||
txn_count = pblock->vtx.size();
|
||||
for (i=0; i<txn_count; i++)
|
||||
{
|
||||
@@ -1320,7 +1366,8 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
|
||||
}
|
||||
if ( commission < 10000 )
|
||||
commission = 0;
|
||||
//fprintf(stderr,"-> %.8f\n",(double)commission/COIN);
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: commission=%.8f at height=%d\n",__func__, (double)commission/COIN, height);
|
||||
return(commission);
|
||||
}
|
||||
|
||||
@@ -1968,20 +2015,22 @@ void GetKomodoEarlytxidScriptPub()
|
||||
|
||||
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
|
||||
{
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s at height=%d\n",__func__,height);
|
||||
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
|
||||
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
|
||||
{
|
||||
checktoshis = komodo_commission(pblock,height);
|
||||
if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 )
|
||||
{
|
||||
//fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN);
|
||||
fprintf(stderr,"ERROR: komodo_checkcommission vsize.%d height.%d commission %.8f has checktoshis <10000 or not enough vouts\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN);
|
||||
return(-1);
|
||||
}
|
||||
else if ( checktoshis != 0 )
|
||||
{
|
||||
script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0];
|
||||
scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size();
|
||||
if ( 0 )
|
||||
if ( fDebug )
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; i<scriptlen; i++)
|
||||
@@ -2021,11 +2070,13 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
|
||||
}
|
||||
if ( pblock->vtx[0].vout[1].nValue != checktoshis )
|
||||
{
|
||||
fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
|
||||
fprintf(stderr,"ERROR: ht.%d checktoshis %.8f vs actual vout[1] %.8f !!!\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s checktoshis=%li at height=%d\n",__func__,checktoshis, height);
|
||||
return(checktoshis);
|
||||
}
|
||||
|
||||
|
||||
@@ -1534,24 +1534,48 @@ char *argv0names[] =
|
||||
(char *)"MNZ", (char *)"MNZ", (char *)"MNZ", (char *)"MNZ", (char *)"BTCH", (char *)"BTCH", (char *)"BTCH", (char *)"BTCH"
|
||||
};
|
||||
|
||||
|
||||
// Large total supplies lead to numerical errors, beware!
|
||||
uint64_t komodo_max_money()
|
||||
{
|
||||
return komodo_current_supply(10000000);
|
||||
}
|
||||
|
||||
|
||||
// This implements the Hush Emission Curve
|
||||
uint64_t hush_block_subsidy(int nHeight)
|
||||
{
|
||||
uint64_t subsidy=0;
|
||||
//TODO: Cover all halvings until BR=0
|
||||
//if (nHeight >= 3700000) {
|
||||
// subsidy = ASSETCHAINS_REWARD[4];
|
||||
//} else
|
||||
if (nHeight >= 2020000) {
|
||||
subsidy = 140625000;
|
||||
} else if (nHeight >= GetArg("-z2zheight",340000)) {
|
||||
subsidy = 281250000;
|
||||
} else if (nHeight >= 128) {
|
||||
subsidy = 1125000000;
|
||||
}
|
||||
return subsidy;
|
||||
}
|
||||
|
||||
// wrapper for more general supply curves of Hush Smart Chains
|
||||
uint64_t komodo_ac_block_subsidy(int nHeight)
|
||||
{
|
||||
// we have to find our era, start from beginning reward, and determine current subsidy
|
||||
//fprintf(stderr,"%s: ht.%d\n", __func__, nHeight);
|
||||
// Find current era, start from beginning reward, and determine current subsidy
|
||||
int64_t numerator, denominator, subsidy = 0;
|
||||
int64_t subsidyDifference;
|
||||
int32_t numhalvings, curEra = 0, sign = 1;
|
||||
int32_t numhalvings = 0, curEra = 0, sign = 1;
|
||||
static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era;
|
||||
bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||
|
||||
// check for backwards compat, older chains with no explicit rewards had 0.0001 block reward
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] == 0 )
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] == 0 ) {
|
||||
fprintf(stderr,"%s: defaulting to 0.0001 subsidy\n",__func__);
|
||||
subsidy = 10000;
|
||||
else if ( (ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] != 0) || ASSETCHAINS_ENDSUBSIDY[0] != 0 )
|
||||
{
|
||||
} else if ( (ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] != 0) || ASSETCHAINS_ENDSUBSIDY[0] != 0 ) {
|
||||
// if we have an end block in the first era, find our current era
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 )
|
||||
{
|
||||
@@ -1561,26 +1585,32 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( curEra <= ASSETCHAINS_LASTERA )
|
||||
{
|
||||
int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0;
|
||||
subsidy = (int64_t)ASSETCHAINS_REWARD[curEra];
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: nStart.%ld subsidy.%ld curEra.%d\n",__func__,nStart,subsidy,curEra);
|
||||
|
||||
if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) )
|
||||
{
|
||||
if ( ASSETCHAINS_HALVING[curEra] != 0 )
|
||||
{
|
||||
if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 )
|
||||
{
|
||||
if ( ASSETCHAINS_DECAY[curEra] == 0 )
|
||||
if (ishush3) {
|
||||
subsidy = hush_block_subsidy(nHeight);
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: HUSH3 subsidy=%ld at height=%d\n",__func__,subsidy,nHeight);
|
||||
} else if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) {
|
||||
// The code below is not compatible with HUSH3 mainnet
|
||||
if ( ASSETCHAINS_DECAY[curEra] == 0 ) {
|
||||
subsidy >>= numhalvings;
|
||||
else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 )
|
||||
{
|
||||
fprintf(stderr,"%s: no decay, numhalvings.%d curEra.%d subsidy.%ld nStart.%ld\n",__func__, numhalvings, curEra, subsidy, nStart);
|
||||
} else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) {
|
||||
if ( curEra == ASSETCHAINS_LASTERA )
|
||||
{
|
||||
subsidyDifference = subsidy;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0
|
||||
subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1];
|
||||
if (subsidyDifference < 0)
|
||||
@@ -1592,13 +1622,10 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
|
||||
denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart;
|
||||
numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra]));
|
||||
subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings )
|
||||
} else {
|
||||
if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) {
|
||||
subsidy = cached_subsidy;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
for (int i=0; i < numhalvings && subsidy != 0; i++)
|
||||
subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000;
|
||||
cached_subsidy = subsidy;
|
||||
@@ -1609,28 +1636,28 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,"%s: curEra.%d > lastEra.%lu\n", __func__, curEra, ASSETCHAINS_LASTERA);
|
||||
}
|
||||
}
|
||||
uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff);
|
||||
if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion?
|
||||
{
|
||||
fprintf(stderr,"%s: Detected supply over 10 billion, danger zone!\n",__func__);
|
||||
if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 )
|
||||
{
|
||||
subsidy += (uint64_t)1000000000 * COIN;
|
||||
if ( nHeight == 1 )
|
||||
subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra;
|
||||
}
|
||||
}
|
||||
else if ( nHeight == 1 )
|
||||
{
|
||||
} else if ( nHeight == 1 ) {
|
||||
if ( ASSETCHAINS_LASTERA == 0 )
|
||||
subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra;
|
||||
else
|
||||
subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra;
|
||||
}
|
||||
else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
|
||||
return(0);
|
||||
// LABS fungible chains, cannot have any block reward!
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: ht.%d curEra.%d lastEra.%lu subsidy.%ld magicExtra.%u\n",__func__,nHeight,curEra,ASSETCHAINS_LASTERA,subsidy,magicExtra);
|
||||
return(subsidy);
|
||||
}
|
||||
|
||||
@@ -1798,6 +1825,8 @@ void komodo_args(char *argv0)
|
||||
printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA);
|
||||
}
|
||||
ASSETCHAINS_LASTERA -= 1;
|
||||
if(fDebug)
|
||||
fprintf(stderr,"%s: lastEra=%lu maxEras=%d\n", __func__, ASSETCHAINS_LASTERA, ASSETCHAINS_MAX_ERAS);
|
||||
|
||||
ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF);
|
||||
ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0);
|
||||
@@ -1805,13 +1834,33 @@ void komodo_args(char *argv0)
|
||||
if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO )
|
||||
{
|
||||
printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n");
|
||||
ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
|
||||
ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
|
||||
ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0;
|
||||
}
|
||||
|
||||
Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0);
|
||||
Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0);
|
||||
Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0);
|
||||
Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0);
|
||||
|
||||
bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||
|
||||
if(ishush3) {
|
||||
fprintf(stderr,"%s: Setting custom HUSH3 reward,halving,subsidy chain values...\n",__func__);
|
||||
// Over-ride HUSH3 values from CLI params. Changing our blocktime to 75s changes things
|
||||
ASSETCHAINS_REWARD[0] = 0;
|
||||
ASSETCHAINS_REWARD[1] = 1125000000;
|
||||
ASSETCHAINS_REWARD[2] = 281250000; // 2.8125 HUSH goes to miners per block after 1st halving at Block 340K
|
||||
ASSETCHAINS_REWARD[3] = 140625000; // 1.40625 HUSH after 2nd halving at Block 2020000
|
||||
ASSETCHAINS_HALVING[0] = 129;
|
||||
ASSETCHAINS_HALVING[1] = GetArg("-z2zheight",340000);
|
||||
ASSETCHAINS_HALVING[2] = 2020000; // 2020000 = 340000 + 1680000 (1st halving block plus new halving interval)
|
||||
ASSETCHAINS_HALVING[3] = 3700000; // ASSETCHAINS_HALVING[2] + 1680000;
|
||||
ASSETCHAINS_ENDSUBSIDY[0] = 129;
|
||||
ASSETCHAINS_ENDSUBSIDY[1] = GetArg("-z2zheight",340000);
|
||||
ASSETCHAINS_ENDSUBSIDY[2] = 2*5422111; // TODO: Fix this, twice the previous end of rewards is an estimate
|
||||
// TODO: fill in all possible values for each halving/reward interval
|
||||
// based on simple halving schedule
|
||||
}
|
||||
Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0);
|
||||
Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0);
|
||||
|
||||
|
||||
47
src/main.cpp
47
src/main.cpp
@@ -1750,7 +1750,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
// and edge cases. This empty mempool assures there will be no transactions involving taddrs
|
||||
// stuck in the mempool, when the z2z rule takes effect.
|
||||
// Thanks to jl777 for helping design this
|
||||
fprintf(stderr,"%s: rejecting all tx's during z2z transition window at height=%d\n", __func__,nHeight);
|
||||
fprintf(stderr,"%s: rejecting all tx's during z2z transition window. Please retry after Block %d !!!\n", __func__,nHeight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2402,49 +2402,9 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW)
|
||||
return true;
|
||||
}
|
||||
|
||||
//uint64_t komodo_moneysupply(int32_t height);
|
||||
|
||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
|
||||
{
|
||||
int32_t numhalvings,i; uint64_t numerator; CAmount nSubsidy = 3 * COIN;
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 )
|
||||
{
|
||||
if ( nHeight == 1 )
|
||||
return(100000000 * COIN); // ICO allocation
|
||||
else if ( nHeight < KOMODO_ENDOFERA )
|
||||
return(3 * COIN);
|
||||
else if ( nHeight < 2*KOMODO_ENDOFERA )
|
||||
return(2 * COIN);
|
||||
else return(COIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(komodo_ac_block_subsidy(nHeight));
|
||||
}
|
||||
/*
|
||||
// Mining slow start
|
||||
// The subsidy is ramped up linearly, skipping the middle payout of
|
||||
// MAX_SUBSIDY/2 to keep the monetary curve consistent with no slow start.
|
||||
if (nHeight < consensusParams.nSubsidySlowStartInterval / 2) {
|
||||
nSubsidy /= consensusParams.nSubsidySlowStartInterval;
|
||||
nSubsidy *= nHeight;
|
||||
return nSubsidy;
|
||||
} else if (nHeight < consensusParams.nSubsidySlowStartInterval) {
|
||||
nSubsidy /= consensusParams.nSubsidySlowStartInterval;
|
||||
nSubsidy *= (nHeight+1);
|
||||
return nSubsidy;
|
||||
}
|
||||
|
||||
assert(nHeight > consensusParams.SubsidySlowStartShift());
|
||||
int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nSubsidyHalvingInterval;*/
|
||||
// Force block reward to zero when right shift is undefined.
|
||||
//int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
|
||||
//if (halvings >= 64)
|
||||
// return 0;
|
||||
|
||||
// Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years.
|
||||
//nSubsidy >>= halvings;
|
||||
//return nSubsidy;
|
||||
return komodo_ac_block_subsidy(nHeight);
|
||||
}
|
||||
|
||||
bool IsInitialBlockDownload()
|
||||
@@ -4829,9 +4789,10 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
||||
nShieldedOutputsInBlock += nShieldedOutputs;
|
||||
nShieldedSpendsInBlock += nShieldedSpends;
|
||||
if (fZdebug) {
|
||||
fprintf(stderr,"%s: tx=%s has zspends=%d zouts=%d\n", __FUNCTION__, tx.GetHash().ToString().c_str(), nShieldedSpendsInBlock, nShieldedOutputsInBlock );
|
||||
fprintf(stderr,"%s: tx=%s has zspends=%d zouts=%d\n", __FUNCTION__, tx.GetHash().ToString().c_str(), nShieldedSpends, nShieldedOutputs );
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"%s: block %s has total zspends=%d zouts=%d\n", __FUNCTION__, block.GetHash().ToString().c_str(), nShieldedSpendsInBlock, nShieldedOutputsInBlock );
|
||||
|
||||
pindexNew->nSproutValue = sproutValue;
|
||||
pindexNew->nChainSproutValue = boost::none;
|
||||
|
||||
@@ -610,7 +610,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
|
||||
int32_t stakeHeight = chainActive.Height() + 1;
|
||||
|
||||
//LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake);
|
||||
LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake);
|
||||
|
||||
// Create coinbase tx
|
||||
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
|
||||
@@ -621,7 +621,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
txNew.vout.resize(1);
|
||||
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
|
||||
txNew.vout[0].nValue = GetBlockSubsidy(nHeight,consensusParams) + nFees;
|
||||
//fprintf(stderr,"mine ht.%d with %.8f\n",nHeight,(double)txNew.vout[0].nValue/COIN);
|
||||
fprintf(stderr,"mine ht.%d with %.8f\n",nHeight,(double)txNew.vout[0].nValue/COIN);
|
||||
txNew.nExpiryHeight = 0;
|
||||
if ( ASSETCHAINS_ADAPTIVEPOW <= 0 )
|
||||
txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetTime());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
@@ -9,125 +9,30 @@ extern pthread_mutex_t staked_mutex;
|
||||
|
||||
int8_t is_STAKED(const char *chain_name)
|
||||
{
|
||||
static int8_t STAKED,doneinit;
|
||||
if ( chain_name[0] == 0 )
|
||||
return(0);
|
||||
if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0)
|
||||
return(STAKED);
|
||||
else STAKED = 0;
|
||||
if ( (strcmp(chain_name, "LABS") == 0) )
|
||||
STAKED = 1; // These chains are allowed coin emissions.
|
||||
else if ( (strncmp(chain_name, "LABS", 4) == 0) )
|
||||
STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed.
|
||||
else if ( (strcmp(chain_name, "CFEK") == 0) || (strncmp(chain_name, "CFEK", 4) == 0) )
|
||||
STAKED = 3; // These chains have no speical rules at all.
|
||||
else if ( (strcmp(chain_name, "TEST") == 0) || (strncmp(chain_name, "TEST", 4) == 0) )
|
||||
STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant to be actually used for anything important.
|
||||
else if ( (strcmp(chain_name, "THIS_CHAIN_IS_BANNED") == 0) )
|
||||
STAKED = 255; // Any chain added to this group is banned, no notarisations are valid, as a consensus rule. Can be used to remove a chain from cluster if needed.
|
||||
doneinit = 1;
|
||||
static int8_t STAKED=0;
|
||||
return(STAKED);
|
||||
};
|
||||
|
||||
int32_t STAKED_era(int timestamp)
|
||||
{
|
||||
int8_t era = 0;
|
||||
if (timestamp <= STAKED_NOTARIES_TIMESTAMP[0])
|
||||
return(1);
|
||||
for (int32_t i = 1; i < NUM_STAKED_ERAS; i++)
|
||||
{
|
||||
if (timestamp <= STAKED_NOTARIES_TIMESTAMP[i] && timestamp >= (STAKED_NOTARIES_TIMESTAMP[i-1] + STAKED_ERA_GAP))
|
||||
return(i+1);
|
||||
}
|
||||
// if we are in a gap, return era 0, this allows to invalidate notarizations when in GAP.
|
||||
return(0);
|
||||
};
|
||||
|
||||
int8_t StakedNotaryID(std::string ¬aryname, char *Raddress) {
|
||||
if ( STAKED_ERA != 0 )
|
||||
{
|
||||
for (int8_t i = 0; i < num_notaries_STAKED[STAKED_ERA-1]; i++) {
|
||||
if ( strcmp(Raddress,NOTARYADDRS[i]) == 0 ) {
|
||||
notaryname.assign(notaries_STAKED[STAKED_ERA-1][i][0]);
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) {
|
||||
int i; int8_t retval = 0;
|
||||
static uint8_t staked_pubkeys[NUM_STAKED_ERAS][64][33],didinit[NUM_STAKED_ERAS];
|
||||
static char ChainName[65];
|
||||
|
||||
if ( ChainName[0] == 0 )
|
||||
{
|
||||
if ( ASSETCHAINS_SYMBOL[0] == 0 )
|
||||
strcpy(ChainName,"KMD");
|
||||
else
|
||||
strcpy(ChainName,ASSETCHAINS_SYMBOL);
|
||||
}
|
||||
|
||||
if ( era == 0 )
|
||||
{
|
||||
// era is zero so we need to null out the pubkeys.
|
||||
memset(pubkeys,0,64 * 33);
|
||||
printf("%s is a STAKED chain and is in an ERA GAP.\n",ChainName);
|
||||
return(64);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( didinit[era-1] == 0 )
|
||||
{
|
||||
for (i=0; i<num_notaries_STAKED[era-1]; i++) {
|
||||
decode_hex(staked_pubkeys[era-1][i],33,(char *)notaries_STAKED[era-1][i][1]);
|
||||
}
|
||||
didinit[era-1] = 1;
|
||||
printf("%s is a STAKED chain in era %i \n",ChainName,era);
|
||||
}
|
||||
memcpy(pubkeys,staked_pubkeys[era-1],num_notaries_STAKED[era-1] * 33);
|
||||
retval = num_notaries_STAKED[era-1];
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) {
|
||||
static int didinit;
|
||||
if ( didinit == 0 ) {
|
||||
pthread_mutex_init(&staked_mutex,NULL);
|
||||
didinit = 1;
|
||||
}
|
||||
if ( pubkeys[0][0] == 0 )
|
||||
{
|
||||
// null pubkeys, era 0.
|
||||
pthread_mutex_lock(&staked_mutex);
|
||||
memset(NOTARYADDRS,0,sizeof(NOTARYADDRS));
|
||||
pthread_mutex_unlock(&staked_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// staked era is set.
|
||||
pthread_mutex_lock(&staked_mutex);
|
||||
for (int i = 0; i<numNotaries; i++)
|
||||
{
|
||||
pubkey2addr((char *)NOTARYADDRS[i],(uint8_t *)pubkeys[i]);
|
||||
if ( memcmp(NOTARY_PUBKEY33,pubkeys[i],33) == 0 )
|
||||
{
|
||||
NOTARY_ADDRESS.assign(NOTARYADDRS[i]);
|
||||
IS_STAKED_NOTARY = i;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&staked_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
CrosschainAuthority Choose_auth_STAKED(int32_t chosen_era) {
|
||||
CrosschainAuthority auth;
|
||||
auth.requiredSigs = (num_notaries_STAKED[chosen_era-1] / 5);
|
||||
auth.size = num_notaries_STAKED[chosen_era-1];
|
||||
for (int n=0; n<auth.size; n++)
|
||||
for (size_t i=0; i<33; i++)
|
||||
sscanf(notaries_STAKED[chosen_era-1][n][1]+(i*2), "%2hhx", auth.notaries[n]+i);
|
||||
return auth;
|
||||
};
|
||||
|
||||
@@ -169,11 +169,11 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "z_listsentbyaddress", 3},
|
||||
{ "z_listsentbyaddress", 4},
|
||||
{ "z_listsentbyaddress", 5},
|
||||
{ "z_listreceivedbyaddress", 1},
|
||||
{ "z_listreceivedbyaddress", 2},
|
||||
{ "z_listreceivedbyaddress", 3},
|
||||
{ "z_listreceivedbyaddress", 4},
|
||||
{ "z_listreceivedbyaddress", 5},
|
||||
{ "z_listreceivedaddress", 1},
|
||||
{ "z_listreceivedaddress", 2},
|
||||
{ "z_listreceivedaddress", 3},
|
||||
{ "z_listreceivedaddress", 4},
|
||||
{ "z_listreceivedaddress", 5},
|
||||
|
||||
// crosschain
|
||||
{ "assetchainproof", 1},
|
||||
|
||||
@@ -681,9 +681,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp
|
||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
|
||||
}
|
||||
|
||||
//if (IsInitialBlockDownload())
|
||||
// throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
|
||||
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
|
||||
if (!lpval.isNull())
|
||||
|
||||
@@ -45,7 +45,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
@@ -82,65 +85,6 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud
|
||||
out.push_back(Pair("addresses", a));
|
||||
}
|
||||
|
||||
UniValue TxJoinSplitToJSON(const CTransaction& tx) {
|
||||
bool useGroth = tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION;
|
||||
UniValue vjoinsplit(UniValue::VARR);
|
||||
for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) {
|
||||
const JSDescription& jsdescription = tx.vjoinsplit[i];
|
||||
UniValue joinsplit(UniValue::VOBJ);
|
||||
|
||||
joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old)));
|
||||
joinsplit.push_back(Pair("vpub_oldZat", jsdescription.vpub_old));
|
||||
joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new)));
|
||||
joinsplit.push_back(Pair("vpub_newZat", jsdescription.vpub_new));
|
||||
|
||||
joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex()));
|
||||
|
||||
{
|
||||
UniValue nullifiers(UniValue::VARR);
|
||||
BOOST_FOREACH(const uint256 nf, jsdescription.nullifiers) {
|
||||
nullifiers.push_back(nf.GetHex());
|
||||
}
|
||||
joinsplit.push_back(Pair("nullifiers", nullifiers));
|
||||
}
|
||||
|
||||
{
|
||||
UniValue commitments(UniValue::VARR);
|
||||
BOOST_FOREACH(const uint256 commitment, jsdescription.commitments) {
|
||||
commitments.push_back(commitment.GetHex());
|
||||
}
|
||||
joinsplit.push_back(Pair("commitments", commitments));
|
||||
}
|
||||
|
||||
joinsplit.push_back(Pair("onetimePubKey", jsdescription.ephemeralKey.GetHex()));
|
||||
joinsplit.push_back(Pair("randomSeed", jsdescription.randomSeed.GetHex()));
|
||||
|
||||
{
|
||||
UniValue macs(UniValue::VARR);
|
||||
BOOST_FOREACH(const uint256 mac, jsdescription.macs) {
|
||||
macs.push_back(mac.GetHex());
|
||||
}
|
||||
joinsplit.push_back(Pair("macs", macs));
|
||||
}
|
||||
|
||||
CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
|
||||
auto ps = SproutProofSerializer<CDataStream>(ssProof, useGroth);
|
||||
boost::apply_visitor(ps, jsdescription.proof);
|
||||
joinsplit.push_back(Pair("proof", HexStr(ssProof.begin(), ssProof.end())));
|
||||
|
||||
{
|
||||
UniValue ciphertexts(UniValue::VARR);
|
||||
for (const ZCNoteEncryption::Ciphertext ct : jsdescription.ciphertexts) {
|
||||
ciphertexts.push_back(HexStr(ct.begin(), ct.end()));
|
||||
}
|
||||
joinsplit.push_back(Pair("ciphertexts", ciphertexts));
|
||||
}
|
||||
|
||||
vjoinsplit.push_back(joinsplit);
|
||||
}
|
||||
return vjoinsplit;
|
||||
}
|
||||
|
||||
uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
|
||||
|
||||
UniValue TxShieldedSpendsToJSON(const CTransaction& tx) {
|
||||
@@ -306,9 +250,6 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
|
||||
}
|
||||
entry.push_back(Pair("vout", vout));
|
||||
|
||||
UniValue vjoinsplit = TxJoinSplitToJSON(tx);
|
||||
entry.push_back(Pair("vjoinsplit", vjoinsplit));
|
||||
|
||||
if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) {
|
||||
entry.push_back(Pair("valueBalance", ValueFromAmount(tx.valueBalance)));
|
||||
UniValue vspenddesc = TxShieldedSpendsToJSON(tx);
|
||||
@@ -390,9 +331,6 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
||||
}
|
||||
entry.push_back(Pair("vout", vout));
|
||||
|
||||
UniValue vjoinsplit = TxJoinSplitToJSON(tx);
|
||||
entry.push_back(Pair("vjoinsplit", vjoinsplit));
|
||||
|
||||
if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) {
|
||||
entry.push_back(Pair("valueBalance", ValueFromAmount(tx.valueBalance)));
|
||||
UniValue vspenddesc = TxShieldedSpendsToJSON(tx);
|
||||
@@ -478,33 +416,6 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& my
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n"
|
||||
" {\n"
|
||||
" \"vpub_old\" : x.xxx, (numeric) public input value\n"
|
||||
" \"vpub_new\" : x.xxx, (numeric) public output value\n"
|
||||
" \"anchor\" : \"hex\", (string) the anchor\n"
|
||||
" \"nullifiers\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) input note nullifier\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"commitments\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) output note commitment\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"onetimePubKey\" : \"hex\", (string) the onetime public key used to encrypt the ciphertexts\n"
|
||||
" \"randomSeed\" : \"hex\", (string) the random seed\n"
|
||||
" \"macs\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) input note MAC\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
|
||||
" \"ciphertexts\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) output note ciphertext\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"blockhash\" : \"hash\", (string) the block hash\n"
|
||||
" \"confirmations\" : n, (numeric) The number of notarized DPoW confirmations\n"
|
||||
" \"rawconfirmations\" : n, (numeric) The number of raw confirmations\n"
|
||||
@@ -933,33 +844,6 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey&
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\n"
|
||||
" {\n"
|
||||
" \"vpub_old\" : x.xxx, (numeric) public input value in HUSH\n"
|
||||
" \"vpub_new\" : x.xxx, (numeric) public output value in HUSH\n"
|
||||
" \"anchor\" : \"hex\", (string) the anchor\n"
|
||||
" \"nullifiers\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) input note nullifier\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"commitments\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) output note commitment\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"onetimePubKey\" : \"hex\", (string) the onetime public key used to encrypt the ciphertexts\n"
|
||||
" \"randomSeed\" : \"hex\", (string) the random seed\n"
|
||||
" \"macs\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) input note MAC\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
" \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
|
||||
" \"ciphertexts\" : [ (json array of string)\n"
|
||||
" \"hex\" (string) output note ciphertext\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
"}\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
@@ -1373,6 +1257,19 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& m
|
||||
const CCoins* existingCoins = view.AccessCoins(hashTx);
|
||||
bool fHaveMempool = mempool.exists(hashTx);
|
||||
bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
|
||||
|
||||
// If we are configured to send transactions via an
|
||||
// external service instead of broadcasting, do that
|
||||
std::string strCmd = GetArg("-txsend", "");
|
||||
if (!strCmd.empty()) {
|
||||
if (fHaveChain) {
|
||||
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
|
||||
}
|
||||
boost::replace_all(strCmd, "%s", EncodeHexTx(tx));
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
// Return here so we don't add to our mempool or broadcast to peers
|
||||
return hashTx.GetHex();
|
||||
}
|
||||
if (!fHaveMempool && !fHaveChain) {
|
||||
// push to local node and sync with wallets
|
||||
CValidationState state;
|
||||
|
||||
@@ -652,6 +652,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
|
||||
{ "wallet", "walletpassphrase", &walletpassphrase, true },
|
||||
{ "wallet", "z_listreceivedbyaddress",&z_listreceivedbyaddress,false },
|
||||
{ "wallet", "z_listreceivedaddress", &z_listreceivedaddress, false },
|
||||
{ "wallet", "z_getbalance", &z_getbalance, false },
|
||||
{ "wallet", "z_gettotalbalance", &z_gettotalbalance, false },
|
||||
{ "wallet", "z_mergetoaddress", &z_mergetoaddress, false },
|
||||
|
||||
@@ -480,6 +480,7 @@ extern UniValue z_listnullifiers(const UniValue& params, bool fHelp, const CPubK
|
||||
extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp
|
||||
extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp
|
||||
extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
|
||||
extern UniValue z_listreceivedaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
|
||||
extern UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
|
||||
extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
|
||||
extern UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
|
||||
|
||||
@@ -66,9 +66,10 @@ void CScheduler::serviceQueue()
|
||||
|
||||
// Some boost versions have a conflicting overload of wait_until that returns void.
|
||||
// Explicitly use a template here to avoid hitting that overload.
|
||||
while (!shouldStop() && !taskQueue.empty() &&
|
||||
newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
|
||||
// Keep waiting until timeout
|
||||
while (!shouldStop() && !taskQueue.empty()) {
|
||||
boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
|
||||
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
|
||||
break; // Exit loop after timeout, it means we reached the time of the event
|
||||
}
|
||||
|
||||
// If there are multiple threads, the queue can empty while we're waiting (another
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Copyright (c) 2016 The Zcash developers
|
||||
// Original code from: https://gist.github.com/laanwj/0e689cfa37b52bcbbb44
|
||||
|
||||
@@ -74,9 +75,9 @@ void ThreadSendAlert()
|
||||
if (!mapArgs.count("-sendalert") && !mapArgs.count("-printalert"))
|
||||
return;
|
||||
|
||||
//TODO: wait until KOMODO_IN_SYNC
|
||||
MilliSleep(60*1000); // Wait a minute so we get connected
|
||||
|
||||
//
|
||||
// Alerts are relayed around the network until nRelayUntil, flood
|
||||
// filling to every node.
|
||||
// After the relay time is past, new nodes are told about alerts
|
||||
@@ -87,7 +88,7 @@ void ThreadSendAlert()
|
||||
CAlert alert;
|
||||
alert.nRelayUntil = GetTime() + 15 * 60;
|
||||
alert.nExpiration = GetTime() + 10 * 365 * 24 * 60 * 60;
|
||||
alert.nID = 1005; // use https://github.com/zcash/zcash/wiki/specification#assigned-numbers to keep track of alert IDs
|
||||
alert.nID = 1005; // HUSH3 has never had any alert id's
|
||||
alert.nCancel = 1004; // cancels previous messages up to this ID number
|
||||
|
||||
// These versions are protocol versions
|
||||
@@ -103,12 +104,12 @@ void ThreadSendAlert()
|
||||
// 4000 or higher will put the RPC into safe mode
|
||||
alert.nPriority = 4000;
|
||||
alert.strComment = "";
|
||||
alert.strStatusBar = "Your client version has degraded networking behavior. Please update to the most recent version of Hush (3.2.0 or later).";
|
||||
alert.strStatusBar = "Your client version has degraded networking behavior. Please update to the most recent version of Hush (3.5.0 or later).";
|
||||
alert.strRPCError = alert.strStatusBar;
|
||||
|
||||
// Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:
|
||||
// alert.setSubVer.insert(std::string("/MagicBean:0.7.2/"));
|
||||
const std::vector<std::string> useragents = {}; //{"MagicBean", "BeanStalk", "AppleSeed", "EleosZcash"};
|
||||
const std::vector<std::string> useragents = {}; //{"MagicBean", "BeanStalk", "AppleSeed" };
|
||||
|
||||
BOOST_FOREACH(const std::string& useragent, useragents) {
|
||||
}
|
||||
|
||||
224
src/sietch.h
224
src/sietch.h
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* Copyright © 2019-2020 The Hush developers *
|
||||
* Copyright © 2019-2020 The Hush developers *
|
||||
* *
|
||||
* See the AUTHORS and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
@@ -10,6 +10,7 @@
|
||||
* or distributed except according to the terms contained in the GPLv3 *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* https://myhush.org *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
@@ -24,6 +25,7 @@ string newSietchZaddr() {
|
||||
|
||||
SendManyRecipient newSietchRecipient(string zaddr) {
|
||||
int nAmount = 0;
|
||||
// TODO: Should we randomize length of data, perhaps into buckets?
|
||||
// Sietch zouts have random data in their memos so they are indistinguishable from
|
||||
// encrypted data being stored in the memo field
|
||||
char hex[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
@@ -36,223 +38,11 @@ SendManyRecipient newSietchRecipient(string zaddr) {
|
||||
return SendManyRecipient( zaddr, nAmount, string(str) );
|
||||
}
|
||||
|
||||
|
||||
// The network essentially DoS's these addresses and reduces their privacy slightly
|
||||
// by making them public, but in return, the rest of the shielded pool benefits
|
||||
// and so it's a large benefit for a small cost.
|
||||
string randomSietchZaddr() {
|
||||
std::vector<string> SietchShieldedPool1 = {
|
||||
"zs1qqj4aw35ku9yn72g3tha588mxk66mhl5smnn99as40887xvdg49d4yqf43hhqnj9rpsq7qaqqhx",
|
||||
"zs1qywzq2cutvg6rkynjljtssz246easagumg3hlwjluz4g7qttg9kqrld7s43ewutpph56jmn2zu6",
|
||||
"zs1qx7swmw28dj992f6zs0aqucds9kag88mnca5u73dddeqek4m97pg7h9qsaxxwwkgqxht6zujaxc",
|
||||
"zs1q82pkqu58uemrm2749x6g2ta5shnsra9p5jgk0qqzxd3e08ke6vyeezz7lhldj32jxtsuemskk7",
|
||||
"zs1qvah5w05qq4yhrsqrt73ckgntkmwdv9mntxep8clnxqfph8xggqad96a5nvwg4evfr9pc5ruvc8",
|
||||
"zs1qwrkjcmnrwrqqkz3dyfjvdvdppe0ndnm8fhhpsz8stje4qcfc54jtuygz2jfwc3aag69wsjcm8h",
|
||||
"zs1q5pd7h4x7dtnpa4ace7tytye5sd0j4043t4f3jdntyxvg9ex258nu6pw9tthn6t5gmjq5gv0lhc",
|
||||
"zs1q6vjrpsuf468an545q7fh9cx0xlkwh75a7qjpemjh3ymuqqzxz5ts2n2dcth3yfnlv6vqpjyglr",
|
||||
"zs1qmsvwtxkwlh3tkh0lqtwqv2mxy94jt778f7j74a8067nejkt4j3m2rkmypccju7cfuw7xyg0gg8",
|
||||
"zs1qu3jxrw5qwuvl7zfvnsdvywr4a9cn4h00me65te29platx5agek072f5rvxgt8kdt630qs4tgtr",
|
||||
"zs1qamxwddwrl5xn56alffruk69p304cqf7uf5nhqpwfc374l9ph00m78xv2kzwymyz0fhxcku7v5k",
|
||||
"zs1q7gv479e6q7d8fxc35v5s27em66mmm5gz50excudf95rzjgnwdy5pnwdfytvm7gt8kt6wpkfphq",
|
||||
"zs1pqvxd9a2zcsh2v8gaswh3jp2qkzz5umrucl5k4gx0rkvmq68krpx3jesavxftd8t0z56v8whllj",
|
||||
"zs1ppn2mdznaa2pd9mavfnxrcjtv0c9un8pg6jaa9ww4wy6wdfs8xxwquqk5umtcjwm6vr4zrqy5x7",
|
||||
"zs1pz9c9ydyrm7e876cvae9ha45ww77ru5fhys2yz33kjy8ej9230wjy8yupfxkynwqr6nfupgmf94",
|
||||
"zs1p83g95avpsgr847eu3rm3xcmgurt9hc77wtndnmpypa046n529aqdc9ptz04ugsuhvum2ztzwe3",
|
||||
"zs1p83jle2p8awu4peevq389y5kyrs5tqxxyrk32zy0t98d4cfepmme0myxp68nrq60xwzc5teulvg",
|
||||
"zs1pg5ggzwx4yaa7g83yuhay8kzh78nahxfe7cgavn88f7rxlnuckhl2vznv0f33yuqhhs3sh62vl6",
|
||||
"zs1p2nrefmqfhnwrxqfsz4ruvu8wl7742j5rv2fmwlpmpudwqpdn2yrha9rwsu5gc0fdv2j73tfk6a",
|
||||
"zs1pw29hkrvszxpe2e4tjpj5h9pszjhql2p4tzcj2c5lf67m7d8jtgc22vehftxdnqze33mgtjc25k",
|
||||
"zs1p0ggg024alu2l5x8df8ucu4lz8r453su56w2mmshru49uh9a0p6ufy3qfj8a9n7xeu8dxxjrk4p",
|
||||
"zs1psaydszvszu4mar7ef9gk8atmwpnfjjsh8plajn6ttlgdk44jfud5zv8l3uyq73qk3eskec96ut",
|
||||
"zs1pjf3kczvrwduuy4x99t03wfrgwstueyw0ypvwa44fz2tukux8kqqqs48uag4y39ed4rux8etvv0",
|
||||
"zs1pnwzzh4mhehkvf4ys9x70q6meq9mgqj6mgl9ddzwvf8excswrj54lfgu4m9slmc90s37q8e63du",
|
||||
"zs1pnndevupuakjcqyqzu4sfcgdmdzrhutp8ygxwsl5wvq5hgu20u55auu8p08wphvz9mu3k8ynyr5",
|
||||
"zs1pmy6tvt9p3xxp5edt70mkwfqk0ljgaranzdnluh5ln36g9g3v2udquleuz5974q2mamywmrxl7j",
|
||||
"zs1pau6lddk3uapms7v7rsmxvxeekqh52z795kzy9z3dv9qvzq3jwh4pr2adg5cf8fw2e3mzqmgstq",
|
||||
"zs1zpy6wuvy3jlrfmj0363tx6cuume6j0mqfakk7ydw4f6zvn4s7plewk0gtm7r34pjtppvkp8rzl0",
|
||||
"zs1zpvkccety206ww6c344ehughuyklc3v02q07j4p72pqewxl0n50zugtje6lclj3m292t6vs56fl",
|
||||
"zs1zzucdg9kalcjnnknt98gpg42qm9aqpkc6qf5ewgr29udu55r0zt862z3zt23sd4mj9t47k7k6w4",
|
||||
"zs1z9agq4vq7eswwynhmzdsy58nxq3azhn66y853yw9kvercmve8vv6d5pawpwwpwpuyedmzpcqk8q",
|
||||
"zs1zvddl2e0pve5kl0hu7fcum30lyhx4pdq64jztq2vp09lqtu5gclfg4fe9fqvnm8k2d5svydg7s4",
|
||||
"zs1zvsmkn6a4celtcg8ece6exnkvnr2u06ej8kjt6mrpm0983e86dr9al6gd5g73k24j0a0zkpjs3w",
|
||||
"zs1zv33kglx4n5572dg2pez2k3m7tgtz08a70ndpfj6x204pphlm0pzcppetsnjlat3qflswqfmu83",
|
||||
"zs1zsz5c9xua7arkvd60vsl559d4dvnjz8ejq4rlmmm9cnz942fdmjmvsgrdl7d5ddxh4y9258jk2l",
|
||||
"zs1z5n6qvch0wfymumxjflezekxa2j5t978eqzh9ldxsl39h2jjrlzdv9rf00wdrvg0t6afq7mq0us",
|
||||
"zs1z4ymm3gt22f3pcj9p9l2yg00e2m39kfexgaz99s9y4nsuxhlk6u0sl9lsx9awzywumxyuxv9vuw",
|
||||
"zs1zkjnhz96xepc97rfyven23epymd5s558yqhp488gcxcj794z6p37h5ej5m5waqxfupmc538mej3",
|
||||
"zs1zcqdekyq656yj2y86lh08u8zpetfanj5u4rhfpcphne9xw7esce8asux2rdr4yjxzds56fuda5r",
|
||||
"zs1zceru3jt9m3jqzacnffetvrg8zch6le0zactl7ssfky2vwy7pcffkg3pmauqqpkv5v7nv3uzc5a",
|
||||
"zs1zellp4tdmxdsd6hmg2c4qlx96m39c0cjlqupw085z87lvzcnx2r0gs7plc0wp4m4upk3zcs35e8",
|
||||
"zs1zm2pcg2d3hnyxufn8cyshjn742gmffwaqdc0nt5uf9gsytdjywsqaasfdxf4sysfu0sgxjwjp0g",
|
||||
"zs1za9nk7fpgnfetjulq6t8jgfyks06xg4q8rfwpgsfrkn49k34nc7xhm27dnjuzztgnwkww28ztyw",
|
||||
"zs1zaaz6j6z7z748mck4v55s3fd4htl4f478kulnwr84m8vn4m0r227juddyq0ncu3cyvc765z9gm4",
|
||||
"zs1zlz59lgwc8pqq33508v5ygk9e58f7fs4rpj3achhwnkcyn2dku44yfjghdf5l2v50nu2gjzgl2l",
|
||||
"zs1zlgenma0yuqxmqgns2avpnauclxgfvgd6rf0jt09fmfyaflwlhsscem9ypmrvewl9l356dn3jtr",
|
||||
"zs1rzu2yg2328l2wlfstu27dl024ucqsjx6g635yxmyhs0wr3lduutkc3peuhqe83uueh5n5q624rd",
|
||||
"zs1rr9jpeemn9ek30x4h65rx0ddul7xet6cc8atwrjftmq9sdrvj9f5zdc9xg7amtc6dv5fxjyhu54",
|
||||
"zs1rrgccr0yvfn5fdek39x09y2ylyf42xkydcwzq67wdrzyjj2mv874easa4h4tymz5gj852aqpffk",
|
||||
"zs1rynh7vl05weafzwkp0p5eafuzzqph04prgg74emqq0sx6xudtrs2380v3ycxgp5lzudw6tmc2zd",
|
||||
"zs1rxqz0a59zx3yduncc3azyzexwu8xl6cc0zu83hfd28mksrgahhvx8604uhf0u5mna9m4znnj4gr",
|
||||
"zs1rxr2xff2vcv0y9s6ux6c6t9y7r3zvcvrqmwkvsnxj39t0qv7qwyhncnykhzcqg0ggpu423ykzxe",
|
||||
"zs1r8chvye5uzlskv8jvt6j8nxnyz4lshy3u46yjhc8w9ekhjhneg402knft3t943t5nrhs6d0d5um",
|
||||
"zs1rgu6mz58xrqxpyl5xw7ss2szz29cg98s8xl25hu7fy4lcxw58zr93a8rgyha52vwxx7hxj2emkw",
|
||||
"zs1rveutz8ftruljrlctum42kakjqk4cm8dm2807nqm974dz0rptlxcs999ttsvwp65vc9e59vv9fe",
|
||||
"zs1rwfqhlezm5ln7kq8wp8hkl08ddn74ryr8cs4cu8qc23spdx79xgfqj4lju4u2yqdrkxkwfvk3ed",
|
||||
"zs1rwklllsk9jwhhf0fedvlzsqfqdkwer05zh8c8hwypl4tls2hdal54lexhca7kghhum5hycurvfe",
|
||||
"zs1r0ulehrcg9xz0lfdcukjm3qlvqy74t0u8raqf4zn88vdsta8mzp8t8p9ul8jragssvs9qaqpw2e",
|
||||
"zs1r3t0cve050wufwl8r2tly05vn7w79v53fe6dagjtt2ese0qm6vgjp3rrsfu4n0am840sq5thn72",
|
||||
"zs1rnd8zwan2xlrnfwylm9khkeutnzg2v9vjdnyellyuzkwmed94uvd2dq8ceumxwspz037zp2ctqa",
|
||||
"zs1r4tphfnf3zy34dqyjuld2kgtyg88hrxpv756pkkkmrfdeun0cqzpepac4ma9qrjrvdqxg2z5fuv",
|
||||
"zs1rcpywy0v4sfej85wdaslfwsp4pe9sa87xgzv24ywhps2l4c9jlrqttv0wl9zkc5e7rsekf42wvp",
|
||||
"zs1r66et0z9xw3qqhzyc2aht294y7yqyz8wx2l2t63unca4k4zh4v9t44kpmg52z9va5968y45fdkx",
|
||||
"zs1rat3szdulwxwmx7y4rdphvlpjj5phadvz0fsvj7mtg9ggzwd22sn30hzsh27h7t6cvca6a8wu2n",
|
||||
"zs1rau4jcth66jsg098ucclp9tfa5qe6jmtmfkcluaqnyj3uatkt9dsrgx44xtmxr3e9xuxv6sy208",
|
||||
"zs1ypf2v2yu4p4mnlmw0wd3mpztpjlhl39jnn6hkvf77ell0h5u6yg2pgeusvku5y5sykyy6kk6yyh",
|
||||
"zs1yzkt8catgk6slwj7azu79tvwv6tkd6agcykvvht4rxlevtsh99u036jf5503pju3h05w7x02cm8",
|
||||
"zs1yrty5fmnyaartpcyjnpal0w44g4mt2ey5tyzcmgq4g6qtsfjmxae7fvy2zsw7t0zvseuwcfwt2e",
|
||||
"zs1y9p5gazcx04kke96xudep0edzkqr06gdjnr5vm99a6qxzatqz5katput4q9nx95e8965sg7d3pl",
|
||||
"zs1y9vpfgkxwh3xm3j9d38zkeqql2lh8w3ucgerkww2asdv89p87emdavkzurnqpkrmu7e3xv5myue",
|
||||
"zs1yfa9gwmn0xe4myrg0rf8kmu36243u8773ukeev0set2yv0z9vpxm6ratee52e9zmpvvx7w2xy28",
|
||||
"zs1ytpjrujfsgs69smqerxeaf8m38jwxc4ejgxxe4pzc5qu4auqrgy8tf7zxc402pxf9uku646kc0q",
|
||||
"zs1ytvtdwmcn8tnka6w6wa8n3ghnkf7gp2qaudd4233y6m509ntm59rr0n8eudhre0md7m0zedpcsq",
|
||||
"zs1yjmeu09mzrt8rgehv2gcfhxx6ddqz7ww87ssfapndvc94hxfrfsdkkgm8f8nr36xm8p7q462qy2",
|
||||
"zs1ynqghdu0r0c20csp3ygrxdw9hk2l89j3g59q8zhht9jyxycpcc9ccvhyyn2f9j0ehp4pk5wkhqs",
|
||||
"zs1y5ny4jpjm05vp5awjd6muaqqypdv0y9tr6pz0m5t82cwtrearxwf7km4aznydpcjeuzxqvk0z9m",
|
||||
"zs1yh2vd5usfsyv4pscjrxg9wdy3gnnyuh8vky27ln3u9jspadmpqsjmyvxmvfyyq3nv4deudvygxa",
|
||||
"zs1yclvhy57hngs7d233e4x8ywfreswslz2gvn0f8epcs0wrzuqqau3hkrvf7ru6jhh0zmsyn5jkj6",
|
||||
"zs1yunkgwzf0m5suz380j7xqge6rd9e6acjc5wp22z0jhalqdpspdjey7jfjvgrckgsk9ydc9yrnq3",
|
||||
"zs19p94fnry6p88ms3yh60nl4kxlxmu7uxv9aafmf5pc4nyd64vslaqgmj30nxe3l5j7cxu5kqeqpm",
|
||||
"zs19x2df6qmd4c9whrgj6m4mssz22x9qj9x8lmcnexnhw32pey24xy9sws5ts2q7guunm7mx9wmllj",
|
||||
"zs198a984na6qt2z3uyhdkmj7sfevt794dl3mum3782kddjy4uawr2teznpuxvnzc4dvs3c6zyqxey",
|
||||
"zs192ld62azpypesveqsat6m63sqaw95ejlqfcjsal5t0fea9zjzqnurmpnl6074zdms0amw83rw0x",
|
||||
"zs19vsx09xmzlj9vr3s3vu8z4237gpcgrl7qs0vapzzawgnu7gxngeaxlgwqf0ppu0f7us9cfe3cqz",
|
||||
"zs19wfwd8zufu27zugan77wf2g790egdw7vkulf6f375ylq0arnv2nv94l84nl8lp3tpccv763wetn",
|
||||
"zs19wcqtqqjj0mnrn90ntcmyq5x8qr2wsaslqwt0fysz4xh2mmjy0z9jjh4sj86sjrgen0axx04zt4",
|
||||
"zs19jypvpjpvhv5et5wq2ny09skt72hxz9adfgk2ev7nza5jyxr6gss5qelygnxn0szmjqyke2h8a7",
|
||||
"zs195kll03d43her83a65y7z0zsetynlnft4pjxdspegvun0m7cwtx0vsxfm89mv50vxr90qhvcqpz",
|
||||
"zs195e2g52jpyly7t9vjpfcegt87g7lpa4rm74nxn0zvmtzjhvg7f5gjnskc5ax5skvwprcshenyqs",
|
||||
"zs194e84mfxc4vn4ssce7hkvgrcm3c8j7vehcetkdf78rele2lwkx9tzcfnrwhykdqa2nmwx5qcr0j",
|
||||
"zs19cxqspj63ksk6uwtynj0la72zuvh8rxfh0e0pr2y5vuuvw35sm78juzh5gxcuqa8jggv703rplf",
|
||||
"zs19e04k24qrca0sx5z47dxmtx0swcx2ywxqjt5594gu95rjaeyxrpa2vyylvzxpau5spt2v529me6",
|
||||
"zs19707gmdvc4hfwg4lgvxg55695gltx3jwye8l2gjekrx4zqz7yr6grq8s8hpfqwggrywx509ln5y",
|
||||
"zs1xrw8nwla7yrz8l3d7y3rxlhamel2ly4kdmxlc6w4cztxhd6l8wufqv2pcsvtl3d7s6awvjatyx9",
|
||||
"zs1xymrgyhle6dcvjk5f62k4xygr0vrr2wckqy7sp6wc6cttn29hra77dzhwxst7z9rxqxkz08jd7g",
|
||||
"zs1x9c8tetxgauxh474hlhnlscuhgzww8vnvxfwm0p8589x73t5yl2fph8q8r8qpl8sh0wfwx0vg62",
|
||||
"zs1xxcpzsfpyekhvvum3erxjpt34pw3h70ma8vxwecg85tze380f4srlg8zlgxty8yqhutt234nk9q",
|
||||
"zs1xx6pd3vtj78tg0zpwtc0jjkdxlfy48vegzd6cng4m9w0gtcya8ck7pqgf4l5sxf9ml5zvzru5xg",
|
||||
"zs1x8qre6x5d8e3tt2m4l9q2tujw8ajun70qelp8tfynyw390rm6vhjtmpf58dmx4hccef9xe50az0",
|
||||
"zs1x88vjduckqarz2j8tp2me08ya4dgd6pw7j4j98j5jynrze3xy2jjptzye7eftjxd6dn4sj03v7m",
|
||||
};
|
||||
|
||||
std::vector<string> SietchShieldedPool2 = {
|
||||
"zs1ehrs7hetemzsmfz9xwt8xetxag33j3xzj8mhdgywdnvkk4dmtvw6eqys6gm3vr679y865jz7rth",
|
||||
"zs1ehyr6w0c4mwp0wlp6w5letgm3rjk32rxa9kkkur86e5x8lutr9mwzey0hsesnz0yaarmxra7w2z",
|
||||
"zs1ec793pjf3anee0qq9ex5u2qygjzk9llmwfygev563l89quc3u8wxvtz9kctlmv2dtjgqwn7krcg",
|
||||
"zs1eclpgnqy7qll0l5z0gy7m4ew86yjvp397yxyau9y2y43x5mqfdw2sll95l83ux6h8mppzsx3xnp",
|
||||
"zs1eexedkctuzhjysl00m0j3ekknd32635yd8rejx9ykjp6zz77fyzf5388env642ja2qlg6mrwgsc",
|
||||
"zs1e77uz8yaj998arp56d0fm4p827wchlf2w09hve6rgkmavhzeyhke8qsk3l7s5k6yh2jwjheqpup",
|
||||
"zs1elj4qvy42jpts2cu22tcwt0kmwzafpmrjgztwf2xcqaycrlr4rpfxfpswx63e6agvhz96gps9yf",
|
||||
"zs16q0fzcvf25fh70ysn38v7qkpfspakmelnljgnyrpu7rvllyew57n5cpqjqe0wmy5j57au47j6x8",
|
||||
"zs16pnkw3mucdef34jjk6q28zd7ghhatdcqn598vs3g70qev234uc5uw6xxxjnzef3pt2t567qev8v",
|
||||
"zs16rmnl4hd6c226u3v6eekk68y59u0x7v37n8pmytt9xw6drugjml7ryhd243nf3l2pvafw42rnxc",
|
||||
"zs16ruwvwmetmnnns0rxwtx2kss23da2pccares0tehzw3v3nxd483qn49c9apdfua0hpm8xdecdt4",
|
||||
"zs16ymafsjd7fp9zdl9vtyvfedecvn7q2vcs7emeglwy7hpuphve97d3j87v2evqs0xm3jrx44nwfe",
|
||||
"zs1697ggm9zqp4rh0fv4r9hnh9uy6gg4hk7r2lm33tp2we4ry5azpxq6nwuzscha0g2nx03x4sstq8",
|
||||
"zs168t8u6at9k6kt748dv749dxahnk8rv8yn32z8gcgvc9rkhkewscgu8r8vuzv0zecnq26w9p7x0c",
|
||||
"zs16gnyx6f8vql24cepamfquhr3jjt7wgmzjcvwtct4lwy9p2studln6ut9kjzf6empwqjtxqmddqy",
|
||||
"zs1622ra8snywvxufsunk97pccr7k0j32p960evl9yqjadhju22m4sk48md84q5u238gej8xnm4xm5",
|
||||
"zs162stv8m0udzy4c6ff5kqva2g7pqth2rrdn7rjjgw29dcx7lj3vs4dnj8fz0gczsat3u3q5axgva",
|
||||
"zs16t78376h9ledgt50k2dmwssuhyy4hn94wfgd8vzegvqy9k9kauuvpe8xz0f3va65l8ufqhgv4gv",
|
||||
"zs16vxrghgv7mth6k9unzdude9cyt9vl76ms5hm9ce4py92rk69j4p9u570974nh8kqh8e2stqknj5",
|
||||
"zs1654eafn589g2ujzcasa8caz8exag742tra2dd6mjkp22axh27hda6sy9exh3wkp4c6f5vztafr0",
|
||||
"zs164u3ntsnn7s3zrp6c5gsqfrwr0ywhspynvunq3fhvr9crwz5eme706j5awwvuatqwh7m2qqkqm9",
|
||||
"zs16cpqwm4yml5x8j5r3q5j0xljam68pf56xt40hylzn69w45venwdvd4h8drys5t380mspkvt7h8r",
|
||||
"zs16c6m9aqs0q9kadm4nk6hugmqw6p0lf2h6v5d9ccwszssyecq35sm6284c3uqx2u40da4s2mr2ap",
|
||||
"zs16u7rc066566j9ux73dcq0m7cq4qdmtd3gefrnhhrpjww3z00j4za7m5mcutmj6qcezkzys87mpp",
|
||||
"zs1673rm5d5z9sh2k9uc2cvgwk2e44z0sekx6ezt9n4fvgnky5yxa2tc306dw7n2dg5vwfn7ppwr5s",
|
||||
"zs167nvq5ahvu4s26447rem9j37qglgtle4fghsgpksumkz34g2q9x783pak5jgdhhzylmgs9wemg8",
|
||||
"zs16lluayez28xevxg0rawxxcd7yx5t7qaraet256sxe8ac69lj7n7ppncsx3m2tddxlzptzyxv0qr",
|
||||
"zs1mydlmczamey4ydc79n8gj5wtgs79zge4nwhcg8g640r6fvwu6wpt70970p7ptkcrzg6r6frqh0u",
|
||||
"zs1my6tgqmy3kgdlqncyd5dv9s727x9hcrmj8h06e5whn4hkn5t2x46j84276yd8pw0p6ysx53u38u",
|
||||
"zs1mte528eue8smvjwpe9cs8qz3wud9735rnk7vrtefu9lhyvh5pyeyenpaq5fa08jpwrl4x7sz069",
|
||||
"zs1mvmu20syf3u5yzd6hpdd29xfej8237x2k0pcmf7pvra46qem5g0jralrmdcvncgf5j0y5varzr2",
|
||||
"zs1mw86y6g2c8972a2ndw57648p9qcx2jppxr9g5k24df8hl3rgfzfsfe2xyesemdfmasutk88duht",
|
||||
"zs1mwca7dqjq0r2mzmn4qarw8acmt4rjk26lyyar35sssqe2fky2nmv3kmf0lfxs2a9htugsadg027",
|
||||
"zs1m0rpcrkfagzpex9mlw2htyrwpxe48v47pj8zg96l9wm5k8xkj3kev3xca6wumv5avkgsjtygush",
|
||||
"zs1mjgyju3jnyxjhekv72y448edq3j2cvtk5s4wrej790zzpv3uc20dvewt7nhjdqryuecmykfm0je",
|
||||
"zs1mjlfwyma3fv45yg50j73wcswnap2s4lsh5c9km6lcem73wky9lej7vy8wrlkr75sy6z2g0agtmw",
|
||||
"zs1mkh9s9gdfxx4dkug47dqnc98g76dhm09zty779pm6gqc5aye4gvxvduqm5j56nq4lncx5ygqu90",
|
||||
"zs1mm7tesf30r56l8xmnxjyxvgmnsny2zntsxahllrd930q8ycahz8npdxt7lqwu3k8ljs9sw7uzs8",
|
||||
"zs1mu34v9wtyhtlr22phfxkp670wt0gj4z8czumx0m4u05elg7kjzu0dzveq5jn28xg5a2wqr6cywd",
|
||||
"zs1ma3xy4fj0vm0w37a4kur3ghe72f8nstmqmmvh0u48kurtlwg50rqqlw39j6ng8lrxgam2dh0zyr",
|
||||
"zs1m7yauj7694wjz92m5sxds8udp43z6kclarqwzc22wn2q6svkkk4lpzx53kwctwfn6jqcu4yww5u",
|
||||
"zs1m77qqksfvuqmjmwdm22xr2u99z3uz4glenk02md4tq5z066gc7jkdayhf2txspqggv29quacpy4",
|
||||
"zs1uq88d69zrnksytnquejpksdvdlp9e5y3xec3eyf0rrya8zap623zpwjs5mfzadrp7twawkpennl",
|
||||
"zs1uq0zzag2cmekwn9a35vkf2q45sary5v8nt2adukhej9ydq3qpegskg5naysl3wvvxtzuyv5lu8w",
|
||||
"zs1uqs3n3j8kfgurz8tj0ea5g2ny200c69rwwpq50kkup8sxntdne6h9uhx3wc2y5jjkcggvpvcl4g",
|
||||
"zs1uqmnl793xh4cskxjherwlpt7xfnt6fy2sp2l3n58hpmd4msj2g3fjsks02069tqgzzvn77mpfg7",
|
||||
"zs1uz73f8arfahrvgtxcjwya33ql5w8mwkmyrvxvjrjx5rla07hv3ax49hkeqg3aqynxx39z4y4vtt",
|
||||
"zs1urzuwedq4qgnqjsjwjeauzyyjwxvs27mau6zmpretn37my92h3jqc0waad4r8s7zeeczq6jfas6",
|
||||
"zs1urfls60sjxpnla4hhe736qu54w7047akw2p9cksx054y8e8gdyknkhwv6spwzgstf7z2wrsdapw",
|
||||
"zs1u9jum0rl3959ay3qqxskkak5emv0fpceuhuhcj9rnkzfy6gpe2uv6ny29c399nrc68fx6fffg6c",
|
||||
"zs1u8fdxg8lu08p6s5z9qe6jf6fkvd74a99yg3n5exlm6wm8paypygy82ue2smf0qqlhdhjzy2jxq4",
|
||||
"zs1u8u44rlv4ay27248807fqwyf6lw2w76v8evn26nvwv887caqlenjgsw0nqlajzw9equn7phhs95",
|
||||
"zs1u4jhx25fghqzn2az7he7lrv7xj23xd8spcl660g9kzqa3wyykm5gucuu5wwxvum6l6spq4u4e5s",
|
||||
"zs1uh85d43vr4wwqnq6e7akxtlwkzx2y8cmdm3wrxzj6m42pzj3xs2heqey79hgxrhwhapwu8tt73g",
|
||||
"zs1uhwgwkg2y3xex7e34dvnx97d0jdnhmchevcvg54tg4dg00ay9sjucr82py4jqx0kkf7cz5dytad",
|
||||
"zs1uhkhsv3c3m5r8z7unmceg4zln6edwfr25wjauv5u8fxdqhdflj7vuc2xnkm9028y802w2pyf07g",
|
||||
"zs1uhuwuzu89j05p9y48nseklu7gfhw4mrwv68f9s66csafrkpsmpsh23zzgxm24nspmsgrvtpttzg",
|
||||
"zs1ucetuz8ysvz42uvuwndjfnphrtsfgekgef228meuhfrqtm97gql87rsvhxmxplw2xmj27p9jemj",
|
||||
"zs1ucm95fgyy72rf6x5rwl5m5pldt38lulzqf9ueepel4gvd4cqjhk8xrf4kvl2lnn5ge9fwyfrfva",
|
||||
"zs1um3pu2u0eu0zpx4czj9dufvxnud2zd0x5lygepp6maz96j572r6mh8gpmlm3w6jhmxxz2sepdfh",
|
||||
"zs1ulkw8j488xuhhlewedj9dr7atm5jatmlwsxz83lquhz42ln78utqmtqsmhagcquq6uqszk23g9d",
|
||||
"zs1az03j8f46n2600z47xnf5y28j34rpxljh3j6w5p3xgsmqt2fuklmhyd383aljxf4mx4pcfv0xm8",
|
||||
"zs1ayal4wq4crwj70u6hae82h6r4jpk7ptycfhs9v5y83lxc7u4gadegu2r5ggsgt95n0rjk284fzj",
|
||||
"zs1a984wux9sr2594lr24yal43zq6pstczyevj7yr8pn403643zuge88ekrc0cj8n2fk6z6xrxjpsz",
|
||||
"zs1a95ptq9d6nauwtvgdj2lnct9y6g4cmm258jzyuqhsk4m3gqmaz62t4klqe42eu83n27jcpgz0ed",
|
||||
"zs1a8xdhdzpjqx0alrjg43enszjnf6nn6nhf6c3xd77ecrvp4kfarvux4u4lcttv3rgyhmgzxukw2q",
|
||||
"zs1afqnaljmvzunvjhr3m8yf2g4r0pe66kkxkm6ldjhylyjfsclk3nf88u29pskdqx76szdz48tt3m",
|
||||
"zs1avx0j6mrcqrhp9903xrysptm6gefcyv6uqltta92hsgjpp2f8h8rz8suwxgjkp2f8366y6n6dj8",
|
||||
"zs1a036amk3q8azryytah2zpdhyazeruq2q7zq2c06l0845kl0v2rmg0h8cdjvta4alxj0my4kcfad",
|
||||
"zs1ahy2sja2ala03wrc79xx2ks3ujxxnsm44uh6yucmy5p5l0xcfa3g90cdgs4l9rhy975zvd4uzts",
|
||||
"zs1aeyqta7xs8edzq2c0z6e9v3vjep55e4lg9fp9ls6d55x2mel6snxud6kqcaz8nl7zgrxxj96d6a",
|
||||
"zs1aap3thj9xna07vlg3yz389c34v9mgd06g234d3htyq667286phjsf98nndm8frts7frmcyjfa90",
|
||||
"zs17qdqrdgwcafkpgchc4rvk22e4u86alhnmzne5xzantpecwrxf3c6jxqk7xgzanzjj4kmxd2tuwg",
|
||||
"zs17z3fmn6e84ypzpzn0p0j9nddptrj2nwhk9lhaw952j0lzxslrp24cj0ltuem9g5dustakcq4dsp",
|
||||
"zs17zut2398dst3hnmnslnk0jv9w4q9yn8akelymvs8ewurdytxushp92nyqv30quqhy0yju7rn7lw",
|
||||
"zs17r4fuv9ldl3kzwk5stv59exusc7jlsmtcz4t2uzjnrgrr6aj6tvnp04wc9jq2n3eh6fsyqe2ru5",
|
||||
"zs17rajftxlkcywcenl0cn3fqw4lh2un5lpfegjdz06j3vl9gjmay2d5pk7uequ02vw6tmtzz6jrst",
|
||||
"zs179rvu8endcr48sft7zg4w6uvxwu4ps94r06uwk7e606yffkgtx7epaamlfdqnc6xa4l9scqcv4v",
|
||||
"zs178dr2z7zgqrsg5ul3sxx05qky2kemfequf08dxr332n9f5fq9cj98jttssz97lzmf2k22xpn54m",
|
||||
"zs172zz77ds82urqmsa9pgyz65k04euw7uuk58k4ardcxectjc4t4yjekxm8xxmgd7gqs8k6jupypk",
|
||||
"zs172eamykp6sl4vx4tsgmg2t0p482hnn3gg4my9y4frd4tl5zgsyrsvjvlxc9zjtqpve6e6djdc4x",
|
||||
"zs17v4xqdu83fkvrjxrpnjksuanj0pung2kqn9ys533nnm8kq8ad8xv9kd48e4utrz947pejg55p46",
|
||||
"zs17dgakqvwzgh4dgfe70cjulju698cs50zvchsze2e3zvdp68wytqdcvj4suh4vq2acdg7wuvs7ar",
|
||||
"zs17snaqr6vukwp4apsdf44h6w3flgphzrnpmdjly662tgqtvkgs72lpz7m7tnkksdmt5uzjgmpg2e",
|
||||
"zs173ad7l6u8dr90e2t5jkrnw0gc9u2mppv9vjeh8l6q2jdvgnq6tq4anxxltwuxm3wssfzgg6hfcy",
|
||||
"zs17nez6jn8tnse243f5uf72d8y000ynmjnm6vsrpzpd2fj75wq4u4lu7xc8fmtn2e5v0r7uknphs3",
|
||||
"zs174c6x8u2yagjnsq2kswnd6fh8u2f3g5dkrk7r7ja5n30zwjm4ke3x84syt9qklqyk0m7vekcx9f",
|
||||
"zs174mlfm6snsmgj4usez3e6xtd5nkwwl24vgg96srpnv7ulz4de6n4lx6cmxaqszqnk7p9y6wcl8q",
|
||||
"zs17h5lnrnpprdtkjwq09ax94qetryf65qm5jqv0gpyeesw4wujytks9qljvlry863flf242arvx8f",
|
||||
"zs1lp07e40usxenrznuuf2nzn5v7tx9pzp9r6eaw6upnm4t9cer8l5fckzm7jr58j5l77tzjrprv8v",
|
||||
"zs1ly5u5sqeeax9g3uafva7fl35r3wv0nm2aka9m940graqjh0zlw7rrcgay0a7f29j3ar4wrj4uzu",
|
||||
"zs1lgqckcp2uqx5c6gdm5zklzrxz8ygva9kxtxc4u4dlzpg68m9prga5q3ur3uqutkcy4ztuhclrxw",
|
||||
"zs1lgz7ychnnhe58hk2e379zhqdxynp30e6fdh6xjxx8u9ga9rmwzdrdvqcq5kps2uetyf6gzeqdn2",
|
||||
"zs1l2ghymesqwrfw89pqnw08u346es6wn86r77a55n7d7xky2rc58jfhn7man9kjjesnegec3frxeh",
|
||||
"zs1ls3lyaqhm39zgz3528ereaa48vzsw4cw99k536524a6ruxmdqyvqnv4pl477q7rwptrzx8dhhzu",
|
||||
"zs1lsnr42d2ez0w55pxws4qn70f68vxllv92wppu24n75y7a0wrmkw6qgup0md5jhjmkwhzu742zx4",
|
||||
"zs1ljzwlum9nme83hhvkjkxl323u0ezm4sgnk84nzkyu5acum0kxf0s6g06gy78w0hl66f5263g7ha",
|
||||
"zs1l5kfev0dpl8swjlyvyms5t9yhhnvg0590jfgpxw7zxx6eh29vd7453q9d0ne75x7gsm42j65l3v",
|
||||
"zs1lhpxmvxmfpdfa5myd35wf24pmacrgdhrcpxydrcwz3qvmfvpt9x78nf2ne3kkqh40m0nvhhd3uj",
|
||||
"zs1lhkhftvpkvcuyhwgcz4gq9y9l3ly5esglk2g0sgdctrz2cd63lgss2gtn8eedsvtuh8f6shpwww",
|
||||
};
|
||||
//TODO: Assumes pools of 100
|
||||
int randIndex = GetRandInt(100); // random int between 0 and 99
|
||||
if(randIndex % 2) {
|
||||
return SietchShieldedPool1[randIndex];
|
||||
} else {
|
||||
return SietchShieldedPool2[randIndex];
|
||||
}
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto zdust = sk.default_address();
|
||||
return EncodePaymentAddress(zdust);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2014 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
@@ -24,7 +25,7 @@
|
||||
* network protocol versioning
|
||||
*/
|
||||
|
||||
static const int PROTOCOL_VERSION = 170008;
|
||||
static const int PROTOCOL_VERSION = 170009;
|
||||
|
||||
//! initial proto version, to be increased after version/verack negotiation
|
||||
static const int INIT_PROTO_VERSION = 209;
|
||||
|
||||
@@ -200,7 +200,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
"2. \"label\" (string, optional, default=\"\") An optional label\n"
|
||||
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
|
||||
"4. height (integer, optional, default=0) start at block height?\n"
|
||||
"5. secret_key (integer, optional, default=188) used to import WIFs of other coins\n"
|
||||
"5. secret_key (integer, optional, default=188) decimal value used to import WIFs of other coins\n"
|
||||
"\nNote: This call can take minutes to complete if rescan is true.\n"
|
||||
"\nExamples:\n"
|
||||
"\nDump a private key\n"
|
||||
|
||||
@@ -134,6 +134,9 @@ void zsTxSpendsToJSON(const CWalletTx& wtx, UniValue& spends, CAmount& totalSpen
|
||||
|
||||
void zsTxReceivedToJSON(const CWalletTx& wtx, UniValue& received, CAmount& totalReceived, const std::string& strAddress, bool filterByAddress) {
|
||||
|
||||
if(fZdebug)
|
||||
fprintf(stderr,"%s: txid=%s\n", __func__, wtx.GetHash().ToString().c_str() );
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
//Check address
|
||||
@@ -401,6 +404,10 @@ void zsWalletTxJSON(const CWalletTx& wtx, UniValue& ret, const std::string strAd
|
||||
|
||||
//Begin Compiling the Decrypted Transaction
|
||||
tx.push_back(Pair("txid", wtx.GetHash().ToString()));
|
||||
|
||||
if(fZdebug)
|
||||
fprintf(stderr,"%s: txid=%s\n", __func__, wtx.GetHash().ToString().c_str() );
|
||||
|
||||
if (wtx.IsCoinBase())
|
||||
{
|
||||
tx.push_back(Pair("coinbase", true));
|
||||
|
||||
@@ -72,8 +72,7 @@ using namespace libzcash;
|
||||
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
|
||||
extern std::string ASSETCHAINS_OVERRIDE_PUBKEY;
|
||||
const std::string ADDR_TYPE_SAPLING = "sapling";
|
||||
const std::string ADDR_TYPE_DONOTREMEMBER = "donotremember";
|
||||
extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
|
||||
const std::string ADDR_TYPE_AMNESIA = "amnesia";
|
||||
extern int32_t KOMODO_INSYNC;
|
||||
uint32_t komodo_segid32(char *coinaddr);
|
||||
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
|
||||
@@ -170,7 +169,6 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
|
||||
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
|
||||
entry.push_back(Pair(item.first, item.second));
|
||||
|
||||
entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx)));
|
||||
}
|
||||
|
||||
string AccountFromValue(const UniValue& value)
|
||||
@@ -3352,8 +3350,8 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey&
|
||||
|
||||
if (fHelp || params.size() > 5 || params.size() == 3)
|
||||
throw runtime_error(
|
||||
"z_listreceivedbyaddress\n"
|
||||
"\nReturns received outputs for a single address.\n"
|
||||
"z_listreceivedaddress\n"
|
||||
"\nReturns received outputs.\n"
|
||||
"\n"
|
||||
"This function only returns information on addresses with full spending keys."
|
||||
"\n"
|
||||
@@ -3411,8 +3409,8 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey&
|
||||
" }],\n"
|
||||
" },\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("z_listreceivedbyaddress", "R...")
|
||||
+ HelpExampleRpc("z_listreceivedbyaddress", "R...")
|
||||
+ HelpExampleCli("z_listreceivedaddress", "\"*\"")
|
||||
+ HelpExampleRpc("z_listreceivedaddress", "RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
@@ -3895,16 +3893,16 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk
|
||||
throw runtime_error(
|
||||
"z_getnewaddress ( type )\n"
|
||||
"\nReturns a new shielded address for receiving payments.\n"
|
||||
"\nWith no arguments, returns a Sapling address.\n"
|
||||
"\nBe very careful with 'donotremember' address type, the extended spending key (xsk) of that address is not stored in wallet.dat!\n"
|
||||
"\nWith no arguments, returns a Sapling address (zaddr).\n"
|
||||
"\nBe very careful with 'amnesia' address type, the address is not stored in wallet.dat and if you send funds to it THEY WILL BE LOST FOREVER\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"type\" (string, optional, default=\"" + defaultType + "\") The type of address. Either "+ ADDR_TYPE_SAPLING + " or " + ADDR_TYPE_DONOTREMEMBER + " .\n"
|
||||
"1. \"type\" (string, optional, default=\"" + defaultType + "\") The type of address. Either "+ ADDR_TYPE_SAPLING + " or " + ADDR_TYPE_AMNESIA + " .\n"
|
||||
"\nResult:\n"
|
||||
"\"" + strprintf("%s",komodo_chainname()) + "_address\" (string) The new shielded address.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("z_getnewaddress", "")
|
||||
+ HelpExampleCli("z_getnewaddress", ADDR_TYPE_SAPLING)
|
||||
+ HelpExampleCli("z_getnewaddress", ADDR_TYPE_DONOTREMEMBER)
|
||||
+ HelpExampleCli("z_getnewaddress", ADDR_TYPE_AMNESIA)
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
@@ -3917,15 +3915,14 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk
|
||||
}
|
||||
if (addrType == ADDR_TYPE_SAPLING) {
|
||||
return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
|
||||
} else if (addrType == ADDR_TYPE_DONOTREMEMBER) {
|
||||
bool addToWallet = false;
|
||||
auto zaddr = EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey(addToWallet));
|
||||
} else if (addrType == ADDR_TYPE_AMNESIA) {
|
||||
auto zaddr = randomSietchZaddr();
|
||||
if(fZdebug) {
|
||||
fprintf(stderr,"%s: Sietch zaddr=%s created, xsk not stored in wallet.dat!\n", __FUNCTION__, zaddr.c_str() );
|
||||
fprintf(stderr,"%s: Sietch zaddr=%s created, not stored in wallet.dat!\n", __FUNCTION__, zaddr.c_str() );
|
||||
}
|
||||
return zaddr;
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type! Try " + ADDR_TYPE_SAPLING + " or " + ADDR_TYPE_DONOTREMEMBER);
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type! Try " + ADDR_TYPE_SAPLING + " or " + ADDR_TYPE_AMNESIA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4086,7 +4083,8 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubK
|
||||
" \"txid\": xxxxx, (string) the transaction id\n"
|
||||
" \"amount\": xxxxx, (numeric) the amount of value in the note\n"
|
||||
" \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n"
|
||||
" \"confirmations\" : n, (numeric) the number of confirmations\n"
|
||||
" \"confirmations\" : n, (numeric) the number of notarized confirmations (dpowconfs)\n"
|
||||
" \"rawconfirmations\" : n, (numeric) the number of raw confirmations\n"
|
||||
" \"outindex\" (sapling) : n, (numeric) the output index\n"
|
||||
" \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
|
||||
"}\n"
|
||||
@@ -4131,7 +4129,6 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubK
|
||||
if (boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
|
||||
for (SaplingNoteEntry & entry : saplingEntries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
||||
int nHeight = tx_height(entry.op.hash);
|
||||
int dpowconfs = komodo_dpowconfs(nHeight, entry.confirmations);
|
||||
// Only return notarized results when minconf>1
|
||||
@@ -4152,6 +4149,10 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubK
|
||||
}
|
||||
obj.push_back(Pair("outindex", (int)entry.op.n));
|
||||
obj.push_back(Pair("rawconfirmations", entry.confirmations));
|
||||
auto wtx = pwalletMain->mapWallet.at(entry.op.hash); //.ToString());
|
||||
//fprintf(stderr,"%s: txid=%s not found in wallet!\n", __func__, entry.op.hash.ToString().c_str());
|
||||
obj.push_back(Pair("time", wtx.GetTxTime()));
|
||||
|
||||
obj.push_back(Pair("confirmations", dpowconfs));
|
||||
if (hasSpendingKey) {
|
||||
obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op)));
|
||||
@@ -4740,24 +4741,22 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
// End goal is to have this be as large as possible without slowing xtns down too much
|
||||
// A value of 7 will provide much stronger linkability privacy versus pre-Sietch operations
|
||||
unsigned int DEFAULT_MIN_ZOUTS=7;
|
||||
unsigned int MAX_ZOUTS=25;
|
||||
unsigned int MAX_ZOUTS=50;
|
||||
unsigned int MIN_ZOUTS=GetArg("--sietch-min-zouts", DEFAULT_MIN_ZOUTS);
|
||||
|
||||
if((MIN_ZOUTS<3) || (MIN_ZOUTS>MAX_ZOUTS)) {
|
||||
fprintf(stderr,"%s: Sietch min zouts must be >=3 and <= 25, setting to default value of %d\n", __FUNCTION__, DEFAULT_MIN_ZOUTS );
|
||||
fprintf(stderr,"%s: Sietch min zouts must be >= 3 and <= %d, setting to default value of %d\n", __FUNCTION__, MAX_ZOUTS, DEFAULT_MIN_ZOUTS );
|
||||
MIN_ZOUTS=DEFAULT_MIN_ZOUTS;
|
||||
}
|
||||
|
||||
int nAmount = 0;
|
||||
// Dynamic Sietch zaddrs default to OFF
|
||||
bool fSietchDynamic = GetArg("--sietch-dynamic",0);
|
||||
while (zaddrRecipients.size() < MIN_ZOUTS) {
|
||||
// OK, we identify this xtn as needing privacy zdust, we must decide how much, non-deterministically
|
||||
int decider = 1 + GetRandInt(100); // random int between 1 and 100
|
||||
string zdust1, zdust2;
|
||||
|
||||
// Which zaddr we send to is non-deterministically chosen from two zpools...
|
||||
zdust1 = fSietchDynamic ? newSietchZaddr() : randomSietchZaddr();
|
||||
// Which zaddr we send to is randomly generated
|
||||
zdust1 = randomSietchZaddr();
|
||||
|
||||
// And their ordering when given to internals is also non-deterministic, which
|
||||
// helps breaks assumptions blockchain analysts may use from z_sendmany internals
|
||||
@@ -4771,7 +4770,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
|
||||
//50% chance of adding another zout
|
||||
if (decider % 2) {
|
||||
zdust2 = fSietchDynamic ? newSietchZaddr() : randomSietchZaddr();
|
||||
zdust2 = randomSietchZaddr();
|
||||
// 50% chance of adding it to the front or back since all odd numbers are 1 or 3 mod 4
|
||||
if(decider % 4 == 3) {
|
||||
zaddrRecipients.push_back( newSietchRecipient(zdust2) );
|
||||
|
||||
@@ -59,6 +59,7 @@ using namespace libzcash;
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
const char * DEFAULT_WALLET_DAT = "wallet.dat";
|
||||
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
||||
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
|
||||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
||||
@@ -668,6 +669,25 @@ void CWallet::Flush(bool shutdown)
|
||||
|
||||
bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
|
||||
{
|
||||
LogPrintf("Using wallet %s\n", walletFile);
|
||||
uiInterface.InitMessage(_("Verifying wallet..."));
|
||||
|
||||
if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) {
|
||||
boost::filesystem::path path(walletFile);
|
||||
if (path.is_absolute()) {
|
||||
if (!boost::filesystem::exists(path.parent_path())) {
|
||||
LogPrintf("Absolute path %s does not exist!", walletFile);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
boost::filesystem::path full_path = GetDataDir() / path;
|
||||
if (!boost::filesystem::exists(full_path.parent_path())) {
|
||||
LogPrintf("Relative path %s does not exist!", walletFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bitdb.Open(GetDataDir()))
|
||||
{
|
||||
// try moving the database env out of the way
|
||||
@@ -3930,6 +3950,8 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
// Track how many getdata requests our transaction gets
|
||||
mapRequestCount[wtxNew.GetHash()] = 0;
|
||||
|
||||
std::string strCmd = GetArg("-txsend", "");
|
||||
|
||||
if (fBroadcastTransactions)
|
||||
{
|
||||
// Broadcast
|
||||
@@ -3942,6 +3964,12 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||
}
|
||||
wtxNew.RelayWalletTransaction();
|
||||
}
|
||||
// If we are configured to send transactions via an
|
||||
// external service instead of broadcasting, do that
|
||||
else if (!strCmd.empty()) {
|
||||
boost::replace_all(strCmd, "%s", EncodeHexTx(wtxNew));
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ static const unsigned int DEFAULT_TX_RETENTION_LASTTX = 200;
|
||||
//Amount of transactions to delete per run while syncing
|
||||
static const int MAX_DELETE_TX_SIZE = 50000;
|
||||
|
||||
extern const char * DEFAULT_WALLET_DAT;
|
||||
|
||||
class CBlockIndex;
|
||||
class CCoinControl;
|
||||
class COutput;
|
||||
|
||||
Reference in New Issue
Block a user