lunalib 1.6.0__py3-none-any.whl → 1.6.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lunalib/core/__init__.py +14 -0
- lunalib/core/daemon.py +391 -0
- lunalib/core/p2p.py +361 -0
- lunalib/mining/__init__.py +5 -1
- lunalib/mining/cuda_manager.py +23 -28
- lunalib/mining/difficulty.py +38 -0
- lunalib/mining/miner.py +436 -45
- {lunalib-1.6.0.dist-info → lunalib-1.6.7.dist-info}/METADATA +1 -1
- {lunalib-1.6.0.dist-info → lunalib-1.6.7.dist-info}/RECORD +11 -9
- {lunalib-1.6.0.dist-info → lunalib-1.6.7.dist-info}/WHEEL +0 -0
- {lunalib-1.6.0.dist-info → lunalib-1.6.7.dist-info}/top_level.txt +0 -0
lunalib/mining/miner.py
CHANGED
|
@@ -18,6 +18,7 @@ from ..gtx.digital_bill import DigitalBill
|
|
|
18
18
|
from ..transactions.transactions import TransactionManager
|
|
19
19
|
from ..core.blockchain import BlockchainManager
|
|
20
20
|
from ..core.mempool import MempoolManager
|
|
21
|
+
from ..mining.cuda_manager import CUDAManager
|
|
21
22
|
|
|
22
23
|
class GenesisMiner:
|
|
23
24
|
"""Mines GTX Genesis bills AND regular transfer transactions with configurable difficulty"""
|
|
@@ -627,7 +628,8 @@ class GenesisMiner:
|
|
|
627
628
|
|
|
628
629
|
class Miner:
|
|
629
630
|
"""
|
|
630
|
-
|
|
631
|
+
Robust miner class that integrates with BlockchainManager, MempoolManager,
|
|
632
|
+
DifficultySystem, and security validation to mine all transaction types.
|
|
631
633
|
"""
|
|
632
634
|
|
|
633
635
|
def __init__(self, config, data_manager, mining_started_callback=None, mining_completed_callback=None, block_mined_callback=None):
|
|
@@ -642,10 +644,21 @@ class Miner:
|
|
|
642
644
|
|
|
643
645
|
self.mining_history = self.data_manager.load_mining_history()
|
|
644
646
|
|
|
645
|
-
#
|
|
647
|
+
# Initialize lunalib components
|
|
646
648
|
self.blockchain_manager = BlockchainManager(endpoint_url=config.node_url)
|
|
649
|
+
self.mempool_manager = MempoolManager([config.node_url])
|
|
647
650
|
self.difficulty_system = DifficultySystem()
|
|
648
651
|
self.cuda_manager = CUDAManager()
|
|
652
|
+
|
|
653
|
+
# Import security components
|
|
654
|
+
try:
|
|
655
|
+
from ..transactions.security import SecurityManager
|
|
656
|
+
from ..transactions.validator import TransactionValidator
|
|
657
|
+
self.security_manager = SecurityManager()
|
|
658
|
+
self.transaction_validator = TransactionValidator()
|
|
659
|
+
except ImportError:
|
|
660
|
+
self.security_manager = None
|
|
661
|
+
self.transaction_validator = None
|
|
649
662
|
|
|
650
663
|
self.current_hash = ""
|
|
651
664
|
self.current_nonce = 0
|
|
@@ -653,10 +666,419 @@ class Miner:
|
|
|
653
666
|
self.mining_thread = None
|
|
654
667
|
self.should_stop_mining = False
|
|
655
668
|
|
|
656
|
-
def
|
|
669
|
+
def mine_block(self) -> tuple[bool, str, Optional[Dict]]:
|
|
657
670
|
"""
|
|
658
|
-
|
|
671
|
+
Mine a block from the mempool with proper validation and difficulty calculation.
|
|
672
|
+
Returns: (success, message, block_data)
|
|
659
673
|
"""
|
|
674
|
+
try:
|
|
675
|
+
# Get the latest block from the blockchain
|
|
676
|
+
latest_block = self.blockchain_manager.get_latest_block()
|
|
677
|
+
if not latest_block:
|
|
678
|
+
return False, "Could not get latest block from server", None
|
|
679
|
+
|
|
680
|
+
current_index = latest_block.get('index', 0)
|
|
681
|
+
previous_hash = latest_block.get('hash', '0' * 64)
|
|
682
|
+
new_index = current_index + 1
|
|
683
|
+
|
|
684
|
+
# Get fresh transactions from mempool
|
|
685
|
+
mempool = self._get_fresh_mempool()
|
|
686
|
+
|
|
687
|
+
# Validate all transactions
|
|
688
|
+
valid_transactions = self._validate_transactions(mempool)
|
|
689
|
+
|
|
690
|
+
# If no valid transactions, create a reward transaction
|
|
691
|
+
if not valid_transactions:
|
|
692
|
+
reward_tx = self._create_empty_block_reward(new_index)
|
|
693
|
+
valid_transactions = [reward_tx]
|
|
694
|
+
|
|
695
|
+
# Calculate block difficulty based on transactions
|
|
696
|
+
block_difficulty = self._calculate_block_difficulty(valid_transactions)
|
|
697
|
+
|
|
698
|
+
# Calculate block reward using exponential difficulty system
|
|
699
|
+
total_reward = self._calculate_exponential_block_reward(block_difficulty)
|
|
700
|
+
|
|
701
|
+
# Create block data
|
|
702
|
+
block_data = {
|
|
703
|
+
'index': new_index,
|
|
704
|
+
'previous_hash': previous_hash,
|
|
705
|
+
'timestamp': time.time(),
|
|
706
|
+
'transactions': valid_transactions,
|
|
707
|
+
'miner': self.config.miner_address,
|
|
708
|
+
'difficulty': block_difficulty,
|
|
709
|
+
'nonce': 0,
|
|
710
|
+
'reward': total_reward,
|
|
711
|
+
'hash': ''
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
# Try CUDA mining first if available
|
|
715
|
+
if self.cuda_manager and self.cuda_manager.cuda_available:
|
|
716
|
+
cuda_result = self._cuda_mine(block_data, block_difficulty)
|
|
717
|
+
if cuda_result:
|
|
718
|
+
return self._finalize_block(cuda_result, 'cuda', total_reward)
|
|
719
|
+
|
|
720
|
+
# Fallback to CPU mining
|
|
721
|
+
cpu_result = self._cpu_mine(block_data, block_difficulty)
|
|
722
|
+
if cpu_result:
|
|
723
|
+
return self._finalize_block(cpu_result, 'cpu', total_reward)
|
|
724
|
+
|
|
725
|
+
return False, "Mining timeout - no solution found", None
|
|
726
|
+
|
|
727
|
+
except Exception as e:
|
|
728
|
+
return False, f"Mining error: {str(e)}", None
|
|
729
|
+
|
|
730
|
+
def _get_fresh_mempool(self) -> List[Dict]:
|
|
731
|
+
"""Get fresh mempool transactions with validation"""
|
|
732
|
+
try:
|
|
733
|
+
mempool = self.mempool_manager.get_pending_transactions()
|
|
734
|
+
if not mempool:
|
|
735
|
+
mempool = self.blockchain_manager.get_mempool()
|
|
736
|
+
return mempool if mempool else []
|
|
737
|
+
except Exception as e:
|
|
738
|
+
safe_print(f"Error fetching mempool: {e}")
|
|
739
|
+
return []
|
|
740
|
+
|
|
741
|
+
def _validate_transactions(self, transactions: List[Dict]) -> List[Dict]:
|
|
742
|
+
"""Validate transactions using security manager"""
|
|
743
|
+
valid_transactions = []
|
|
744
|
+
|
|
745
|
+
for tx in transactions:
|
|
746
|
+
try:
|
|
747
|
+
# Basic validation
|
|
748
|
+
if not self._validate_transaction_structure(tx):
|
|
749
|
+
continue
|
|
750
|
+
|
|
751
|
+
# Security validation if available
|
|
752
|
+
if self.transaction_validator:
|
|
753
|
+
if not self.transaction_validator.validate_transaction(tx):
|
|
754
|
+
continue
|
|
755
|
+
|
|
756
|
+
valid_transactions.append(tx)
|
|
757
|
+
except Exception as e:
|
|
758
|
+
safe_print(f"Transaction validation error: {e}")
|
|
759
|
+
continue
|
|
760
|
+
|
|
761
|
+
return valid_transactions
|
|
762
|
+
|
|
763
|
+
def _validate_transaction_structure(self, tx: Dict) -> bool:
|
|
764
|
+
"""Basic transaction structure validation"""
|
|
765
|
+
required_fields = ['type', 'timestamp']
|
|
766
|
+
|
|
767
|
+
for field in required_fields:
|
|
768
|
+
if field not in tx:
|
|
769
|
+
return False
|
|
770
|
+
|
|
771
|
+
tx_type = tx.get('type')
|
|
772
|
+
|
|
773
|
+
if tx_type == 'transaction':
|
|
774
|
+
if not all(k in tx for k in ['from', 'to', 'amount']):
|
|
775
|
+
return False
|
|
776
|
+
elif tx_type == 'genesis_bill':
|
|
777
|
+
if 'denomination' not in tx:
|
|
778
|
+
return False
|
|
779
|
+
elif tx_type == 'reward':
|
|
780
|
+
if not all(k in tx for k in ['to', 'amount']):
|
|
781
|
+
return False
|
|
782
|
+
|
|
783
|
+
return True
|
|
784
|
+
|
|
785
|
+
def _calculate_block_difficulty(self, transactions: List[Dict]) -> int:
|
|
786
|
+
"""Calculate block difficulty based on transactions using DifficultySystem"""
|
|
787
|
+
if not transactions:
|
|
788
|
+
return self.config.difficulty
|
|
789
|
+
|
|
790
|
+
max_difficulty = self.config.difficulty
|
|
791
|
+
|
|
792
|
+
for tx in transactions:
|
|
793
|
+
tx_type = tx.get('type')
|
|
794
|
+
|
|
795
|
+
if tx_type == 'genesis_bill':
|
|
796
|
+
denomination = tx.get('denomination', 0)
|
|
797
|
+
tx_difficulty = self.difficulty_system.get_bill_difficulty(denomination)
|
|
798
|
+
max_difficulty = max(max_difficulty, tx_difficulty)
|
|
799
|
+
elif tx_type == 'transaction':
|
|
800
|
+
amount = tx.get('amount', 0)
|
|
801
|
+
tx_difficulty = self.difficulty_system.get_transaction_difficulty(amount)
|
|
802
|
+
max_difficulty = max(max_difficulty, tx_difficulty)
|
|
803
|
+
elif tx_type == 'reward':
|
|
804
|
+
max_difficulty = max(max_difficulty, 1)
|
|
805
|
+
|
|
806
|
+
return max(max_difficulty, self.config.difficulty)
|
|
807
|
+
|
|
808
|
+
def _calculate_block_reward(self, transactions: List[Dict]) -> float:
|
|
809
|
+
"""Calculate total block reward based on transactions using DifficultySystem"""
|
|
810
|
+
total_reward = 0.0
|
|
811
|
+
|
|
812
|
+
for tx in transactions:
|
|
813
|
+
tx_type = tx.get('type')
|
|
814
|
+
|
|
815
|
+
if tx_type == 'genesis_bill':
|
|
816
|
+
denomination = tx.get('denomination', 0)
|
|
817
|
+
# Use difficulty system to calculate proper reward
|
|
818
|
+
bill_difficulty = self.difficulty_system.get_bill_difficulty(denomination)
|
|
819
|
+
avg_mining_time = 15.0 # Will be updated with actual time
|
|
820
|
+
bill_reward = self.difficulty_system.calculate_mining_reward(denomination, avg_mining_time)
|
|
821
|
+
total_reward += bill_reward
|
|
822
|
+
elif tx_type == 'transaction':
|
|
823
|
+
fee = tx.get('fee', 0)
|
|
824
|
+
total_reward += fee
|
|
825
|
+
elif tx_type == 'reward':
|
|
826
|
+
reward_amount = tx.get('amount', 0)
|
|
827
|
+
total_reward += reward_amount
|
|
828
|
+
|
|
829
|
+
# Minimum reward for empty blocks
|
|
830
|
+
if total_reward == 0:
|
|
831
|
+
total_reward = 1.0
|
|
832
|
+
|
|
833
|
+
return total_reward
|
|
834
|
+
|
|
835
|
+
def _calculate_exponential_block_reward(self, difficulty: int) -> float:
|
|
836
|
+
"""Calculate block reward using exponential difficulty system
|
|
837
|
+
|
|
838
|
+
Uses the new exponential reward system:
|
|
839
|
+
difficulty 1 = 1 LKC
|
|
840
|
+
difficulty 2 = 10 LKC
|
|
841
|
+
difficulty 3 = 100 LKC
|
|
842
|
+
difficulty 9 = 100,000,000 LKC
|
|
843
|
+
"""
|
|
844
|
+
return self.difficulty_system.calculate_block_reward(difficulty)
|
|
845
|
+
|
|
846
|
+
def _create_empty_block_reward(self, block_index: int) -> Dict:
|
|
847
|
+
"""Create reward transaction for empty blocks"""
|
|
848
|
+
return {
|
|
849
|
+
'type': 'reward',
|
|
850
|
+
'from': 'network',
|
|
851
|
+
'to': self.config.miner_address,
|
|
852
|
+
'amount': 1.0,
|
|
853
|
+
'timestamp': time.time(),
|
|
854
|
+
'block_height': block_index,
|
|
855
|
+
'hash': f"reward_{block_index}_{int(time.time())}",
|
|
856
|
+
'description': 'Empty block mining reward'
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
def _cuda_mine(self, block_data: Dict, difficulty: int) -> Optional[Dict]:
|
|
860
|
+
"""Mine using CUDA acceleration"""
|
|
861
|
+
try:
|
|
862
|
+
safe_print("Attempting CUDA mining...")
|
|
863
|
+
cuda_result = self.cuda_manager.cuda_mine_batch(
|
|
864
|
+
block_data, difficulty, batch_size=100000
|
|
865
|
+
)
|
|
866
|
+
if cuda_result and cuda_result.get('success'):
|
|
867
|
+
block_data['hash'] = cuda_result['hash']
|
|
868
|
+
block_data['nonce'] = cuda_result['nonce']
|
|
869
|
+
return block_data
|
|
870
|
+
except Exception as e:
|
|
871
|
+
safe_print(f"CUDA mining failed: {e}")
|
|
872
|
+
return None
|
|
873
|
+
|
|
874
|
+
def _cpu_mine(self, block_data: Dict, difficulty: int) -> Optional[Dict]:
|
|
875
|
+
"""Mine using CPU"""
|
|
876
|
+
safe_print("Using CPU mining...")
|
|
877
|
+
start_time = time.time()
|
|
878
|
+
target = "0" * difficulty
|
|
879
|
+
nonce = 0
|
|
880
|
+
hash_count = 0
|
|
881
|
+
last_hash_update = start_time
|
|
882
|
+
|
|
883
|
+
while not self.should_stop_mining and nonce < 1000000:
|
|
884
|
+
# Calculate block hash
|
|
885
|
+
block_hash = self._calculate_block_hash(
|
|
886
|
+
block_data['index'],
|
|
887
|
+
block_data['previous_hash'],
|
|
888
|
+
block_data['timestamp'],
|
|
889
|
+
block_data['transactions'],
|
|
890
|
+
nonce,
|
|
891
|
+
block_data['miner'],
|
|
892
|
+
difficulty
|
|
893
|
+
)
|
|
894
|
+
|
|
895
|
+
if block_hash.startswith(target):
|
|
896
|
+
block_data['hash'] = block_hash
|
|
897
|
+
block_data['nonce'] = nonce
|
|
898
|
+
return block_data
|
|
899
|
+
|
|
900
|
+
nonce += 1
|
|
901
|
+
hash_count += 1
|
|
902
|
+
self.current_nonce = nonce
|
|
903
|
+
self.current_hash = block_hash
|
|
904
|
+
|
|
905
|
+
# Update hash rate
|
|
906
|
+
current_time = time.time()
|
|
907
|
+
if current_time - last_hash_update >= 1:
|
|
908
|
+
self.hash_rate = hash_count / (current_time - last_hash_update)
|
|
909
|
+
hash_count = 0
|
|
910
|
+
last_hash_update = current_time
|
|
911
|
+
|
|
912
|
+
if nonce % 1000 == 0 and not self.is_mining:
|
|
913
|
+
return None
|
|
914
|
+
|
|
915
|
+
return None
|
|
916
|
+
|
|
917
|
+
def _calculate_block_hash(self, index: int, previous_hash: str, timestamp: float,
|
|
918
|
+
transactions: List[Dict], nonce: int, miner: str, difficulty: int) -> str:
|
|
919
|
+
"""Calculate SHA-256 hash of a block matching server validation"""
|
|
920
|
+
try:
|
|
921
|
+
block_data = {
|
|
922
|
+
"difficulty": int(difficulty),
|
|
923
|
+
"index": int(index),
|
|
924
|
+
"miner": str(miner),
|
|
925
|
+
"nonce": int(nonce),
|
|
926
|
+
"previous_hash": str(previous_hash),
|
|
927
|
+
"timestamp": float(timestamp),
|
|
928
|
+
"transactions": [], # Empty for mining proof
|
|
929
|
+
"version": "1.0"
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
block_string = json.dumps(block_data, sort_keys=True)
|
|
933
|
+
calculated_hash = hashlib.sha256(block_string.encode()).hexdigest()
|
|
934
|
+
return calculated_hash
|
|
935
|
+
|
|
936
|
+
except Exception as e:
|
|
937
|
+
safe_print(f"Hash calculation error: {e}")
|
|
938
|
+
return "0" * 64
|
|
939
|
+
|
|
940
|
+
def _finalize_block(self, block_data: Dict, method: str, total_reward: float) -> tuple[bool, str, Dict]:
|
|
941
|
+
"""Finalize mined block with proper record keeping and blockchain submission"""
|
|
942
|
+
mining_time = time.time() - block_data.get('timestamp', time.time())
|
|
943
|
+
|
|
944
|
+
# Validate block before submission
|
|
945
|
+
validation_result = self._validate_mined_block(block_data)
|
|
946
|
+
if not validation_result[0]:
|
|
947
|
+
safe_print(f"❌ Block validation failed: {validation_result[1]}")
|
|
948
|
+
return False, f"Block validation failed: {validation_result[1]}", None
|
|
949
|
+
|
|
950
|
+
# Block reward is already calculated based on difficulty (exponential system)
|
|
951
|
+
final_reward = block_data['reward']
|
|
952
|
+
|
|
953
|
+
# Submit block to blockchain
|
|
954
|
+
try:
|
|
955
|
+
submission_success = self.blockchain_manager.submit_mined_block(block_data)
|
|
956
|
+
|
|
957
|
+
if not submission_success:
|
|
958
|
+
safe_print(f"⚠️ Block #{block_data['index']} submission failed")
|
|
959
|
+
return False, f"Block #{block_data['index']} mined but submission failed", None
|
|
960
|
+
|
|
961
|
+
safe_print(f"✅ Block #{block_data['index']} submitted successfully (Reward: {final_reward} LKC)")
|
|
962
|
+
|
|
963
|
+
# Clear mined transactions from mempool
|
|
964
|
+
self._clear_transactions_from_mempool(block_data['transactions'])
|
|
965
|
+
|
|
966
|
+
except Exception as e:
|
|
967
|
+
safe_print(f"❌ Block submission error: {e}")
|
|
968
|
+
return False, f"Block submission error: {str(e)}", None
|
|
969
|
+
|
|
970
|
+
# Record mining history
|
|
971
|
+
mining_record = {
|
|
972
|
+
'block_index': block_data['index'],
|
|
973
|
+
'timestamp': time.time(),
|
|
974
|
+
'mining_time': mining_time,
|
|
975
|
+
'difficulty': block_data['difficulty'],
|
|
976
|
+
'nonce': block_data['nonce'],
|
|
977
|
+
'hash': block_data['hash'],
|
|
978
|
+
'method': method,
|
|
979
|
+
'reward': final_reward,
|
|
980
|
+
'status': 'success'
|
|
981
|
+
}
|
|
982
|
+
self.mining_history.append(mining_record)
|
|
983
|
+
self.save_mining_history()
|
|
984
|
+
|
|
985
|
+
self.blocks_mined += 1
|
|
986
|
+
self.total_reward += final_reward
|
|
987
|
+
|
|
988
|
+
if self.mining_completed_callback:
|
|
989
|
+
self.mining_completed_callback(True, f"Block #{block_data['index']} mined - Reward: {final_reward}")
|
|
990
|
+
|
|
991
|
+
if self.block_mined_callback:
|
|
992
|
+
self.block_mined_callback(block_data)
|
|
993
|
+
|
|
994
|
+
return True, f"Block #{block_data['index']} mined - Reward: {final_reward}", block_data
|
|
995
|
+
|
|
996
|
+
def _validate_mined_block(self, block: Dict) -> tuple:
|
|
997
|
+
"""Validate mined block before submission
|
|
998
|
+
|
|
999
|
+
Returns: (is_valid, error_message)
|
|
1000
|
+
"""
|
|
1001
|
+
# Validate structure
|
|
1002
|
+
is_valid, error = self.difficulty_system.validate_block_structure(block)
|
|
1003
|
+
if not is_valid:
|
|
1004
|
+
return False, error
|
|
1005
|
+
|
|
1006
|
+
# Validate hash meets difficulty
|
|
1007
|
+
block_hash = block.get('hash', '')
|
|
1008
|
+
difficulty = block.get('difficulty', 0)
|
|
1009
|
+
|
|
1010
|
+
if not self.difficulty_system.validate_block_hash(block_hash, difficulty):
|
|
1011
|
+
return False, f"Hash does not meet difficulty {difficulty} requirement"
|
|
1012
|
+
|
|
1013
|
+
# Validate previous hash (get from blockchain)
|
|
1014
|
+
try:
|
|
1015
|
+
latest_block = self.blockchain_manager.get_latest_block()
|
|
1016
|
+
if latest_block:
|
|
1017
|
+
expected_prev_hash = latest_block.get('hash', '')
|
|
1018
|
+
if block.get('previous_hash') != expected_prev_hash:
|
|
1019
|
+
return False, f"Previous hash mismatch: expected {expected_prev_hash[:16]}..., got {block.get('previous_hash', '')[:16]}..."
|
|
1020
|
+
except Exception as e:
|
|
1021
|
+
safe_print(f"⚠️ Could not validate previous hash: {e}")
|
|
1022
|
+
|
|
1023
|
+
# Validate reward matches difficulty
|
|
1024
|
+
expected_reward = self.difficulty_system.calculate_block_reward(difficulty)
|
|
1025
|
+
actual_reward = block.get('reward', 0)
|
|
1026
|
+
|
|
1027
|
+
# Allow some tolerance for floating point comparison
|
|
1028
|
+
if abs(actual_reward - expected_reward) > 0.01:
|
|
1029
|
+
return False, f"Reward mismatch: expected {expected_reward} LKC for difficulty {difficulty}, got {actual_reward} LKC"
|
|
1030
|
+
|
|
1031
|
+
safe_print(f"✅ Block validation passed: Hash meets difficulty {difficulty}, Reward: {actual_reward} LKC")
|
|
1032
|
+
return True, ""
|
|
1033
|
+
|
|
1034
|
+
def _clear_transactions_from_mempool(self, transactions: List[Dict]):
|
|
1035
|
+
"""Remove mined transactions from mempool"""
|
|
1036
|
+
try:
|
|
1037
|
+
for tx in transactions:
|
|
1038
|
+
# Skip reward transactions (they were created during mining)
|
|
1039
|
+
if tx.get('type') == 'reward' and tx.get('from') == 'network':
|
|
1040
|
+
continue
|
|
1041
|
+
|
|
1042
|
+
tx_hash = tx.get('hash')
|
|
1043
|
+
if tx_hash:
|
|
1044
|
+
# Remove from mempool manager if available
|
|
1045
|
+
try:
|
|
1046
|
+
self.mempool_manager.remove_transaction(tx_hash)
|
|
1047
|
+
except:
|
|
1048
|
+
pass # Silent fail if method doesn't exist
|
|
1049
|
+
|
|
1050
|
+
safe_print(f"🧹 Cleared {len(transactions)} transactions from mempool")
|
|
1051
|
+
|
|
1052
|
+
except Exception as e:
|
|
1053
|
+
safe_print(f"⚠️ Error clearing mempool: {e}")
|
|
1054
|
+
|
|
1055
|
+
def _calculate_final_reward(self, transactions: List[Dict], actual_mining_time: float) -> float:
|
|
1056
|
+
"""Calculate final reward using actual mining time"""
|
|
1057
|
+
total_reward = 0.0
|
|
1058
|
+
|
|
1059
|
+
for tx in transactions:
|
|
1060
|
+
tx_type = tx.get('type')
|
|
1061
|
+
|
|
1062
|
+
if tx_type == 'genesis_bill':
|
|
1063
|
+
denomination = tx.get('denomination', 0)
|
|
1064
|
+
bill_reward = self.difficulty_system.calculate_mining_reward(denomination, actual_mining_time)
|
|
1065
|
+
total_reward += bill_reward
|
|
1066
|
+
elif tx_type == 'transaction':
|
|
1067
|
+
total_reward += tx.get('fee', 0)
|
|
1068
|
+
elif tx_type == 'reward':
|
|
1069
|
+
total_reward += tx.get('amount', 0)
|
|
1070
|
+
|
|
1071
|
+
if total_reward == 0:
|
|
1072
|
+
total_reward = 1.0
|
|
1073
|
+
|
|
1074
|
+
return total_reward
|
|
1075
|
+
|
|
1076
|
+
def save_mining_history(self):
|
|
1077
|
+
"""Save mining history to storage"""
|
|
1078
|
+
self.data_manager.save_mining_history(self.mining_history)
|
|
1079
|
+
|
|
1080
|
+
def start_mining(self):
|
|
1081
|
+
"""Start the mining process"""
|
|
660
1082
|
if self.is_mining:
|
|
661
1083
|
return
|
|
662
1084
|
|
|
@@ -666,51 +1088,20 @@ class Miner:
|
|
|
666
1088
|
if self.mining_started_callback:
|
|
667
1089
|
self.mining_started_callback()
|
|
668
1090
|
|
|
669
|
-
if mining_type == 'transfer':
|
|
670
|
-
self.mine_transfers()
|
|
671
|
-
elif mining_type == 'gtx_genesis':
|
|
672
|
-
self.mine_genesis_blocks()
|
|
673
|
-
elif mining_type == 'reward':
|
|
674
|
-
self.mine_rewards()
|
|
675
|
-
else:
|
|
676
|
-
raise ValueError("Invalid mining type. Choose 'transfer', 'gtx_genesis', or 'reward'.")
|
|
677
|
-
|
|
678
1091
|
def stop_mining(self):
|
|
679
|
-
"""Stop the mining process
|
|
1092
|
+
"""Stop the mining process"""
|
|
680
1093
|
self.is_mining = False
|
|
681
1094
|
self.should_stop_mining = True
|
|
682
1095
|
if self.mining_thread and self.mining_thread.is_alive():
|
|
683
1096
|
self.mining_thread.join()
|
|
684
1097
|
|
|
685
|
-
def mine_transfers(self):
|
|
686
|
-
"""Mine transfer transactions."""
|
|
687
|
-
while self.is_mining:
|
|
688
|
-
# Fetch transactions from the mempool
|
|
689
|
-
transactions = self.mempool_manager.get_pending_transactions()
|
|
690
|
-
if not transactions:
|
|
691
|
-
continue
|
|
692
|
-
|
|
693
|
-
# Mine a block with the transactions
|
|
694
|
-
block = self.blockchain_manager.create_block(transactions)
|
|
695
|
-
self.blockchain_manager.add_block(block)
|
|
696
|
-
self.mining_stats["transfers_mined"] += 1
|
|
697
|
-
|
|
698
|
-
def mine_genesis_blocks(self):
|
|
699
|
-
"""Mine GTX genesis blocks."""
|
|
700
|
-
while self.is_mining:
|
|
701
|
-
# Create a genesis block
|
|
702
|
-
genesis_block = self.blockchain_manager.create_genesis_block()
|
|
703
|
-
self.blockchain_manager.add_block(genesis_block)
|
|
704
|
-
self.mining_stats["genesis_blocks_mined"] += 1
|
|
705
|
-
|
|
706
|
-
def mine_rewards(self):
|
|
707
|
-
"""Mine rewards."""
|
|
708
|
-
while self.is_mining:
|
|
709
|
-
# Simulate mining rewards
|
|
710
|
-
reward = self.blockchain_manager.generate_reward()
|
|
711
|
-
self.blockchain_manager.add_reward(reward)
|
|
712
|
-
self.mining_stats["rewards_mined"] += 1
|
|
713
|
-
|
|
714
1098
|
def get_mining_stats(self):
|
|
715
|
-
"""Return the current mining statistics
|
|
716
|
-
return
|
|
1099
|
+
"""Return the current mining statistics"""
|
|
1100
|
+
return {
|
|
1101
|
+
"blocks_mined": self.blocks_mined,
|
|
1102
|
+
"total_reward": self.total_reward,
|
|
1103
|
+
"current_hash": self.current_hash,
|
|
1104
|
+
"current_nonce": self.current_nonce,
|
|
1105
|
+
"hash_rate": self.hash_rate,
|
|
1106
|
+
"mining_history": len(self.mining_history)
|
|
1107
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
lunalib/__init__.py,sha256=fEvoHvfcC6ilDGQrhXaVmcdB4yDmuijxz6YZHkjbuBg,527
|
|
2
2
|
lunalib/cli.py,sha256=SyuJIhvqld-XL9ks9XFOuyqVb44qyBUbahlqE_RDVkM,524
|
|
3
3
|
lunalib/luna_lib.py,sha256=ue9Bs93xjpg7_GHSUJPKBhf8nF5YcbCIdoMIu-jDgG4,2748
|
|
4
|
-
lunalib/core/__init__.py,sha256=
|
|
4
|
+
lunalib/core/__init__.py,sha256=V86B0jI8snFIg8yCyd_Qoi2Tl6elQn_1cT-oeR6Ig3s,361
|
|
5
5
|
lunalib/core/blockchain.py,sha256=dY_zQXzT8wufrinN8rGlpDTHM_M1yejfKEIm6_s78io,36564
|
|
6
6
|
lunalib/core/crypto.py,sha256=R_f2sj7ASNnMW8Dtf2LIWTw-vCUjXD33zJPqPcPQVB8,10684
|
|
7
|
+
lunalib/core/daemon.py,sha256=h8I68axWR78I8w5eOrBBQwfTeAxGqOKKW0RtLoQ52yM,16189
|
|
7
8
|
lunalib/core/mempool.py,sha256=itYFGQEuUde0Xh6WXcEz_n8hDsNhxkEAlRQ5g_Qiygg,14845
|
|
9
|
+
lunalib/core/p2p.py,sha256=cj3dda05oL6W5oMsvJ_HT3U0qr1FL6DR-YI78k3InKg,13784
|
|
8
10
|
lunalib/core/sm2.py,sha256=Eq8Er3XQW5rYJXwaPT5vw5NoVXbSWhyuvjoG1LMo-NQ,23454
|
|
9
11
|
lunalib/core/wallet.py,sha256=RNrEI7_tsaJOLcCJoTy_lLj22bc_bJtoO7iR3C3u7Ls,57435
|
|
10
12
|
lunalib/core/wallet_manager.py,sha256=KK58hrr_xF1vZ4qI6x_BJqrs9XXh5m0XbZYnZmi9yoU,26031
|
|
@@ -13,10 +15,10 @@ lunalib/gtx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
13
15
|
lunalib/gtx/bill_registry.py,sha256=J1TivYIzmJEVQHNJrZxqOOEbUSlJs7rQIXfSA90ztL4,4333
|
|
14
16
|
lunalib/gtx/digital_bill.py,sha256=xi2d7RVBGFwDOr8ulMCgvXXebHKl9LeeW9f5H4j_P_A,10977
|
|
15
17
|
lunalib/gtx/genesis.py,sha256=dDiLz-jW0zr5WUifYo9lzsrafQGOuZ9oakv_TX6QdPg,16028
|
|
16
|
-
lunalib/mining/__init__.py,sha256=
|
|
17
|
-
lunalib/mining/cuda_manager.py,sha256=
|
|
18
|
-
lunalib/mining/difficulty.py,sha256=
|
|
19
|
-
lunalib/mining/miner.py,sha256=
|
|
18
|
+
lunalib/mining/__init__.py,sha256=kOwXt_fwjHLUvV3XxieG2LZyKMW316brXLF8V8lHBUo,193
|
|
19
|
+
lunalib/mining/cuda_manager.py,sha256=VjVx9KLhT2F1jOOhva8ioGP32oQIAciZjf1irWl1jJY,5136
|
|
20
|
+
lunalib/mining/difficulty.py,sha256=hKCtvEovb4le5Fnhz6Mm8-Cugjm_CduJnZA2aNC2eyU,5326
|
|
21
|
+
lunalib/mining/miner.py,sha256=nGzfv4oK1evDXeYyS6lzaAWc8IolFrO99F0ZucBH3Ec,47715
|
|
20
22
|
lunalib/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
23
|
lunalib/storage/cache.py,sha256=U-riY8OTzxCOpl8yvhpbU3YUysEKgrPlmhO4F4cI9FM,5352
|
|
22
24
|
lunalib/storage/database.py,sha256=2f3Ie6JnuK7L0YGtAdZt5mgj90pokneXhSQKUyvx8Pc,8219
|
|
@@ -25,7 +27,7 @@ lunalib/transactions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
25
27
|
lunalib/transactions/security.py,sha256=cQJRasJ37Z8mJo8gt0JJOb0_M9CQ0QScr67y3M_NP4Q,10309
|
|
26
28
|
lunalib/transactions/transactions.py,sha256=3PgyW8gDQwY-gAPGY_T3m7RE_9HzEIOjTf6CWCsOKFY,18151
|
|
27
29
|
lunalib/transactions/validator.py,sha256=FQ-jVjj8VoVTlq65blB_hprAwJOtpc2peYdQk_L2xmg,2730
|
|
28
|
-
lunalib-1.6.
|
|
29
|
-
lunalib-1.6.
|
|
30
|
-
lunalib-1.6.
|
|
31
|
-
lunalib-1.6.
|
|
30
|
+
lunalib-1.6.7.dist-info/METADATA,sha256=XkB0ZGSCQ8QoUy3XSv17UOPTAENS0ZrY1m_H_fBdgZU,774
|
|
31
|
+
lunalib-1.6.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
32
|
+
lunalib-1.6.7.dist-info/top_level.txt,sha256=eLcoOCtOwfvoqUu5g5CNBZB9bdhGXbTwmjuOM7i8ylw,8
|
|
33
|
+
lunalib-1.6.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|