Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The Dogecoin repo's [root README](/README.md) contains relevant information on t
### Miscellaneous
- [Assets Attribution](assets-attribution.md)
- [Files](files.md)
- [Rebooted testnet](testnet-reboot.md)
- [Fuzz-testing](fuzzing.md)
- [Reduce Traffic](reduce-traffic.md)
- [Tor Support](tor.md)
Expand Down
1 change: 1 addition & 0 deletions doc/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Chain | Data directory path
--------------|------------------------------
(default) | *path_to_datadir*`/`
`-testnet` | *path_to_datadir*`/testnet3/`
`-testnet4` | *path_to_datadir*`/testnet4/`
`-regtest` | *path_to_datadir*`/regtest/`

## Data directory layout
Expand Down
9 changes: 5 additions & 4 deletions doc/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ shibetoshi:~$ dogecoin-cli listunspent 1 9999999 '["nnJDY1xCRgWQc7vBXHUPMPsEynuZ

The `minconf` and `maxconf` parameters filter the minimum and maximum number of [confirmations](https://www.pcmag.com/encyclopedia/term/bitcoin-confirmation) of the UTXO returned.

> **Note:** The example address starts with `n` instead of `D`, because it uses [testnet](#mainnet-testnet-and-regtest).
> **Note:** Legacy testnet (`-testnet`) addresses start with `n`. Reboot testnet4 (`-testnet4`) addresses start with `T`. See [testnet-reboot.md](testnet-reboot.md).

##### createrawtransaction

Expand Down Expand Up @@ -334,11 +334,12 @@ You can see a more concrete example [here](/contrib/debian/examples/dogecoin.con

When trying out new things, for example to test your application that interacts with the Dogecoin chain, it is recommended to not use the main Dogecoin network. Multiple networks are built-in for this purpose.

**Mainnet** : The main network where real transaction operate.
**Testnet** : The test network, with peers.
**Mainnet** : The main network where real transactions operate.
**Testnet (legacy testnet3)** : The long-running public test network (`-testnet`, `n` addresses, datadir `testnet3/`).
**Testnet4 (rebooted)** : Fresh test network with `T` addresses and strict min-difficulty rules (`-testnet4`, datadir `testnet4/`). See [testnet-reboot.md](testnet-reboot.md).
**Regtest** : The regression test network, to test with only local peers and create blocks on-demand.

When not specifying any network, *Mainnet* is the network used by default. To enable *testnet*, use the `dogecoind -testnet`.
When not specifying any network, *Mainnet* is the network used by default. Use `dogecoind -testnet` for legacy testnet3 or `dogecoind -testnet4` for the rebooted chain. Only one test flag may be set at a time.

To enable *regtest*, use the `-regtest` option.

Expand Down
93 changes: 93 additions & 0 deletions doc/testnet-reboot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Rebooted Dogecoin testnet (testnet4)

Dogecoin Core supports **two** public test networks. Pick one with a command-line flag; you cannot combine them in a single process.

| | Legacy testnet3 | Reboot testnet4 |
|---|-----------------|-----------------|
| **Flag** | `-testnet` | `-testnet4` |
| **Datadir** | `testnet3/` | `testnet4/` |
| **`getblockchaininfo` chain** | `test` | `testnet4` |
| **P2P magic** | `fc c1 b7 dc` | `fd d4 dc e1` |
| **P2P port** | 44556 | 44556 |
| **RPC port** | 44555 | 44555 |
| **Addresses** | `n` / `2` (legacy) | **`T`** prefix |
| **Genesis** | `bb0a7826…` | `d5d619f8…` |
| **Strict min-difficulty ([PR #3967](https://github.com/dogecoin/dogecoin/pull/3967))** | No | Yes (from block 1) |
| **Typical use** | Existing apps, historical chain | New development, fresh chain |

Both networks use the same default **P2P port (44556)** and the same **fixed seed list** from `chainparamsseeds.h`. Magic bytes differ, so nodes only peer with the chain they were started for. **Do not run both on the same machine on port 44556** unless you change `-port` on one of them.

---

## Legacy testnet3 (`-testnet`)

Unchanged behavior for existing testnet users:

```bash
dogecoind -testnet
dogecoin-cli -testnet getblockchaininfo
```

- Data: `…/testnet3/`
- Addresses from `getnewaddress` start with **`n`** (P2PKH)
- DNS seed: `testseed.jrn.me.uk`

## Reboot testnet4 (`-testnet4`)

Fresh chain with block-storm protections, aligned with DogeGo reboot testnet:

```bash
dogecoind -testnet4
dogecoin-cli -testnet4 getnewaddress
```

- Data: `…/testnet4/` (never reuse `testnet3/` blocks)
- Addresses start with **`T`**
- 10,000 DOGE block subsidy from height 1
- Digishield + strict min-difficulty from block 1
- AuxPoW from height 158100
- No DNS seeds yet; use `addnode` or run a founder node

### First node (founder)

```ini
testnet4=1
server=1
listen=1
gen=1
```

```bash
dogecoind -testnet4 -datadir=/path/to/datadir
```

### Join an existing testnet4 network

```ini
testnet4=1
addnode=FOUNDER_HOST:44556
```

Forward TCP **44556** on the founder if peers connect from the internet.

### DogeGo interoperability

DogeGo nodes with `network=testnet` use the same chain identity as Core `-testnet4` (magic, genesis, `T` addresses). Connect with `addnode` on both sides.

---

## Choosing a network

| Goal | Use |
|------|-----|
| Test against the long-running public testnet chain | `-testnet` |
| Start clean development without 30M+ legacy blocks | `-testnet4` |
| Local isolated regression tests | `-regtest` |

---

## Related docs

- [getting-started.md](getting-started.md)
- [files.md](files.md) (datadir layout)
- [PR #3967](https://github.com/dogecoin/dogecoin/pull/3967)
3 changes: 2 additions & 1 deletion qa/rpc-tests/test_framework/mininode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1636,7 +1636,8 @@ class NodeConn(asyncore.dispatcher):
}
MAGIC_BYTES = {
"mainnet": b"\xc0\xc0\xc0\xc0", # mainnet
"testnet3": b"\xfc\xc1\xb7\xdc", # testnet3
"testnet3": b"\xfc\xc1\xb7\xdc", # legacy testnet3 (-testnet)
"testnet4": b"\xfd\xd4\xdc\xe1", # rebooted testnet (-testnet4)
"regtest": b"\xfa\xbf\xb5\xda", # regtest
}

Expand Down
2 changes: 1 addition & 1 deletion src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ CAddrInfo CAddrMan::Select_(bool newOnly)

// Use a 50% chance for choosing between tried and new table entries.
if (!newOnly &&
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
// use a tried node
double fChanceFactor = 1.0;
while (1) {
Expand Down
4 changes: 2 additions & 2 deletions src/addrman.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ class CAddrInfo : public CAddress
#define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2)
#define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2)

/**
* Stochastical (IP) address manager
/**
* Stochastical (IP) address manager
*/
class CAddrMan
{
Expand Down
2 changes: 1 addition & 1 deletion src/bench/bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static void CODE_TO_TIME(benchmark::State& state)
BENCHMARK(CODE_TO_TIME);

*/

namespace benchmark {

class State {
Expand Down
2 changes: 1 addition & 1 deletion src/bloom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
const CTxOut& txout = tx.vout[i];
// Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
// If this matches, also add the specific output that was matched.
// This means clients don't have to update the filter themselves when a new relevant tx
// This means clients don't have to update the filter themselves when a new relevant tx
// is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
CScript::const_iterator pc = txout.scriptPubKey.begin();
std::vector<unsigned char> data;
Expand Down
4 changes: 2 additions & 2 deletions src/bloom.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ enum bloomflags
/**
* BloomFilter is a probabilistic filter which SPV clients provide
* so that we can filter the transactions we send them.
*
*
* This allows for significantly more efficient transaction and block downloads.
*
*
* Because bloom filters are probabilistic, a SPV node can increase the false-
* positive rate, making us send it transactions which aren't actually its,
* allowing clients to trade more bandwidth for more privacy by obfuscating which
Expand Down
137 changes: 136 additions & 1 deletion src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class CMainParams : public CChainParams {
static CMainParams mainParams;

/**
* Testnet (v3)
* Testnet (v3, legacy)
*/
class CTestNetParams : public CChainParams {
private:
Expand Down Expand Up @@ -371,6 +371,139 @@ class CTestNetParams : public CChainParams {
};
static CTestNetParams testNetParams;

/**
* Testnet4 (rebooted: new genesis + P2P magic; same default P2P port 44556 as legacy testnet.
* Uses data dir testnet4 so it does not reuse old testnet3 block files.)
*/
class CTestNet4Params : public CChainParams {
private:
Consensus::Params digishieldConsensus;
Consensus::Params auxpowConsensus;
public:
CTestNet4Params() {
strNetworkID = "testnet4";

// Blocks 0 - 144999 are pre-Digishield
consensus.nHeightEffective = 0;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.fDigishieldDifficultyCalculation = false;
consensus.nCoinbaseMaturity = 30;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowAllowDigishieldMinDifficultyBlocks = false;
consensus.fEnforceStrictMinDifficulty = false;
consensus.nSubsidyHalvingInterval = 100000;
consensus.nMajorityEnforceBlockUpgrade = 501;
consensus.nMajorityRejectBlockOutdated = 750;
consensus.nMajorityWindow = 1000;
// BIP34 is never enforced in Dogecoin v2 blocks, so we enforce from v3
consensus.BIP34Height = 708658;
consensus.BIP34Hash = uint256S("0x21b8b97dcdb94caa67c7f8f6dbf22e61e0cfe0e46e1fff3528b22864659e9b38");
consensus.BIP65Height = 1854705; // 955bd496d23790aba1ecfacb722b089a6ae7ddabaedf7d8fb0878f48308a71f9
consensus.BIP66Height = 708658; // 21b8b97dcdb94caa67c7f8f6dbf22e61e0cfe0e46e1fff3528b22864659e9b38 - this is the last block that could be v2, 1900 blocks past the last v2 block
consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.nPowTargetSpacing = 60; // 1 minute
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 2880; // 2 days (note this is significantly lower than Bitcoin standard)
consensus.nMinerConfirmationWindow = 10080; // 60 * 24 * 7 = 10,080 blocks, or one week
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008

// Deployment of BIP68, BIP112, and BIP113.
// XXX: BIP heights and hashes all need to be updated to Dogecoin values
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017

// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Disabled

// Fresh chain: no minimum work gate; raise once the network has meaningful depth.
consensus.nMinimumChainWork = uint256S("0x00");

// No deep assume-valid block yet.
consensus.defaultAssumeValid = uint256S("0x00");

// AuxPoW parameters
consensus.nAuxpowChainId = 0x0062; // 98 - Josh Wise!
consensus.fStrictChainId = false;
consensus.nHeightEffective = 0;
consensus.fAllowLegacyBlocks = true;

// Reboot testnet: Digishield + tail mainnet subsidy from block 1 (not historical 145k replay).
digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 1;
digishieldConsensus.nPowTargetTimespan = 60; // post-digishield: 1 minute
digishieldConsensus.fDigishieldDifficultyCalculation = true;
digishieldConsensus.fSimplifiedRewards = true;
digishieldConsensus.fTailSubsidyOnly = true;
digishieldConsensus.fPowAllowMinDifficultyBlocks = false;
digishieldConsensus.fPowAllowDigishieldMinDifficultyBlocks = true;
digishieldConsensus.fEnforceStrictMinDifficulty = true;
digishieldConsensus.nCoinbaseMaturity = 240;

// AuxPoW at 158100 (legacy scrypt solo mining on low heights).
auxpowConsensus = digishieldConsensus;
auxpowConsensus.nHeightEffective = 158100;
auxpowConsensus.fPowAllowDigishieldMinDifficultyBlocks = true;
auxpowConsensus.fEnforceStrictMinDifficulty = true;
auxpowConsensus.fAllowLegacyBlocks = false;

// Assemble the binary search tree of parameters (no min-difficulty middle era).
pConsensusRoot = &digishieldConsensus;
digishieldConsensus.pLeft = &consensus;
digishieldConsensus.pRight = &auxpowConsensus;

pchMessageStart[0] = 0xfd;
pchMessageStart[1] = 0xd4;
pchMessageStart[2] = 0xdc;
pchMessageStart[3] = 0xe1;
nDefaultPort = 44556;
nPruneAfterHeight = 1000;

// New genesis (same coinbase script / merkle as legacy Dogecoin testnet; new time + nonce).
genesis = CreateGenesisBlock(1747000000, 2139303, 0x1e0ffff0, 1, 88 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
assert(consensus.hashGenesisBlock == uint256S("0xd5d619f8be025d4700940883c86f271d08cffa8dd1d3d4afa474c9ed9e8b68a0"));
assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"));

vSeeds.clear();
// Add DNS seeds for this rebooted testnet when available.

// Pubkey addresses start with 'T' (version 0x41); P2SH also 'T' (0x42).
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1, 65); // 0x41
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 66); // 0x42
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1, 193); // 0x41 + 128
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x89)(0xcf).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x89)(0x94).convert_to_container<std::vector<unsigned char> >();

vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));

fMiningRequiresPeers = true;
fDefaultConsistencyChecks = false;
fRequireStandard = false;
fMineBlocksOnDemand = false;

checkpointData = (CCheckpointData) {
boost::assign::map_list_of
( 0, uint256S("0xd5d619f8be025d4700940883c86f271d08cffa8dd1d3d4afa474c9ed9e8b68a0"))
};

chainTxData = ChainTxData{
0,
0,
0
};

}
};
static CTestNet4Params testNet4Params;

/**
* Regression test
*/
Expand Down Expand Up @@ -511,6 +644,8 @@ CChainParams& Params(const std::string& chain)
return mainParams;
else if (chain == CBaseChainParams::TESTNET)
return testNetParams;
else if (chain == CBaseChainParams::TESTNET4)
return testNet4Params;
else if (chain == CBaseChainParams::REGTEST)
return regTestParams;
else
Expand Down
Loading