From 037c8eb3a178acb34777abdfb76f3b2354bbfebd Mon Sep 17 00:00:00 2001 From: raisultan Date: Wed, 28 Aug 2024 20:04:11 +0500 Subject: [PATCH 1/5] fix stale transaction page after transaction submission --- .gitignore | 2 +- README.md | 2 +- cmd/private_key_generator/main.go | 1 + frontend/src/AddTransactionModalButton.tsx | 17 +++++++++++++---- frontend/src/TransactionsPage.tsx | 10 +++++++--- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 0566492..d4bc9b9 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,4 @@ go.work node_modules/ .DS_Store -chain_storage/ +chain_storage*/ diff --git a/README.md b/README.md index 9713743..83cd111 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ go run cmd/blockchain/main.go -address localhost:8080 -http localhost:8090 -stor go run cmd/blockchain/main.go -address localhost:8081 -peers localhost:8080 -http localhost:8091 -storage chain_storage_2 -go run cmd/blockchain/main.goo -address localhost:8082 -peers localhost:8080,localhost:8081 -http localhost:8092 -storage chain_storage_3 +go run cmd/blockchain/main.go -address localhost:8082 -peers localhost:8080,localhost:8081 -http localhost:8092 -storage chain_storage_3 ``` ### Generate private key for testing diff --git a/cmd/private_key_generator/main.go b/cmd/private_key_generator/main.go index 8330a67..2f29305 100644 --- a/cmd/private_key_generator/main.go +++ b/cmd/private_key_generator/main.go @@ -9,6 +9,7 @@ func main() { wallet := chain.Wallet{} wallet.KeyGen() fmt.Println(wallet.PrivateKey) + fmt.Println(wallet.PublicKey) t := chain.Transaction{} err := t.Sign(wallet.PrivateKey) if err != nil { diff --git a/frontend/src/AddTransactionModalButton.tsx b/frontend/src/AddTransactionModalButton.tsx index ce87017..9adff1e 100644 --- a/frontend/src/AddTransactionModalButton.tsx +++ b/frontend/src/AddTransactionModalButton.tsx @@ -12,14 +12,23 @@ import { import AddTransactionForm from './AddTransactionForm' -export default function AddTransactionsModalButton() { - const { isOpen, onOpen, onClose } = useDisclosure() +interface AddTransactionsModalButtonProps { + onClose: () => void; + } + +export default function AddTransactionsModalButton({ onClose }: AddTransactionsModalButtonProps) { + const { isOpen, onOpen, onClose: closeModal } = useDisclosure() + + const handleClose = () => { + closeModal(); + onClose(); + }; return ( <> - + @@ -39,7 +48,7 @@ export default function AddTransactionsModalButton() { - diff --git a/frontend/src/TransactionsPage.tsx b/frontend/src/TransactionsPage.tsx index e0629ad..bdd538d 100644 --- a/frontend/src/TransactionsPage.tsx +++ b/frontend/src/TransactionsPage.tsx @@ -12,17 +12,21 @@ async function fetchTransactions(): Promise { } export default function TransactionsPage({ caption }: { caption: string }) { - const { isPending, error, data } = useQuery({ + const { isPending, error, data, refetch } = useQuery({ queryKey: ["transactions"], queryFn: fetchTransactions, }); + const handleRefetch = () => { + refetch(); + }; + if (!data || !data.length) { return ( <> <>No transactions yet. - + ); @@ -34,7 +38,7 @@ export default function TransactionsPage({ caption }: { caption: string }) { <> - + ); From 21ce9d3062e32f11596de74972482cbbc766e20a Mon Sep 17 00:00:00 2001 From: raisultan Date: Wed, 28 Aug 2024 20:18:34 +0500 Subject: [PATCH 2/5] block transmission added --- api/api.go | 3 ++- chain/chain.go | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api/api.go b/api/api.go index 756da1b..11253b9 100644 --- a/api/api.go +++ b/api/api.go @@ -78,7 +78,7 @@ func (h *Handler) MineBlock(w http.ResponseWriter, r *http.Request) { h.StatusesRWLock.Lock() h.MiningStatuses[id] = MineStatusResponse{Status: StatusPending} h.StatusesRWLock.Unlock() - err := h.Blockchain.MinePendingTransactions("") + block, err := h.Blockchain.MinePendingTransactions("") if err != nil { h.StatusesRWLock.Lock() h.MiningStatuses[id] = MineStatusResponse{ @@ -89,6 +89,7 @@ func (h *Handler) MineBlock(w http.ResponseWriter, r *http.Request) { } h.StatusesRWLock.Lock() h.MiningStatuses[id] = MineStatusResponse{Status: StatusSuccessful} + go h.Node.BroadcastBlock(block) h.StatusesRWLock.Unlock() }() err := json.NewEncoder(w).Encode(MineResponse{Id: id.String()}) diff --git a/chain/chain.go b/chain/chain.go index fc7567f..b1bf828 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -273,7 +273,7 @@ func (chain *Blockchain) IsValid() bool { return true } -func (chain *Blockchain) MinePendingTransactions(minerAddress string) error { +func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, error) { currentPoolSize := len(chain.PendingTransactions) var transactions []Transaction @@ -306,9 +306,9 @@ func (chain *Blockchain) MinePendingTransactions(minerAddress string) error { chain.AddBlock(block) err := chain.Storage.AddBlock(block) if err != nil { - return err + return Block{}, err } - return nil + return block, nil } type Storage interface { From b1ea8757d64cf47e844fc062805ea3e075d33d6b Mon Sep 17 00:00:00 2001 From: raisultan Date: Wed, 28 Aug 2024 20:41:46 +0500 Subject: [PATCH 3/5] check emptiness of the pool when adding transaction --- api/api.go | 1 + chain/chain.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/api/api.go b/api/api.go index 11253b9..583fc14 100644 --- a/api/api.go +++ b/api/api.go @@ -86,6 +86,7 @@ func (h *Handler) MineBlock(w http.ResponseWriter, r *http.Request) { Details: fmt.Sprintf("Error: %v", err), } h.StatusesRWLock.Unlock() + return } h.StatusesRWLock.Lock() h.MiningStatuses[id] = MineStatusResponse{Status: StatusSuccessful} diff --git a/chain/chain.go b/chain/chain.go index b1bf828..92626ca 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -275,6 +275,10 @@ func (chain *Blockchain) IsValid() bool { func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, error) { currentPoolSize := len(chain.PendingTransactions) + if currentPoolSize == 0 { + return Block{}, errors.New("Transaction pool is empty") + } + var transactions []Transaction if currentPoolSize < chain.MaxBlockSize { From 6ce00a92e6be7f13eacc77f19ffaacf79c0ca8e4 Mon Sep 17 00:00:00 2001 From: raisultan Date: Sat, 31 Aug 2024 14:40:08 +0500 Subject: [PATCH 4/5] add sync with storage on transaction removal by mining --- chain/chain.go | 4 ++++ storage/badger.go | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/chain/chain.go b/chain/chain.go index 92626ca..81698a2 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -284,9 +284,11 @@ func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, er if currentPoolSize < chain.MaxBlockSize { transactions = chain.PendingTransactions[0:currentPoolSize] chain.PendingTransactions = chain.PendingTransactions[currentPoolSize:] + chain.Storage.DequeueTransactions(currentPoolSize) } else { transactions = chain.PendingTransactions[0 : chain.MaxBlockSize-1] chain.PendingTransactions = chain.PendingTransactions[chain.MaxBlockSize-1:] + chain.Storage.DequeueTransactions(chain.MaxBlockSize - 1) } rewardTx := Transaction{ @@ -306,6 +308,7 @@ func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, er } block.Hash = block.CalculateHash() + // TODO: recover if mining failed block.MineBlock(chain.Difficulty) chain.AddBlock(block) err := chain.Storage.AddBlock(block) @@ -320,6 +323,7 @@ type Storage interface { AddBlock(b Block) error AddTransaction(t Transaction) error Reset(chain *Blockchain) error + DequeueTransactions(n int) error } func InitBlockchain(difficulty, maxBlockSize int, miningReward float64, s Storage) *Blockchain { diff --git a/storage/badger.go b/storage/badger.go index 946f0de..61b64f8 100644 --- a/storage/badger.go +++ b/storage/badger.go @@ -158,6 +158,33 @@ func (bs *Storage) AddTransaction(t chain.Transaction) error { return err } +func (bs *Storage) DequeueTransactions(n int) error { + return bs.db.Update(func(txn *badger.Txn) error { + opts := badger.DefaultIteratorOptions + opts.PrefetchValues = false + it := txn.NewIterator(opts) + defer it.Close() + + prefix := []byte(transactionPrefix) + count := 0 + + for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() { + if count >= n { + break + } + + key := it.Item().Key() + if err := txn.Delete(key); err != nil { + return err + } + + count++ + } + + return nil + }) +} + func (storage *Storage) deleteByPrefix(prefix []byte) error { deleteKeys := func(keysForDelete [][]byte) error { if err := storage.db.Update(func(txn *badger.Txn) error { From ed5836c74d382e683be41743ca77f6bf30987c05 Mon Sep 17 00:00:00 2001 From: raisultan Date: Sat, 31 Aug 2024 14:44:22 +0500 Subject: [PATCH 5/5] =?UTF-8?q?lint=20=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chain/chain.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/chain/chain.go b/chain/chain.go index 81698a2..fcfbd59 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -284,11 +284,17 @@ func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, er if currentPoolSize < chain.MaxBlockSize { transactions = chain.PendingTransactions[0:currentPoolSize] chain.PendingTransactions = chain.PendingTransactions[currentPoolSize:] - chain.Storage.DequeueTransactions(currentPoolSize) + err := chain.Storage.DequeueTransactions(currentPoolSize) + if err != nil { + fmt.Println("Could not dequeue transactions from storage") + } } else { transactions = chain.PendingTransactions[0 : chain.MaxBlockSize-1] chain.PendingTransactions = chain.PendingTransactions[chain.MaxBlockSize-1:] - chain.Storage.DequeueTransactions(chain.MaxBlockSize - 1) + err := chain.Storage.DequeueTransactions(chain.MaxBlockSize - 1) + if err != nil { + fmt.Println("Could not dequeue transactions from storage") + } } rewardTx := Transaction{ @@ -308,6 +314,7 @@ func (chain *Blockchain) MinePendingTransactions(minerAddress string) (Block, er } block.Hash = block.CalculateHash() + // TODO: sync transaction removal between nodes // TODO: recover if mining failed block.MineBlock(chain.Difficulty) chain.AddBlock(block)