Compare commits
41 Commits
coin-contr
...
flo-master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54a1b3ffb6 | ||
|
|
6fec5825b6 | ||
|
|
7467f8ecdd | ||
|
|
f087e0456d | ||
|
|
9dc768e6eb | ||
|
|
718c49811c | ||
|
|
cb22cf223e | ||
|
|
7edfcbe8c9 | ||
|
|
1893eeba7c | ||
|
|
dbf9e880ba | ||
|
|
7642a51c95 | ||
|
|
164d16ff36 | ||
|
|
844b6383c6 | ||
|
|
d6f66b8a66 | ||
|
|
38dc6b6b8f | ||
|
|
573db9c7a8 | ||
| bfbcd2af7e | |||
| 0a9c06b7e3 | |||
| 71277f3ada | |||
| aa525180f7 | |||
| 4eeff2a332 | |||
| 4cb428f926 | |||
| 2ec5baeeb7 | |||
|
|
f9b49f3a67 | ||
|
|
d34c2ce7f7 | ||
|
|
8708d4bc17 | ||
|
|
72120bff0d | ||
|
|
cba88b4c54 | ||
|
|
cbaf28e4dd | ||
|
|
ffa312c126 | ||
|
|
6af88ae751 | ||
|
|
0786249978 | ||
|
|
818b91b454 | ||
|
|
3da8e84238 | ||
|
|
0b8b8f16c6 | ||
|
|
df02b9c155 | ||
|
|
a33e124e82 | ||
|
|
2fe045194c | ||
|
|
998ac47e9a | ||
|
|
1ee6c75b74 | ||
|
|
4d3b091eb2 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -109,3 +109,8 @@ test/cache/*
|
||||
|
||||
libbitcoinconsensus.pc
|
||||
contrib/devtools/split-debug.sh
|
||||
|
||||
#IntelliJ
|
||||
*.iml
|
||||
.idea/
|
||||
|
||||
|
||||
126
README.md
126
README.md
@ -1,78 +1,3 @@
|
||||
FLO Core integration/staging tree
|
||||
=====================================
|
||||
|
||||
[](https://travis-ci.org/floblockchain/flo)
|
||||
|
||||
https://flo.cash
|
||||
|
||||
What is FLO?
|
||||
----------------
|
||||
|
||||
FLO is an experimental digital currency that enables instant payments to
|
||||
anyone, anywhere in the world. FLO uses peer-to-peer technology to operate
|
||||
with no central authority: managing transactions and issuing money are carried
|
||||
out collectively by the network. FLO Core is the name of open source
|
||||
software which enables the use of this currency.
|
||||
|
||||
For more information, as well as an immediately useable, binary version of
|
||||
the FLO Core software, see [https://flo.cash](https://flo.cash).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
FLO Core is released under the terms of the MIT license. See [COPYING](COPYING) for more
|
||||
information or see https://opensource.org/licenses/MIT.
|
||||
|
||||
Development Process
|
||||
-------------------
|
||||
|
||||
The `master` branch is regularly built and tested, but is not guaranteed to be
|
||||
completely stable. [Tags](https://github.com/floblockchain/flo/tags) are created
|
||||
regularly to indicate new official, stable release versions of FLO Core.
|
||||
|
||||
The contribution workflow is described in [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Testing and code review is the bottleneck for development; we get more pull
|
||||
requests than we can review and test on short notice. Please be patient and help out by testing
|
||||
other people's pull requests, and remember this is a security-critical project where any mistake might cost people
|
||||
lots of money.
|
||||
|
||||
### Automated Testing
|
||||
|
||||
Developers are strongly encouraged to write [unit tests](src/test/README.md) for new code, and to
|
||||
submit new unit tests for old code. Unit tests can be compiled and run
|
||||
(assuming they weren't disabled in configure) with: `make check`. Further details on running
|
||||
and extending unit tests can be found in [/src/test/README.md](/src/test/README.md).
|
||||
|
||||
There are also [regression and integration tests](/test), written
|
||||
in Python, that are run automatically on the build server.
|
||||
These tests can be run (if the [test dependencies](/test) are installed) with: `test/functional/test_runner.py`
|
||||
|
||||
The Travis CI system makes sure that every pull request is built for Windows, Linux, and OS X, and that unit/sanity tests are run automatically.
|
||||
|
||||
### Manual Quality Assurance (QA) Testing
|
||||
|
||||
Changes should be tested by somebody other than the developer who wrote the
|
||||
code. This is especially important for large or high-risk changes. It is useful
|
||||
to add a test plan to the pull request description if testing the changes is
|
||||
not straightforward.
|
||||
|
||||
Translations
|
||||
------------
|
||||
|
||||
We only accept translation fixes that are submitted through [Bitcoin Core's Transifex page](https://www.transifex.com/projects/p/bitcoin/).
|
||||
Translations are converted to FLO periodically.
|
||||
|
||||
Translations are periodically pulled from Transifex and merged into the git repository. See the
|
||||
[translation process](doc/translation_process.md) for details on how this works.
|
||||
|
||||
**Important**: We do not accept translation changes as GitHub pull requests because the next
|
||||
pull from Transifex would automatically overwrite them again.
|
||||
|
||||
Usage
|
||||
--------
|
||||
|
||||
@ -96,12 +21,56 @@ flo-tx - FLO transactions
|
||||
|
||||
4. For more details view the readme file in the extracted directory
|
||||
|
||||
### For creating Pre-compiled executable binary files from source code :
|
||||
### Compiling on Linux OS Server
|
||||
Go to **flo** directory, and execute
|
||||
|
||||
|
||||
cd depends/
|
||||
|
||||
make HOST=x86_64-linux-gnu
|
||||
|
||||
cd ..
|
||||
|
||||
./autogen.sh
|
||||
|
||||
./configure --prefix=`pwd`/depends/x86_64-linux-gnu
|
||||
|
||||
make
|
||||
|
||||
For PCs on Linux, and execute
|
||||
|
||||
|
||||
cd depends/
|
||||
|
||||
make HOST=x86_64-pc-linux-gnu
|
||||
|
||||
cd ..
|
||||
|
||||
./autogen.sh
|
||||
|
||||
./configure --prefix=`pwd`/depends/x86_64-pc-linux-gnu
|
||||
|
||||
make
|
||||
To make with debuging in GDB
|
||||
|
||||
cd depends/
|
||||
|
||||
make clean HOST=x86_64-pc-linux-gnu
|
||||
|
||||
cd ..
|
||||
|
||||
./autogen.sh
|
||||
|
||||
./configure CXXFLAGS="-O0 -ggdb3" --prefix=`pwd`/depends/x86_64-pc-linux-gnu
|
||||
|
||||
make -j $(nproc)
|
||||
|
||||
### Details: For creating Pre-compiled executable binary files from source code :
|
||||
The dependencies for creating pre-compiled binaries are present in **depends/** directory.
|
||||
|
||||
cd depends/
|
||||
|
||||
To build dependencies for the current arch/OS:
|
||||
To build dependencies for the current arch/OS (usually this gives error if architecture/OS is not specified in some versions. Better to specify arch/OS prefix explicitly):
|
||||
|
||||
make
|
||||
|
||||
@ -142,7 +111,8 @@ To enable it, add **SendChangeToBack=1** in flo.conf (or) pass **-SendChangeToBa
|
||||
|
||||
### Added Multi-Wallet support for Linux :
|
||||
Multi-wallet support allows the user to run more than 1 wallet simultaneously.
|
||||
The Multi-wallet executable file is located in **bin/Linux**
|
||||
The Multi-wallet executable file is located in **tmp/**
|
||||
Copy the executable(binary) file to the flo binary files
|
||||
To access multi-wallet run :
|
||||
|
||||
./multiWallet -create [walletName]
|
||||
|
||||
BIN
bin/linux.tar.xz
BIN
bin/linux.tar.xz
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,10 +2,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
||||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 15)
|
||||
define(_CLIENT_VERSION_REVISION, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 1)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2017)
|
||||
define(_COPYRIGHT_YEAR, 2019)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[FLO Core]])
|
||||
AC_INIT([FLO Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/floblockchain/flo/issues],[flo],[https://flo.cash/])
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "flo-linux-0.15"
|
||||
name: "flo-linux-0.15.2.1"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "trusty"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "flo-osx-0.15"
|
||||
name: "flo-osx-0.15.2.1"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "trusty"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "flo-win-0.15"
|
||||
name: "flo-win-0.15.2.1"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "trusty"
|
||||
|
||||
59
reference/readme.md
Normal file
59
reference/readme.md
Normal file
@ -0,0 +1,59 @@
|
||||
# How I started mining FLO coins using my GPU
|
||||
|
||||
To get started with GPU mining, Create an account with Suprnova.
|
||||
After registration, navigate to My Account and then click on Edit Account.
|
||||
Scroll down and update the payment address by entering your Flo Core wallet address and make sure you click on the update button.
|
||||
(Use the payment address that you got when you registered for FLO Core Wallet.
|
||||
You can find your Payment address by navigating to the receive section and clicking on the request payment option).
|
||||
|
||||
Once you’ve updated the payment option, Go to my Account and click on My Workers.
|
||||
Add a new worker and update the credentials accordingly.
|
||||
Again make sure you click on the update button once you’ve added a new worker.
|
||||
Make sure that the monitor option is enabled.
|
||||
|
||||
Now once you’ve got all the Supernova stuff figured out, it’s time to get the miner running.
|
||||
I’ve given the links to all the resources below. From there, Download GC Miner. You’ll need an application to extract the RAR file.
|
||||
I used Peazip, you. can use your preferred application. Once you’ve got it downloaded, extract the file and make sure you have it
|
||||
stored properly and safely in a specific new folder.
|
||||
|
||||
After it’s done, open the extracted file and navigate to the config file.
|
||||
Delete the config file. Once you’re done deleting it, click on the empty space present in the address
|
||||
bar and type cmd. This will open the command prompt. Now to start running the mining software executethe command:-
|
||||
|
||||
```
|
||||
cgminer — scrypt -o stratum+tcp://flo.suprnova.cc:3210 -u [workername] -p [worker_pass]
|
||||
```
|
||||
|
||||
Here “workername” and “worker_pass” refer to the credentials of the workers which we created in Supernova.
|
||||
Note that the workername should be typed in the format [your username].[worker name] and replace it accordingly.
|
||||
for example
|
||||
|
||||
```
|
||||
-u bharat01.mall01 -p duckgostack123
|
||||
```
|
||||
|
||||
Once you’ve executed the program by replacing the appropriate usernames and passwords, the process of mining will be started. and this is what it’ll look like.
|
||||
|
||||
To quit the program press q. We can’t always type in a long command so let’s create a shortcut. Create a new text file in the folder and rename it as start.bat
|
||||
edit this document in the text file and type in the same executable that we used to start the mining process.
|
||||
|
||||
```
|
||||
cgminer — scrypt -o stratum+tcp://flo.suprnova.cc:3210 -u [workername] -p [worker_pass]
|
||||
```
|
||||
|
||||
After saving the bat file, copy and paste the start.bat file to the desktop for easy access.
|
||||
|
||||
Happy mining!!
|
||||
|
||||
All the resources used:-
|
||||
|
||||
#### GC Miner:-
|
||||
(https://drive.google.com/file/d/1nNutlChYfkXFoDIE_bFVtH9YhVGWPdU9/view?usp=drive_link)
|
||||
#### Peazip download:-
|
||||
(https://peazip.github.io/index.html)
|
||||
#### Suprnova:-
|
||||
(https://flo.suprnova.cc/index.php)
|
||||
|
||||
### Written by Bhardwaj Hariharan on Medium
|
||||
For attached screenshots, read this Medium post
|
||||
(https://medium.com/@bhardhwaj01/how-i-started-mining-flo-coins-using-my-gpu-01ea0ac436eb)
|
||||
@ -102,10 +102,10 @@ public:
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1554098766; // April 1st, 2019
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000011f1db4843f05806");
|
||||
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000050b6f9f1c2494ad8"); // 3,000,000
|
||||
|
||||
// By default assume that the signatures in ancestors of this block are valid.
|
||||
consensus.defaultAssumeValid = uint256S("0x4a8cb5ca397b7c92c270ccfa9139ffb93f7c5b9515e52486c635c7a1dee9d221"); // 2000000
|
||||
consensus.defaultAssumeValid = uint256S("0x5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f"); // 3,000,000
|
||||
|
||||
// Difficulty adjustments
|
||||
consensus.nPowTargetSpacing = 40; // 40s block time
|
||||
@ -139,6 +139,7 @@ public:
|
||||
pchMessageStart[3] = 0xf1;
|
||||
nDefaultPort = 7312;
|
||||
nPruneAfterHeight = 100000;
|
||||
nNlrLimit = 100; // 100 * ~40s = ~66 minutes
|
||||
|
||||
genesis = CreateGenesisBlock(1371488396, 1000112548, 0x1e0ffff0, 1, 100 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
@ -191,15 +192,16 @@ public:
|
||||
{1796633, uint256S("0xc2da8b936a7f2c0de02aa0c6c45f3d971ebad78655255a945b0e60b62f27d445")},
|
||||
{2094558, uint256S("0x946616c88286f32bfac15868456d87a86f8611e1f9b56594b81e46831ce43f81")},
|
||||
{2532181, uint256S("0xcacd5149aaed1088ae1db997a741210b0525e941356104120f182f3159931c79")},
|
||||
{3000000, uint256S("0x5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f")},
|
||||
}
|
||||
};
|
||||
|
||||
chainTxData = ChainTxData{
|
||||
// Data as of block cacd5149aaed1088ae1db997a741210b0525e941356104120f182f3159931c79 (height 2532181).
|
||||
1515282818, // * UNIX timestamp of last known number of transactions
|
||||
3223208, // * total number of transactions between genesis and that timestamp
|
||||
// Data as of block 5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f (height 3,000,000).
|
||||
1538389345, // * UNIX timestamp of last known number of transactions
|
||||
4563023, // * total number of transactions between genesis and that timestamp
|
||||
// (the tx=... number in the SetBestChain debug.log lines)
|
||||
0.04 // * estimated number of transactions per second after that timestamp
|
||||
0.03 // * estimated number of transactions per second after that timestamp
|
||||
};
|
||||
|
||||
}
|
||||
@ -237,10 +239,10 @@ public:
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1530446401; // July 1, 2018 FLO future date
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000083540886d");
|
||||
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000003dd47d3172"); // 230,000
|
||||
|
||||
// By default assume that the signatures in ancestors of this block are valid.
|
||||
consensus.defaultAssumeValid = uint256S("0x4be79531ee8b0f410f0d8c8d785083acb4e14e5d54b0820502bc60f98a629b19"); //flo testnet block 20,000
|
||||
consensus.defaultAssumeValid = uint256S("0xc2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539"); // 230,000
|
||||
|
||||
// Difficulty adjustments
|
||||
consensus.nPowTargetSpacing = 40; // 40s block time
|
||||
@ -274,6 +276,7 @@ public:
|
||||
pchMessageStart[3] = 0xf2;
|
||||
nDefaultPort = 17312;
|
||||
nPruneAfterHeight = 100000;
|
||||
nNlrLimit = 50; // 50 * ~40s = ~33 minutes
|
||||
|
||||
genesis = CreateGenesisBlock(1371387277, 1000580675, 0x1e0ffff0, 1, 100 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
@ -303,14 +306,15 @@ public:
|
||||
checkpointData = (CCheckpointData) {
|
||||
{
|
||||
{2056, uint256S("0xd3334db071731beaa651f10624c2fea1a5e8c6f9e50f0e602f86262938374148")},
|
||||
{230000, uint256S("0xc2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539")},
|
||||
}
|
||||
};
|
||||
|
||||
chainTxData = ChainTxData{
|
||||
// flo: Data as of block 4be79531ee8b0f410f0d8c8d785083acb4e14e5d54b0820502bc60f98a629b19 (height 20000)
|
||||
1515699893, // * UNIX timestamp of last known number of transactions
|
||||
34572, // * total number of transactions between genesis and that timestamp
|
||||
0.001454897737891917 // * estimated number of transactions per second after that timestamp
|
||||
// flo: Data as of block c2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539 (height 230,000)
|
||||
1538135261, // * UNIX timestamp of last known number of transactions
|
||||
265211, // * total number of transactions between genesis and that timestamp
|
||||
0.01 // * estimated number of transactions per second after that timestamp
|
||||
};
|
||||
|
||||
}
|
||||
@ -387,6 +391,7 @@ public:
|
||||
pchMessageStart[3] = 0xda;
|
||||
nDefaultPort = 17412;
|
||||
nPruneAfterHeight = 1000;
|
||||
nNlrLimit = 10;
|
||||
|
||||
genesis = CreateGenesisBlock(1371387277, 0, 0x207fffff, 1, 100 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
|
||||
@ -63,6 +63,7 @@ public:
|
||||
const Consensus::Params& GetConsensus() const { return consensus; }
|
||||
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||
int GetDefaultPort() const { return nDefaultPort; }
|
||||
int NoLargeReorgLimit() const { return nNlrLimit; }
|
||||
|
||||
const CBlock& GenesisBlock() const { return genesis; }
|
||||
/** Default value for -checkmempool and -checkblockindex argument */
|
||||
@ -87,6 +88,7 @@ protected:
|
||||
CMessageHeader::MessageStartChars pchMessageStart;
|
||||
int nDefaultPort;
|
||||
uint64_t nPruneAfterHeight;
|
||||
int nNlrLimit;
|
||||
std::vector<CDNSSeedData> vSeeds;
|
||||
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
|
||||
std::string strNetworkID;
|
||||
|
||||
@ -58,7 +58,7 @@ class CBaseRegTestParams : public CBaseChainParams
|
||||
public:
|
||||
CBaseRegTestParams()
|
||||
{
|
||||
nRPCPort = 17313;
|
||||
nRPCPort = 17413;
|
||||
strDataDir = "regtest";
|
||||
}
|
||||
};
|
||||
|
||||
@ -157,7 +157,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
|
||||
return nSigOps;
|
||||
}
|
||||
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
||||
{
|
||||
// Basic checks that don't depend on any context
|
||||
if (tx.vin.empty())
|
||||
@ -181,14 +181,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
|
||||
}
|
||||
|
||||
// Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
|
||||
if (fCheckDuplicateInputs) {
|
||||
std::set<COutPoint> vInOutPoints;
|
||||
for (const auto& txin : tx.vin)
|
||||
{
|
||||
if (!vInOutPoints.insert(txin.prevout).second)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
// Check for duplicate inputs - note that this check is slow (no longer skipped due to CVE-2018-17144)
|
||||
std::set<COutPoint> vInOutPoints;
|
||||
for (const auto& txin : tx.vin)
|
||||
{
|
||||
if (!vInOutPoints.insert(txin.prevout).second)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
|
||||
if (tx.IsCoinBase())
|
||||
|
||||
@ -17,7 +17,7 @@ class CValidationState;
|
||||
/** Transaction validation functions */
|
||||
|
||||
/** Context-independent validity checks */
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||
|
||||
namespace Consensus {
|
||||
/**
|
||||
|
||||
@ -401,6 +401,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER));
|
||||
strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER));
|
||||
strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT));
|
||||
strUsage += HelpMessageOpt("-nlrlimit=<n>", strprintf(_("Set the limit to be considered a large reorg, -nlrlimit=0 to disable NLR mode (default: %u)"), defaultChainParams->NoLargeReorgLimit()));
|
||||
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
|
||||
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
|
||||
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG));
|
||||
|
||||
125
src/netbase.cpp
125
src/netbase.cpp
@ -185,6 +185,48 @@ struct timeval MillisToTimeval(int64_t nTimeout)
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/** SOCKS version */
|
||||
enum SOCKSVersion: uint8_t {
|
||||
SOCKS4 = 0x04,
|
||||
SOCKS5 = 0x05
|
||||
};
|
||||
|
||||
/** Values defined for METHOD in RFC1928 */
|
||||
enum SOCKS5Method: uint8_t {
|
||||
NOAUTH = 0x00, //! No authentication required
|
||||
GSSAPI = 0x01, //! GSSAPI
|
||||
USER_PASS = 0x02, //! Username/password
|
||||
NO_ACCEPTABLE = 0xff, //! No acceptable methods
|
||||
};
|
||||
|
||||
/** Values defined for CMD in RFC1928 */
|
||||
enum SOCKS5Command: uint8_t {
|
||||
CONNECT = 0x01,
|
||||
BIND = 0x02,
|
||||
UDP_ASSOCIATE = 0x03
|
||||
};
|
||||
|
||||
/** Values defined for REP in RFC1928 */
|
||||
enum SOCKS5Reply: uint8_t {
|
||||
SUCCEEDED = 0x00, //! Succeeded
|
||||
GENFAILURE = 0x01, //! General failure
|
||||
NOTALLOWED = 0x02, //! Connection not allowed by ruleset
|
||||
NETUNREACHABLE = 0x03, //! Network unreachable
|
||||
HOSTUNREACHABLE = 0x04, //! Network unreachable
|
||||
CONNREFUSED = 0x05, //! Connection refused
|
||||
TTLEXPIRED = 0x06, //! TTL expired
|
||||
CMDUNSUPPORTED = 0x07, //! Command not supported
|
||||
ATYPEUNSUPPORTED = 0x08, //! Address type not supported
|
||||
};
|
||||
|
||||
/** Values defined for ATYPE in RFC1928 */
|
||||
enum SOCKS5Atyp: uint8_t {
|
||||
IPV4 = 0x01,
|
||||
DOMAINNAME = 0x03,
|
||||
IPV6 = 0x04,
|
||||
};
|
||||
|
||||
/** Status codes that can be returned by InterruptibleRecv */
|
||||
enum class IntrRecvError {
|
||||
OK,
|
||||
Timeout,
|
||||
@ -204,7 +246,7 @@ enum class IntrRecvError {
|
||||
*
|
||||
* @note This function requires that hSocket is in non-blocking mode.
|
||||
*/
|
||||
static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, const SOCKET& hSocket)
|
||||
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
|
||||
{
|
||||
int64_t curTime = GetTimeMillis();
|
||||
int64_t endTime = curTime + timeout;
|
||||
@ -212,7 +254,7 @@ static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, cons
|
||||
// to break off in case of an interruption.
|
||||
const int64_t maxWait = 1000;
|
||||
while (len > 0 && curTime < endTime) {
|
||||
ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first
|
||||
ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
|
||||
if (ret > 0) {
|
||||
len -= ret;
|
||||
data += ret;
|
||||
@ -243,24 +285,35 @@ static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, cons
|
||||
return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
|
||||
}
|
||||
|
||||
/** Credentials for proxy authentication */
|
||||
struct ProxyCredentials
|
||||
{
|
||||
std::string username;
|
||||
std::string password;
|
||||
};
|
||||
|
||||
std::string Socks5ErrorString(int err)
|
||||
/** Convert SOCKS5 reply to a an error message */
|
||||
std::string Socks5ErrorString(uint8_t err)
|
||||
{
|
||||
switch(err) {
|
||||
case 0x01: return "general failure";
|
||||
case 0x02: return "connection not allowed";
|
||||
case 0x03: return "network unreachable";
|
||||
case 0x04: return "host unreachable";
|
||||
case 0x05: return "connection refused";
|
||||
case 0x06: return "TTL expired";
|
||||
case 0x07: return "protocol error";
|
||||
case 0x08: return "address type not supported";
|
||||
default: return "unknown";
|
||||
case SOCKS5Reply::GENFAILURE:
|
||||
return "general failure";
|
||||
case SOCKS5Reply::NOTALLOWED:
|
||||
return "connection not allowed";
|
||||
case SOCKS5Reply::NETUNREACHABLE:
|
||||
return "network unreachable";
|
||||
case SOCKS5Reply::HOSTUNREACHABLE:
|
||||
return "host unreachable";
|
||||
case SOCKS5Reply::CONNREFUSED:
|
||||
return "connection refused";
|
||||
case SOCKS5Reply::TTLEXPIRED:
|
||||
return "TTL expired";
|
||||
case SOCKS5Reply::CMDUNSUPPORTED:
|
||||
return "protocol error";
|
||||
case SOCKS5Reply::ATYPEUNSUPPORTED:
|
||||
return "address type not supported";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,34 +328,34 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
|
||||
}
|
||||
// Accepted authentication methods
|
||||
std::vector<uint8_t> vSocks5Init;
|
||||
vSocks5Init.push_back(0x05);
|
||||
vSocks5Init.push_back(SOCKSVersion::SOCKS5);
|
||||
if (auth) {
|
||||
vSocks5Init.push_back(0x02); // # METHODS
|
||||
vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
|
||||
vSocks5Init.push_back(0x02); // X'02' USERNAME/PASSWORD (RFC1929)
|
||||
vSocks5Init.push_back(0x02); // Number of methods
|
||||
vSocks5Init.push_back(SOCKS5Method::NOAUTH);
|
||||
vSocks5Init.push_back(SOCKS5Method::USER_PASS);
|
||||
} else {
|
||||
vSocks5Init.push_back(0x01); // # METHODS
|
||||
vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
|
||||
vSocks5Init.push_back(0x01); // Number of methods
|
||||
vSocks5Init.push_back(SOCKS5Method::NOAUTH);
|
||||
}
|
||||
ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
|
||||
if (ret != (ssize_t)vSocks5Init.size()) {
|
||||
CloseSocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet1[2];
|
||||
uint8_t pchRet1[2];
|
||||
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
|
||||
CloseSocket(hSocket);
|
||||
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
|
||||
return false;
|
||||
}
|
||||
if (pchRet1[0] != 0x05) {
|
||||
if (pchRet1[0] != SOCKSVersion::SOCKS5) {
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy failed to initialize");
|
||||
}
|
||||
if (pchRet1[1] == 0x02 && auth) {
|
||||
if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
|
||||
// Perform username/password authentication (as described in RFC1929)
|
||||
std::vector<uint8_t> vAuth;
|
||||
vAuth.push_back(0x01);
|
||||
vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
|
||||
if (auth->username.size() > 255 || auth->password.size() > 255)
|
||||
return error("Proxy username or password too long");
|
||||
vAuth.push_back(auth->username.size());
|
||||
@ -315,7 +368,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
|
||||
return error("Error sending authentication to proxy");
|
||||
}
|
||||
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
|
||||
char pchRetA[2];
|
||||
uint8_t pchRetA[2];
|
||||
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
|
||||
CloseSocket(hSocket);
|
||||
return error("Error reading proxy authentication response");
|
||||
@ -324,17 +377,17 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy authentication unsuccessful");
|
||||
}
|
||||
} else if (pchRet1[1] == 0x00) {
|
||||
} else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
|
||||
// Perform no authentication
|
||||
} else {
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
|
||||
}
|
||||
std::vector<uint8_t> vSocks5;
|
||||
vSocks5.push_back(0x05); // VER protocol version
|
||||
vSocks5.push_back(0x01); // CMD CONNECT
|
||||
vSocks5.push_back(0x00); // RSV Reserved
|
||||
vSocks5.push_back(0x03); // ATYP DOMAINNAME
|
||||
vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
|
||||
vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
|
||||
vSocks5.push_back(0x00); // RSV Reserved must be 0
|
||||
vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
|
||||
vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
|
||||
vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
|
||||
vSocks5.push_back((port >> 8) & 0xFF);
|
||||
@ -344,7 +397,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
|
||||
CloseSocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet2[4];
|
||||
uint8_t pchRet2[4];
|
||||
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
|
||||
CloseSocket(hSocket);
|
||||
if (recvr == IntrRecvError::Timeout) {
|
||||
@ -356,26 +409,26 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
|
||||
return error("Error while reading proxy response");
|
||||
}
|
||||
}
|
||||
if (pchRet2[0] != 0x05) {
|
||||
if (pchRet2[0] != SOCKSVersion::SOCKS5) {
|
||||
CloseSocket(hSocket);
|
||||
return error("Proxy failed to accept request");
|
||||
}
|
||||
if (pchRet2[1] != 0x00) {
|
||||
if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
|
||||
// Failures to connect to a peer that are not proxy errors
|
||||
CloseSocket(hSocket);
|
||||
LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
|
||||
return false;
|
||||
}
|
||||
if (pchRet2[2] != 0x00) {
|
||||
if (pchRet2[2] != 0x00) { // Reserved field must be 0
|
||||
CloseSocket(hSocket);
|
||||
return error("Error: malformed proxy response");
|
||||
}
|
||||
char pchRet3[256];
|
||||
uint8_t pchRet3[256];
|
||||
switch (pchRet2[3])
|
||||
{
|
||||
case 0x01: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
|
||||
case 0x04: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
|
||||
case 0x03:
|
||||
case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
|
||||
case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
|
||||
case SOCKS5Atyp::DOMAINNAME:
|
||||
{
|
||||
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
|
||||
if (recvr != IntrRecvError::OK) {
|
||||
|
||||
@ -266,8 +266,6 @@ void SendCoinsDialog::on_sendButton_clicked()
|
||||
|
||||
// prepare transaction for getting txFee earlier
|
||||
std::string floData = ui->floData->text().toStdString();
|
||||
if (!floData.empty())
|
||||
floData = "text:" + floData;
|
||||
WalletModelTransaction currentTransaction(recipients, floData);
|
||||
WalletModel::SendCoinsReturn prepareStatus;
|
||||
|
||||
|
||||
@ -1457,7 +1457,7 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
ActivateBestChain(state, Params());
|
||||
ActivateBestChain(state, Params(), std::shared_ptr<const CBlock>(), true);
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
||||
|
||||
@ -28,13 +28,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||
if (sigversion == SIGVERSION_WITNESS_V0 && !key.IsCompressed())
|
||||
return false;
|
||||
|
||||
int tempHashType = nHashType;
|
||||
if (sigversion != SIGVERSION_WITNESS_V0) {
|
||||
// Compatibility with v0.10.4 requires not signing the flo data
|
||||
// Once v0.10.4 is sufficiently fazed out this should be removed
|
||||
tempHashType |= SIGHASH_OMIT_FLO_DATA;
|
||||
}
|
||||
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, tempHashType, amount, sigversion);
|
||||
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
|
||||
if (!key.Sign(hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
|
||||
@ -2313,12 +2313,42 @@ static void PruneBlockIndexCandidates() {
|
||||
* Try to make some progress towards making pindexMostWork the active block.
|
||||
* pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork.
|
||||
*/
|
||||
static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace)
|
||||
static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace, bool reconsider)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
const CBlockIndex *pindexOldTip = chainActive.Tip();
|
||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
|
||||
|
||||
int nNlrLimit = gArgs.GetArg("-nlrlimit", Params().NoLargeReorgLimit());
|
||||
if (nNlrLimit != 0 && !reconsider && !IsInitialBlockDownload() && pindexFork != nullptr
|
||||
&& chainActive.Tip()->nHeight - pindexFork->nHeight >= nNlrLimit) {
|
||||
LogPrintf("%s: NLR triggered! current height=%d current hash=%s | fork height=%d fork hash=%s\n", __func__,
|
||||
pindexOldTip->nHeight, pindexOldTip->GetBlockHash().ToString(), pindexMostWork->nHeight,
|
||||
pindexMostWork->GetBlockHash().ToString());
|
||||
CBlockIndex *pindexWalk = pindexMostWork;
|
||||
|
||||
// mark invalid_child from tip of fork to second block of fork
|
||||
while (pindexWalk->nHeight != pindexFork->nHeight+2) {
|
||||
pindexWalk = pindexWalk->pprev;
|
||||
pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
|
||||
setDirtyBlockIndex.insert(pindexWalk);
|
||||
setBlockIndexCandidates.erase(pindexWalk);
|
||||
}
|
||||
|
||||
// mark invalid first block of fork
|
||||
pindexWalk = pindexWalk->pprev;
|
||||
pindexWalk->nStatus |= BLOCK_FAILED_VALID;
|
||||
setDirtyBlockIndex.insert(pindexWalk);
|
||||
setBlockIndexCandidates.erase(pindexWalk);
|
||||
|
||||
// sanity check
|
||||
assert(pindexWalk->pprev == pindexFork);
|
||||
|
||||
fInvalidFound = true;
|
||||
InvalidChainFound(pindexMostWork);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disconnect active blocks which are no longer in the best chain.
|
||||
bool fBlocksDisconnected = false;
|
||||
DisconnectedBlockTransactions disconnectpool;
|
||||
@ -2420,7 +2450,7 @@ static void NotifyHeaderTip() {
|
||||
* or an activated best chain. pblock is either nullptr or a pointer to a block
|
||||
* that is already loaded (to avoid loading it again from disk).
|
||||
*/
|
||||
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) {
|
||||
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock, bool reconsider) {
|
||||
// Note that while we're often called here from ProcessNewBlock, this is
|
||||
// far from a guarantee. Things in the P2P/RPC will often end up calling
|
||||
// us in the middle of ProcessNewBlock - do not assume pblock is set
|
||||
@ -2451,7 +2481,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||
|
||||
bool fInvalidFound = false;
|
||||
std::shared_ptr<const CBlock> nullBlockPtr;
|
||||
if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace))
|
||||
if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace, reconsider))
|
||||
return false;
|
||||
|
||||
if (fInvalidFound) {
|
||||
@ -2824,7 +2854,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
|
||||
|
||||
// Check transactions
|
||||
for (const auto& tx : block.vtx)
|
||||
if (!CheckTransaction(*tx, state, false))
|
||||
if (!CheckTransaction(*tx, state))
|
||||
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
|
||||
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
|
||||
|
||||
|
||||
@ -59,13 +59,13 @@ static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
|
||||
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
|
||||
static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
|
||||
/** Default for -limitancestorcount, max number of in-mempool ancestors */
|
||||
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
|
||||
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 1250;
|
||||
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
|
||||
static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
|
||||
static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 1750;
|
||||
/** Default for -limitdescendantcount, max number of in-mempool descendants */
|
||||
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
|
||||
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 1250;
|
||||
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
|
||||
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
|
||||
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 1750;
|
||||
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
|
||||
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
|
||||
/** Maximum kilobytes for transactions to store for processing during reorg */
|
||||
@ -273,7 +273,7 @@ bool IsInitialBlockDownload();
|
||||
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
|
||||
bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
|
||||
/** Find the best known block, and make it the tip of the block chain */
|
||||
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
|
||||
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>(), bool reconsider=false);
|
||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
|
||||
|
||||
/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
|
||||
|
||||
105
test/functional/nlr.py
Normal file
105
test/functional/nlr.py
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Copyright (c) Flo Developers 2013-2018
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the getchaintips RPC.
|
||||
|
||||
- introduce a network split
|
||||
- work on chains of different lengths
|
||||
- join the network together again
|
||||
- verify that getchaintips now returns two chain tips.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal
|
||||
|
||||
class GetChainTipsTest (BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.extra_args = [['-nlrlimit=0'], ['-nlrlimit=10'], ['-nlrlimit=10'], ['-nlrlimit=10']]
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test (self):
|
||||
|
||||
tips = self.nodes[0].getchaintips ()
|
||||
assert_equal (len (tips), 1)
|
||||
assert_equal (tips[0]['branchlen'], 0)
|
||||
assert_equal (tips[0]['height'], 200)
|
||||
assert_equal (tips[0]['status'], 'active')
|
||||
|
||||
# Split the network and build two chains of different lengths.
|
||||
self.split_network()
|
||||
self.nodes[0].generate(10)
|
||||
self.nodes[2].generate(20)
|
||||
self.sync_all([self.nodes[:2], self.nodes[2:]])
|
||||
|
||||
tips = self.nodes[1].getchaintips ()
|
||||
assert_equal (len (tips), 1)
|
||||
shortTip = tips[0]
|
||||
assert_equal(shortTip['branchlen'], 0)
|
||||
assert_equal(shortTip['height'], 210)
|
||||
assert_equal(tips[0]['status'], 'active')
|
||||
|
||||
tips = self.nodes[3].getchaintips ()
|
||||
assert_equal (len (tips), 1)
|
||||
longTip = tips[0]
|
||||
assert_equal (longTip['branchlen'], 0)
|
||||
assert_equal (longTip['height'], 220)
|
||||
assert_equal (tips[0]['status'], 'active')
|
||||
|
||||
# Join the network halves and check that we now have two tips
|
||||
# (at least at the nodes that previously had the short chain).
|
||||
print("pre join")
|
||||
self.join_network_no_sync ()
|
||||
time.sleep(10)
|
||||
print("post join")
|
||||
|
||||
print("node 0")
|
||||
print(self.nodes[0].getchaintips())
|
||||
print("node 1")
|
||||
print(self.nodes[1].getchaintips())
|
||||
print("node 2")
|
||||
print(self.nodes[2].getchaintips())
|
||||
|
||||
print("reconsider")
|
||||
self.nodes[1].reconsiderblock(self.nodes[2].getbestblockhash())
|
||||
self.sync_all()
|
||||
|
||||
print("node 0")
|
||||
print(self.nodes[0].getchaintips ())
|
||||
print("node 1")
|
||||
print(self.nodes[1].getchaintips ())
|
||||
print("node 2")
|
||||
print(self.nodes[2].getchaintips ())
|
||||
self.nodes[2].generate(20)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(20)
|
||||
|
||||
self.sync_all()
|
||||
|
||||
print("node 0")
|
||||
print(self.nodes[0].getchaintips ())
|
||||
print("node 1")
|
||||
print(self.nodes[1].getchaintips ())
|
||||
print("node 2")
|
||||
print(self.nodes[2].getchaintips ())
|
||||
|
||||
# tips = self.nodes[1].getchaintips ()
|
||||
# assert_equal (len (tips), 2)
|
||||
# assert_equal (tips[0], longTip)
|
||||
#
|
||||
# assert_equal (tips[1]['branchlen'], 10)
|
||||
# assert_equal (tips[1]['status'], 'valid-fork')
|
||||
# tips[1]['branchlen'] = 0
|
||||
# tips[1]['status'] = 'active'
|
||||
# assert_equal (tips[1], shortTip)
|
||||
|
||||
assert_equal(1, 3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
GetChainTipsTest().main()
|
||||
@ -310,6 +310,12 @@ class BitcoinTestFramework(object):
|
||||
connect_nodes_bi(self.nodes, 1, 2)
|
||||
self.sync_all()
|
||||
|
||||
def join_network_no_sync(self):
|
||||
"""
|
||||
Join the (previously split) network halves together. Do not wait sync.
|
||||
"""
|
||||
connect_nodes_bi(self.nodes, 1, 2)
|
||||
|
||||
def sync_all(self, node_groups=None):
|
||||
if not node_groups:
|
||||
node_groups = [self.nodes]
|
||||
|
||||
23
tmp/README.md
Normal file
23
tmp/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
FLO Core MultiWallet
|
||||
|
||||
This executable file is used to run more than 1 wallet at a same time
|
||||
|
||||
Usage:
|
||||
|
||||
./multiWallet -create [walletName]
|
||||
creates a wallet under 'walletName' if specified
|
||||
else creates wallet with name 'floxxxxxx'
|
||||
|
||||
./multiWallet <walletName> <command> [option]
|
||||
executes the command in wallet 'walletName'
|
||||
|
||||
commands:
|
||||
|
||||
flo-qt - open FLO Core Wallet
|
||||
flo-cli - run cli commands
|
||||
flod - run FLO daemon
|
||||
|
||||
for more info on each commands use option -help (or) -?
|
||||
./flo-qt -?
|
||||
./flo-cli -?
|
||||
./flod -?
|
||||
BIN
tmp/multiWallet
Normal file
BIN
tmp/multiWallet
Normal file
Binary file not shown.
81
tmp/multiWallet.py
Normal file
81
tmp/multiWallet.py
Normal file
@ -0,0 +1,81 @@
|
||||
import subprocess
|
||||
import random
|
||||
import sys
|
||||
import os
|
||||
import socket
|
||||
|
||||
|
||||
def _start():
|
||||
|
||||
if(len(sys.argv)<2):
|
||||
_help()
|
||||
print('Error : too few parameters')
|
||||
|
||||
elif(sys.argv[1] in ['-help','-?']):
|
||||
_help()
|
||||
|
||||
elif(sys.argv[1]=='-create'):
|
||||
try:
|
||||
foldername = sys.argv[2]
|
||||
except:
|
||||
rand = random.randint(1,999999)
|
||||
foldername = 'flo'+str(rand)
|
||||
print('Creating a new Wallet...')
|
||||
try:
|
||||
subprocess.call(['mkdir','-p',foldername])
|
||||
except Exception as e:
|
||||
print('Wallet Creation Failed : '+str(e))
|
||||
exit(0)
|
||||
print('Created wallet '+foldername)
|
||||
print('To use wallet : '+sys.argv[0]+' '+foldername)
|
||||
|
||||
elif(len(sys.argv)<3):
|
||||
_help()
|
||||
print('Error : too few parameters (command missing)')
|
||||
|
||||
elif(sys.argv[2] in ['flo-qt','flo-cli','flod']):
|
||||
|
||||
#use this for find ip n available port using socket instead of random port
|
||||
localip=socket.gethostbyname(socket.gethostname())
|
||||
'''
|
||||
for p in range(0, 65535):
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
if(!sock.connect_ex(('localhost', p)))
|
||||
port = p
|
||||
break;
|
||||
'''
|
||||
#localip = '0.0.0.0'
|
||||
port = str(random.randint(2000,10000))
|
||||
path=os.getcwd()
|
||||
cmd = ['./'+sys.argv[2]] + ['-conf='+path+'/'+sys.argv[1]+'/flo.conf','-datadir='+sys.argv[1],'-bind='+localip+':'+port] + sys.argv[3:]
|
||||
#print(cmd)
|
||||
subprocess.run(cmd)
|
||||
else:
|
||||
_help()
|
||||
print('Error : command '+sys.argv[2]+' not recognised')
|
||||
|
||||
def _help():
|
||||
help_data=f"""
|
||||
FLO Core MultiWallet
|
||||
|
||||
Usage:
|
||||
|
||||
{sys.argv[0]} -create [walletName]
|
||||
creates a wallet under 'walletName' if specified
|
||||
else creates wallet with name 'floxxxxxx'
|
||||
|
||||
{sys.argv[0]} <walletName> <command> [option]
|
||||
executes the command in wallet 'walletName'
|
||||
|
||||
commands:
|
||||
|
||||
flo-qt - open FLO Core Wallet
|
||||
flo-cli - run cli commands
|
||||
flod - run FLO daemon
|
||||
|
||||
for more info on each commands use option -help (or) -?
|
||||
|
||||
"""
|
||||
print(help_data)
|
||||
|
||||
_start()
|
||||
Loading…
Reference in New Issue
Block a user