mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-03-04 08:15:24 +00:00
Compare commits
1 Commits
v0.0.10-te
...
v1.2.3-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71aca9c360 |
2
LICENSE
2
LICENSE
@@ -1,7 +1,7 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2018-2019 DAGLabs
|
||||
Copyright (c) 2013-2018 The btcsuite developers
|
||||
Copyright (c) 2013-20 18 The btcsuite developers
|
||||
Copyright (c) 2015-2016 The Decred developers
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
|
||||
@@ -232,8 +232,8 @@ func (node *blockNode) isGenesis() bool {
|
||||
return len(node.parents) == 0
|
||||
}
|
||||
|
||||
func (node *blockNode) finalityScore(dag *BlockDAG) uint64 {
|
||||
return node.blueScore / uint64(dag.dagParams.FinalityInterval)
|
||||
func (node *blockNode) finalityScore() uint64 {
|
||||
return node.blueScore / FinalityInterval
|
||||
}
|
||||
|
||||
// String returns a string that contains the block hash.
|
||||
|
||||
@@ -26,6 +26,9 @@ const (
|
||||
// maxOrphanBlocks is the maximum number of orphan blocks that can be
|
||||
// queued.
|
||||
maxOrphanBlocks = 100
|
||||
|
||||
// FinalityInterval is the interval that determines the finality window of the DAG.
|
||||
FinalityInterval = 100
|
||||
)
|
||||
|
||||
// orphanBlock represents a block that we don't yet have the parent for. It
|
||||
@@ -733,14 +736,14 @@ func (dag *BlockDAG) updateFinalityPoint() {
|
||||
}
|
||||
// We are looking for a new finality point only if the new block's finality score is higher
|
||||
// by 2 than the existing finality point's
|
||||
if selectedTip.finalityScore(dag) < dag.lastFinalityPoint.finalityScore(dag)+2 {
|
||||
if selectedTip.finalityScore() < dag.lastFinalityPoint.finalityScore()+2 {
|
||||
return
|
||||
}
|
||||
|
||||
var currentNode *blockNode
|
||||
for currentNode = selectedTip.selectedParent; ; currentNode = currentNode.selectedParent {
|
||||
// We look for the first node in the selected parent chain that has a higher finality score than the last finality point.
|
||||
if currentNode.selectedParent.finalityScore(dag) == dag.lastFinalityPoint.finalityScore(dag) {
|
||||
if currentNode.selectedParent.finalityScore() == dag.lastFinalityPoint.finalityScore() {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -757,7 +760,7 @@ func (dag *BlockDAG) finalizeNodesBelowFinalityPoint(deleteDiffData bool) {
|
||||
}
|
||||
var blockHashesToDelete []*daghash.Hash
|
||||
if deleteDiffData {
|
||||
blockHashesToDelete = make([]*daghash.Hash, 0, dag.dagParams.FinalityInterval)
|
||||
blockHashesToDelete = make([]*daghash.Hash, 0, FinalityInterval)
|
||||
}
|
||||
for len(queue) > 0 {
|
||||
var current *blockNode
|
||||
|
||||
@@ -1234,22 +1234,22 @@ func testFinalizeNodesBelowFinalityPoint(t *testing.T, deleteDiffData bool) {
|
||||
flushUTXODiffStore()
|
||||
return node
|
||||
}
|
||||
finalityInterval := dag.dagParams.FinalityInterval
|
||||
nodes := make([]*blockNode, 0, finalityInterval)
|
||||
|
||||
nodes := make([]*blockNode, 0, FinalityInterval)
|
||||
currentNode := dag.genesis
|
||||
nodes = append(nodes, currentNode)
|
||||
for i := 0; i <= finalityInterval*2; i++ {
|
||||
for i := 0; i <= FinalityInterval*2; i++ {
|
||||
currentNode = addNode(currentNode)
|
||||
nodes = append(nodes, currentNode)
|
||||
}
|
||||
|
||||
// Manually set the last finality point
|
||||
dag.lastFinalityPoint = nodes[finalityInterval-1]
|
||||
dag.lastFinalityPoint = nodes[FinalityInterval-1]
|
||||
|
||||
dag.finalizeNodesBelowFinalityPoint(deleteDiffData)
|
||||
flushUTXODiffStore()
|
||||
|
||||
for _, node := range nodes[:finalityInterval-1] {
|
||||
for _, node := range nodes[:FinalityInterval-1] {
|
||||
if !node.isFinalized {
|
||||
t.Errorf("Node with blue score %d expected to be finalized", node.blueScore)
|
||||
}
|
||||
@@ -1267,7 +1267,7 @@ func testFinalizeNodesBelowFinalityPoint(t *testing.T, deleteDiffData bool) {
|
||||
}
|
||||
}
|
||||
|
||||
for _, node := range nodes[finalityInterval-1:] {
|
||||
for _, node := range nodes[FinalityInterval-1:] {
|
||||
if node.isFinalized {
|
||||
t.Errorf("Node with blue score %d wasn't expected to be finalized", node.blueScore)
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ import (
|
||||
|
||||
// TestFinality checks that the finality mechanism works as expected.
|
||||
// This is how the flow goes:
|
||||
// 1) We build a chain of params.FinalityInterval blocks and call its tip altChainTip.
|
||||
// 2) We build another chain (let's call it mainChain) of 2 * params.FinalityInterval
|
||||
// 1) We build a chain of blockdag.FinalityInterval blocks and call its tip altChainTip.
|
||||
// 2) We build another chain (let's call it mainChain) of 2 * blockdag.FinalityInterval
|
||||
// blocks, which points to genesis, and then we check that the block in that
|
||||
// chain with height of params.FinalityInterval is marked as finality point (This is
|
||||
// chain with height of blockdag.FinalityInterval is marked as finality point (This is
|
||||
// very predictable, because the blue score of each new block in a chain is the
|
||||
// parents plus one).
|
||||
// 3) We make a new child to block with height (2 * params.FinalityInterval - 1)
|
||||
// 3) We make a new child to block with height (2 * blockdag.FinalityInterval - 1)
|
||||
// in mainChain, and we check that connecting it to the DAG
|
||||
// doesn't affect the last finality point.
|
||||
// 4) We make a block that points to genesis, and check that it
|
||||
@@ -38,7 +38,6 @@ import (
|
||||
func TestFinality(t *testing.T) {
|
||||
params := dagconfig.SimNetParams
|
||||
params.K = 1
|
||||
params.FinalityInterval = 100
|
||||
dag, teardownFunc, err := blockdag.DAGSetup("TestFinality", blockdag.Config{
|
||||
DAGParams: ¶ms,
|
||||
})
|
||||
@@ -71,8 +70,8 @@ func TestFinality(t *testing.T) {
|
||||
genesis := util.NewBlock(params.GenesisBlock)
|
||||
currentNode := genesis
|
||||
|
||||
// First we build a chain of params.FinalityInterval blocks for future use
|
||||
for i := 0; i < params.FinalityInterval; i++ {
|
||||
// First we build a chain of blockdag.FinalityInterval blocks for future use
|
||||
for i := 0; i < blockdag.FinalityInterval; i++ {
|
||||
currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()})
|
||||
if err != nil {
|
||||
t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err)
|
||||
@@ -81,10 +80,10 @@ func TestFinality(t *testing.T) {
|
||||
|
||||
altChainTip := currentNode
|
||||
|
||||
// Now we build a new chain of 2 * params.FinalityInterval blocks, pointed to genesis, and
|
||||
// we expect the block with height 1 * params.FinalityInterval to be the last finality point
|
||||
// Now we build a new chain of 2 * blockdag.FinalityInterval blocks, pointed to genesis, and
|
||||
// we expect the block with height 1 * blockdag.FinalityInterval to be the last finality point
|
||||
currentNode = genesis
|
||||
for i := 0; i < params.FinalityInterval; i++ {
|
||||
for i := 0; i < blockdag.FinalityInterval; i++ {
|
||||
currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()})
|
||||
if err != nil {
|
||||
t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err)
|
||||
@@ -93,7 +92,7 @@ func TestFinality(t *testing.T) {
|
||||
|
||||
expectedFinalityPoint := currentNode
|
||||
|
||||
for i := 0; i < params.FinalityInterval; i++ {
|
||||
for i := 0; i < blockdag.FinalityInterval; i++ {
|
||||
currentNode, err = buildNodeToDag([]*daghash.Hash{currentNode.Hash()})
|
||||
if err != nil {
|
||||
t.Fatalf("TestFinality: buildNodeToDag unexpectedly returned an error: %v", err)
|
||||
@@ -166,9 +165,8 @@ func TestFinality(t *testing.T) {
|
||||
// a getblocks message it should always be able to send
|
||||
// all the necessary invs.
|
||||
func TestFinalityInterval(t *testing.T) {
|
||||
params := dagconfig.SimNetParams
|
||||
if params.FinalityInterval > wire.MaxInvPerMsg {
|
||||
t.Errorf("dagconfig.SimNetParams.FinalityInterval should be lower or equal to wire.MaxInvPerMsg")
|
||||
if blockdag.FinalityInterval > wire.MaxInvPerMsg {
|
||||
t.Errorf("blockdag.FinalityInterval should be lower or equal to wire.MaxInvPerMsg")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -29,7 +28,5 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "Failed to generate p2pkh address: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Address: %s\n", addr)
|
||||
hash160 := addr.Hash160()[:]
|
||||
fmt.Printf("Hash160 of address (hex): %s\n\n", hex.EncodeToString(hash160))
|
||||
fmt.Printf("Public key: %s\n\n", addr)
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ func createTx(walletUTXOSet utxoSet, minAmount uint64, feeRate uint64, targetNum
|
||||
numOuts = maxNumOuts
|
||||
}
|
||||
|
||||
fee := calcFee(tx, feeRate, numOuts, walletUTXOSet)
|
||||
fee := calcFee(tx, feeRate, numOuts)
|
||||
funds -= fee
|
||||
|
||||
for i := uint64(0); i < numOuts; i++ {
|
||||
@@ -350,15 +350,15 @@ func fundTx(walletUTXOSet utxoSet, tx *wire.MsgTx, amount uint64, feeRate uint64
|
||||
// Add the selected output to the transaction
|
||||
tx.AddTxIn(wire.NewTxIn(&outpoint, nil))
|
||||
|
||||
// Check if transaction has enough funds. If we don't have enough
|
||||
// Check if transaction has enought funds. If we don't have enough
|
||||
// coins from he current amount selected to pay the fee, or we have
|
||||
// less inputs then the targeted amount, continue to grab more coins.
|
||||
if uint64(len(tx.TxIn)) >= targetNumberOfInputs && isFunded(tx, feeRate, targetNumberOfOutputs, amountSelected, amount, walletUTXOSet) {
|
||||
if uint64(len(tx.TxIn)) >= targetNumberOfInputs && isFunded(tx, feeRate, targetNumberOfOutputs, amountSelected, amount) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isFunded(tx, feeRate, targetNumberOfOutputs, amountSelected, amount, walletUTXOSet) {
|
||||
if !isFunded(tx, feeRate, targetNumberOfOutputs, amountSelected, amount) {
|
||||
return 0, fmt.Errorf("not enough funds for coin selection")
|
||||
}
|
||||
|
||||
@@ -367,40 +367,20 @@ func fundTx(walletUTXOSet utxoSet, tx *wire.MsgTx, amount uint64, feeRate uint64
|
||||
|
||||
// Check if the transaction has enough funds to cover the fee
|
||||
// required for the txn.
|
||||
func isFunded(tx *wire.MsgTx, feeRate uint64, targetNumberOfOutputs uint64, amountSelected uint64, targetAmount uint64, walletUTXOSet utxoSet) bool {
|
||||
reqFee := calcFee(tx, feeRate, targetNumberOfOutputs, walletUTXOSet)
|
||||
func isFunded(tx *wire.MsgTx, feeRate uint64, targetNumberOfOutputs uint64, amountSelected uint64, targetAmount uint64) bool {
|
||||
reqFee := calcFee(tx, feeRate, targetNumberOfOutputs)
|
||||
return amountSelected > reqFee && amountSelected-reqFee >= targetAmount
|
||||
}
|
||||
|
||||
func calcFee(msgTx *wire.MsgTx, feeRate uint64, numberOfOutputs uint64, walletUTXOSet utxoSet) uint64 {
|
||||
txMass := calcTxMass(msgTx, walletUTXOSet)
|
||||
txMassWithOutputs := txMass + outputsTotalSize(numberOfOutputs)
|
||||
reqFee := txMassWithOutputs * feeRate
|
||||
func calcFee(tx *wire.MsgTx, feeRate uint64, numberOfOutputs uint64) uint64 {
|
||||
txSize := uint64(tx.SerializeSize()) + spendSize*uint64(len(tx.TxIn)) + numberOfOutputs*outputSize + 1
|
||||
reqFee := uint64(txSize) * feeRate
|
||||
if reqFee < minTxFee {
|
||||
return minTxFee
|
||||
}
|
||||
return reqFee
|
||||
}
|
||||
|
||||
func outputsTotalSize(numberOfOutputs uint64) uint64 {
|
||||
return numberOfOutputs*outputSize + uint64(wire.VarIntSerializeSize(numberOfOutputs))
|
||||
}
|
||||
|
||||
func calcTxMass(msgTx *wire.MsgTx, walletUTXOSet utxoSet) uint64 {
|
||||
previousScriptPubKeys := getPreviousScriptPubKeys(msgTx, walletUTXOSet)
|
||||
return blockdag.CalcTxMass(util.NewTx(msgTx), previousScriptPubKeys)
|
||||
}
|
||||
|
||||
func getPreviousScriptPubKeys(msgTx *wire.MsgTx, walletUTXOSet utxoSet) [][]byte {
|
||||
previousScriptPubKeys := make([][]byte, len(msgTx.TxIn))
|
||||
for i, txIn := range msgTx.TxIn {
|
||||
outpoint := txIn.PreviousOutpoint
|
||||
prevOut := walletUTXOSet[outpoint]
|
||||
previousScriptPubKeys[i] = prevOut.ScriptPubKey
|
||||
}
|
||||
return previousScriptPubKeys
|
||||
}
|
||||
|
||||
func applyConfirmedTransactionsAndResendNonAccepted(client *txgenClient, walletTxs map[daghash.TxID]*walletTransaction, walletUTXOSet utxoSet,
|
||||
blockChainHeight uint64, txChan chan *wire.MsgTx) error {
|
||||
for txID, walletTx := range walletTxs {
|
||||
|
||||
@@ -137,9 +137,6 @@ type Params struct {
|
||||
// block.
|
||||
TargetTimePerBlock time.Duration
|
||||
|
||||
// FinalityInterval is the interval that determines the finality window of the DAG.
|
||||
FinalityInterval int
|
||||
|
||||
// TimestampDeviationTolerance is the maximum offset a block timestamp
|
||||
// is allowed to be in the future before it gets delayed
|
||||
TimestampDeviationTolerance uint64
|
||||
@@ -208,7 +205,6 @@ var MainNetParams = Params{
|
||||
BlockCoinbaseMaturity: 100,
|
||||
SubsidyReductionInterval: 210000,
|
||||
TargetTimePerBlock: time.Second * 1, // 1 second
|
||||
FinalityInterval: 1000,
|
||||
DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
TimestampDeviationTolerance: timestampDeviationTolerance,
|
||||
GenerateSupported: false,
|
||||
@@ -269,7 +265,6 @@ var RegressionNetParams = Params{
|
||||
BlockCoinbaseMaturity: 100,
|
||||
SubsidyReductionInterval: 150,
|
||||
TargetTimePerBlock: time.Second * 1, // 1 second
|
||||
FinalityInterval: 1000,
|
||||
DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
TimestampDeviationTolerance: timestampDeviationTolerance,
|
||||
GenerateSupported: true,
|
||||
@@ -328,7 +323,6 @@ var TestNetParams = Params{
|
||||
BlockCoinbaseMaturity: 100,
|
||||
SubsidyReductionInterval: 210000,
|
||||
TargetTimePerBlock: time.Second * 1, // 1 second
|
||||
FinalityInterval: 1000,
|
||||
DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
TimestampDeviationTolerance: timestampDeviationTolerance,
|
||||
GenerateSupported: true,
|
||||
@@ -393,7 +387,6 @@ var SimNetParams = Params{
|
||||
BlockCoinbaseMaturity: 100,
|
||||
SubsidyReductionInterval: 210000,
|
||||
TargetTimePerBlock: time.Second * 1, // 1 second
|
||||
FinalityInterval: 1000,
|
||||
DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
TimestampDeviationTolerance: timestampDeviationTolerance,
|
||||
GenerateSupported: true,
|
||||
@@ -450,7 +443,6 @@ var DevNetParams = Params{
|
||||
BlockCoinbaseMaturity: 100,
|
||||
SubsidyReductionInterval: 210000,
|
||||
TargetTimePerBlock: time.Second * 1, // 1 second
|
||||
FinalityInterval: 1000,
|
||||
DifficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
TimestampDeviationTolerance: timestampDeviationTolerance,
|
||||
GenerateSupported: true,
|
||||
|
||||
@@ -71,7 +71,7 @@ const (
|
||||
|
||||
// trickleTimeout is the duration of the ticker which trickles down the
|
||||
// inventory to a peer.
|
||||
trickleTimeout = 100 * time.Millisecond
|
||||
trickleTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
40
run-dev.sh
40
run-dev.sh
@@ -13,41 +13,27 @@ then
|
||||
echo ""
|
||||
echo -e "\t--rm\t\tRemove dockers prior to running them, to clear data"
|
||||
echo -e "\t--debug\t\tEnable debugging on second server. Server will not start until debugger is attached"
|
||||
echo -e "\t--no-build\t\tRun without building docker images"
|
||||
echo -e "\t--only-build\t\tBuild docker images without running"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ $* == *--no-build* ]] && [[ $* == *--only-build* ]]
|
||||
then
|
||||
echo "--no-build and --only-build may not be passed together"
|
||||
exit
|
||||
fi
|
||||
|
||||
export SERVICE_NAME=btcd
|
||||
export GIT_COMMIT=$(git rev-parse --short=12 HEAD)
|
||||
|
||||
if [[ $* != *--no-build* ]]
|
||||
docker build -t "${SERVICE_NAME}:${GIT_COMMIT}" . \
|
||||
-f docker/Dockerfile.dev \
|
||||
|| fatal 'Failed to build the docker image'
|
||||
docker tag "${SERVICE_NAME}:${GIT_COMMIT}" "${SERVICE_NAME}:latest"
|
||||
|
||||
cd docker
|
||||
|
||||
if [[ $* == *--rm* ]]
|
||||
then
|
||||
docker build -t "${SERVICE_NAME}:${GIT_COMMIT}" . \
|
||||
-f docker/Dockerfile.dev \
|
||||
|| fatal 'Failed to build the docker image'
|
||||
docker tag "${SERVICE_NAME}:${GIT_COMMIT}" "${SERVICE_NAME}:latest"
|
||||
docker-compose rm -f
|
||||
fi
|
||||
|
||||
if [[ $* != *--only-build* ]]
|
||||
if [[ $* == *--debug* ]]
|
||||
then
|
||||
cd docker
|
||||
|
||||
if [[ $* == *--rm* ]]
|
||||
then
|
||||
docker-compose rm -f
|
||||
fi
|
||||
|
||||
if [[ $* == *--debug* ]]
|
||||
then
|
||||
docker-compose up first second-debug
|
||||
else
|
||||
docker-compose up first second
|
||||
fi
|
||||
docker-compose up first second-debug
|
||||
else
|
||||
docker-compose up first second
|
||||
fi
|
||||
|
||||
@@ -551,7 +551,6 @@ func (s *Server) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin boo
|
||||
if parsedCmd.err != nil {
|
||||
jsonErr = parsedCmd.err
|
||||
} else {
|
||||
log.Debugf("HTTP server received command <%s> from %s", parsedCmd.method, r.RemoteAddr)
|
||||
result, jsonErr = s.standardCmdResult(parsedCmd, closeChan)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1022,7 +1022,7 @@ out:
|
||||
c.SendMessage(reply, nil)
|
||||
continue
|
||||
}
|
||||
log.Debugf("Websocket server received command <%s> from %s", cmd.method, c.addr)
|
||||
log.Debugf("Received command <%s> from %s", cmd.method, c.addr)
|
||||
|
||||
// Check auth. The client is immediately disconnected if the
|
||||
// first request of an unauthentiated websocket client is not
|
||||
|
||||
Reference in New Issue
Block a user