From 856cec4405d241f3cafc47cf051cc2e1e0ffb0f9 Mon Sep 17 00:00:00 2001 From: Nithish Karthik Date: Fri, 12 Apr 2024 02:02:38 +0530 Subject: [PATCH] add priority queue --- src/main.go | 126 ++++++++++++++++++++++++++++-------------- src/mining/mining.go | 19 +------ src/selector.go | 41 ++++++++++++++ src/transaction/tx.go | 11 ++++ 4 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 src/selector.go diff --git a/src/main.go b/src/main.go index 2e7dfdf..d8dfb18 100644 --- a/src/main.go +++ b/src/main.go @@ -6,6 +6,8 @@ import ( "io/fs" "os" + "container/heap" + "github.com/humblenginr/btc-miner/mining" txn "github.com/humblenginr/btc-miner/transaction" "github.com/humblenginr/btc-miner/utils" @@ -29,7 +31,7 @@ func Validate(tx txn.Transaction) bool { } func LogDetailsAboutTx(tx txn.Transaction){ - txid := tx.TxHash() + txid := tx.TxHash() rev := utils.ReverseBytes(txid) fmt.Printf("Tx hex: %x\n",tx.RawHex() ) fmt.Printf("Txid: %x\n", txid) @@ -67,57 +69,99 @@ func UpdateValidTxns() { } } -var TemporaryValidTxn = []string{ - "001035505afbf143e51bd667099190943a38eee20092bb691e72eaa44992b2f7.json", - "000cb561188c762c81f76976f816829424e2af9e0e491c617b7bf41038df3d35.json", - "0018c221bca3da35128baabe412a14c95b6864b2e6f7f7a8ffdd8eb0923dec49.json", - "001e296ba3feddda174e62df57506861823b0831af983364d2c1808779b443f7.json", - "0022a52ad27796a1a2d9eddd6f4b055c097b51ad7cb8f000fe0d78b26cb71639.json", +func GetValidTxns() PriorityQueue { + pq := make(PriorityQueue, 0) + var transaction txn.Transaction + files, err := os.ReadDir(MempoolDirPath) + if err != nil { + panic(err) + } + for _, f := range files { + txnPath := fmt.Sprintf("%s/%s", MempoolDirPath, f.Name()) + byteResult, _ := os.ReadFile(txnPath) + err = json.Unmarshal(byteResult, &transaction) + if err != nil { + panic(err) + } + isValid := Validate(transaction) + err = os.MkdirAll(ValidTxnsDirPath, fs.FileMode(ValidTxnsDirPerm)) + if err != nil { + panic(err) + } + if(isValid && !transaction.Vin[0].IsCoinbase){ + priority := int(transaction.GetFeeByWeight() * 100000) + item := &Item{ + value: transaction, + priority: priority, + } + heap.Push(&pq, item) + } + } + return pq +} + + +// An Item is something we manage in a priority queue. +type Item struct { + value txn.Transaction // The value of the item; arbitrary. + priority int // The priority of the item in the queue. + // The index is needed by update and is maintained by the heap.Interface methods. + index int // The index of the item in the heap. } -var TemporaryValidTxns = []string{ - "000cb561188c762c81f76976f816829424e2af9e0e491c617b7bf41038df3d35.json", - "001035505afbf143e51bd667099190943a38eee20092bb691e72eaa44992b2f7.json", - "0018c221bca3da35128baabe412a14c95b6864b2e6f7f7a8ffdd8eb0923dec49.json", - "001e296ba3feddda174e62df57506861823b0831af983364d2c1808779b443f7.json", - "0022a52ad27796a1a2d9eddd6f4b055c097b51ad7cb8f000fe0d78b26cb71639.json", - "002f5ff2f870154b109d823bbad6fd349582d5b85ead5ce0f9f7a4a0270ce37a.json", - "0030b203ff93ff7f4c6fdabda1026a8167038dfb94985669721086df9ad4337a.json", - "00359dc6a7cf0d808eb5cf6450cf8243408395c6fa5be649f4f6c3b5a394d1b7.json", - "003d95255dacb65b0896ab1fc7d3f88d347c762d5164de45a5bea75da95c3830.json", - "004c2dec582638c26fed3d55b2fee8bbf1c2d4b70449b0a3f03faa105ad03f15.json", - "00550d2c315129f77a97d1b5f8483d1efc9e9edebbb229dcf4a87e0c988f6840.json", - "005747a8401a6ef30f3d55172fea54a4c4e940d0dcde372087aea286661e04c5.json", - "00703f54c52da70ce7a94f2f59b73c2435476eb531362adb20e78ecc159dd376.json", - "007b0fd78cdb709f83823b79fd9824bc39873632c6472f4e4d7c766f9a7e0e82.json", - "00b6d3b2d204a97a8877e34c1f3ce454cba5d299aab705e263b49328cbc683f1.json", - "00b8ffa99b973547fb665bdee70d3123f345c12664046e767777a822284fea3f.json", - "00c4387b3de5d0376b3df4db81a6016b584aad10c5aff619d15627e43ca4d697.json", - "00cd2a7549860949e9b7b1c182060ace476f5127f3ee561d72633ffaaea2b2ec.json", - "00d12b523d8b7ad90e2269767478764c243625539dc59bcd457d14ca1aa4e38c.json", - "00d7c8ddc2e75f6ba97520623390f01a910dc66a9e6a2052ee31f1b99aabdea5.json", - "00d9c01fd8722f63cc327c93e59de64395d1e6ca5861ae6b9b149b364d082352.json", +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the highest, not lowest, priority so we use greater than here. + return pq[i].priority > pq[j].priority } +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} -func SelectTransactionsFromPaths(validTxnPaths []string) []*txn.Transaction { - txnSlice := make([]*txn.Transaction, 0) +func (pq *PriorityQueue) Push(x any) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} - for _, fileName := range validTxnPaths { - var transaction txn.Transaction - txnPath := fmt.Sprintf("%s/%s", MempoolDirPath, fileName) - byteResult, _ := os.ReadFile(txnPath) - json.Unmarshal(byteResult, &transaction) - txnSlice = append(txnSlice, &transaction) - } - return txnSlice +func (pq *PriorityQueue) Pop() any { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item } -// Block Hash does not meet difficulty target +// update modifies the priority and value of an Item in the queue. +func (pq *PriorityQueue) update(item *Item, value txn.Transaction, priority int) { + item.value = value + item.priority = priority + heap.Fix(pq, item.index) +} + +func GetTop2000() []*txn.Transaction{ + pq := GetValidTxns() + var txns []*txn.Transaction + for range 2000 { + item := heap.Pop(&pq).(*Item) + txns = append(txns, &item.value) + } + return txns +} func main() { UpdateValidTxns() - txns := mining.SelectTransactionsFromFolder(ValidTxnsDirPath) + txns := GetTop2000() candidateBlock := mining.GetCandidateBlock(txns, true) mining.MineBlock(candidateBlock, OutputFilePath) } diff --git a/src/mining/mining.go b/src/mining/mining.go index 19926f6..89e76e1 100644 --- a/src/mining/mining.go +++ b/src/mining/mining.go @@ -3,10 +3,8 @@ package mining import ( "bytes" "encoding/hex" - "encoding/json" "fmt" "math/big" - "os" "time" txn "github.com/humblenginr/btc-miner/transaction" @@ -113,19 +111,4 @@ func calculateFees(txns []*txn.Transaction) int { return fees } -func SelectTransactionsFromFolder(validTxnsFolderPath string) []*txn.Transaction { - files, err := os.ReadDir(validTxnsFolderPath) - if err != nil { - panic(err) - } - txnSlice := make([]*txn.Transaction, 0) - - for _, f := range files { - var transaction txn.Transaction - txnPath := fmt.Sprintf("%s/%s", validTxnsFolderPath, f.Name()) - byteResult, _ := os.ReadFile(txnPath) - err = json.Unmarshal(byteResult, &transaction) - txnSlice = append(txnSlice, &transaction) - } - return txnSlice -} + diff --git a/src/selector.go b/src/selector.go new file mode 100644 index 0000000..43da874 --- /dev/null +++ b/src/selector.go @@ -0,0 +1,41 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + + txn "github.com/humblenginr/btc-miner/transaction" +) + + + +func SelectTransactionsFromPaths(validTxnPaths []string) []*txn.Transaction { + txnSlice := make([]*txn.Transaction, 0) + + for _, fileName := range validTxnPaths { + var transaction txn.Transaction + txnPath := fmt.Sprintf("%s/%s", MempoolDirPath, fileName) + byteResult, _ := os.ReadFile(txnPath) + json.Unmarshal(byteResult, &transaction) + txnSlice = append(txnSlice, &transaction) + } + return txnSlice +} + +func SelectTransactionsFromFolder(validTxnsFolderPath string) []*txn.Transaction { + files, err := os.ReadDir(validTxnsFolderPath) + if err != nil { + panic(err) + } + txnSlice := make([]*txn.Transaction, 0) + + for _, f := range files { + var transaction txn.Transaction + txnPath := fmt.Sprintf("%s/%s", validTxnsFolderPath, f.Name()) + byteResult, _ := os.ReadFile(txnPath) + err = json.Unmarshal(byteResult, &transaction) + txnSlice = append(txnSlice, &transaction) + } + return txnSlice +} diff --git a/src/transaction/tx.go b/src/transaction/tx.go index 34b91ba..a304dd1 100644 --- a/src/transaction/tx.go +++ b/src/transaction/tx.go @@ -165,6 +165,17 @@ func (tx *Transaction) SerializeSize() int { return n } +func (t Transaction) GetFeeByWeight() float64 { + return float64(t.GetFees())/float64(t.GetWeight()) +} + +func (t Transaction) GetWeight() int { + baseSize := t.SerializeSize() + totalSize := t.SerializeSizeWithWitness() + + return (baseSize * 3) + totalSize +} + func (t Transaction) GetFees() int { // transaction fees = input sum value - output sum value inputSum, outputSum := 0,0