Explorar o código

darkfid: purge unreferenced trees after a new tx is received

skoupidi hai 4 meses
pai
achega
3356fdebd5

+ 1 - 1
bin/darkfid/src/proto/mod.rs

@@ -105,7 +105,7 @@ impl DarkfidP2pHandler {
 
         // Start the `ProtocolTx` messages handler
         let subscriber = node.subscribers.get("txs").unwrap().clone();
-        self.txs.start(executor, &node.validator, subscriber).await?;
+        self.txs.start(executor, &node.validator, &node.registry.state, subscriber).await?;
 
         // Start the P2P instance
         self.p2p.clone().start().await?;

+ 20 - 2
bin/darkfid/src/proto/protocol_tx.rs

@@ -38,6 +38,8 @@ use darkfi::{
 };
 use darkfi_serial::serialize_async;
 
+use crate::registry::DarkfiMinersRegistryStatePtr;
+
 /// Atomic pointer to the `ProtocolTx` handler.
 pub type ProtocolTxHandlerPtr = Arc<ProtocolTxHandler>;
 
@@ -66,6 +68,7 @@ impl ProtocolTxHandler {
         &self,
         executor: &ExecutorPtr,
         validator: &ValidatorPtr,
+        registry_state: &DarkfiMinersRegistryStatePtr,
         subscriber: JsonSubscriber,
     ) -> Result<()> {
         debug!(
@@ -74,7 +77,7 @@ impl ProtocolTxHandler {
         );
 
         self.handler.task.clone().start(
-            handle_receive_tx(self.handler.clone(), validator.clone(), subscriber),
+            handle_receive_tx(self.handler.clone(), validator.clone(), registry_state.clone(), subscriber),
             |res| async move {
                 match res {
                     Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
@@ -105,6 +108,7 @@ impl ProtocolTxHandler {
 async fn handle_receive_tx(
     handler: ProtocolGenericHandlerPtr<Transaction, Transaction>,
     validator: ValidatorPtr,
+    registry_state: DarkfiMinersRegistryStatePtr,
     subscriber: JsonSubscriber,
 ) -> Result<()> {
     debug!(target: "darkfid::proto::protocol_tx::handle_receive_tx", "START");
@@ -133,7 +137,21 @@ async fn handle_receive_tx(
         }
 
         // Append transaction
-        if let Err(e) = validator.append_tx(&tx, true).await {
+        let result = validator.append_tx(&tx, true).await;
+
+        // Purge all unreferenced contract trees from the database
+        if let Err(e) = validator
+            .consensus
+            .purge_unreferenced_trees(&mut registry_state.read().await.new_trees())
+            .await
+        {
+            error!(target: "darkfid::proto::protocol_tx::handle_receive_tx", "Purging unreferenced contract trees from the database failed: {e}");
+            handler.send_action(channel, ProtocolGenericAction::Skip).await;
+            continue
+        }
+
+        // Handle result
+        if let Err(e) = result {
             debug!(
                 target: "darkfid::proto::protocol_tx::handle_receive_tx",
                 "append_tx fail: {e}"

+ 42 - 7
bin/darkfid/src/rpc/tx.rs

@@ -73,7 +73,20 @@ impl DarkfiNode {
         };
 
         // Simulate state transition
-        if let Err(e) = validator.append_tx(&tx, false).await {
+        let result = validator.append_tx(&tx, false).await;
+
+        // Purge all unreferenced contract trees from the database
+        if let Err(e) = validator
+            .consensus
+            .purge_unreferenced_trees(&mut self.registry.state.read().await.new_trees())
+            .await
+        {
+            error!(target: "darkfid::rpc::tx_simulate", "Purging unreferenced contract trees from the database failed: {e}");
+            return JsonError::new(InternalError, None, id).into()
+        }
+
+        // Handle result
+        if let Err(e) = result {
             error!(target: "darkfid::rpc::tx_simulate", "Failed to validate state transition: {e}");
             return server_error(RpcError::TxSimulationFail, id, None)
         };
@@ -123,7 +136,20 @@ impl DarkfiNode {
         };
 
         // We'll perform the state transition check here.
-        if let Err(e) = validator.append_tx(&tx, true).await {
+        let result = validator.append_tx(&tx, true).await;
+
+        // Purge all unreferenced contract trees from the database
+        if let Err(e) = validator
+            .consensus
+            .purge_unreferenced_trees(&mut self.registry.state.read().await.new_trees())
+            .await
+        {
+            error!(target: "darkfid::rpc::tx_broadcast", "Purging unreferenced contract trees from the database failed: {e}");
+            return JsonError::new(InternalError, None, id).into()
+        }
+
+        // Handle result
+        if let Err(e) = result {
             error!(target: "darkfid::rpc::tx_broadcast", "Failed to append transaction to mempool: {e}");
             return server_error(RpcError::TxSimulationFail, id, None)
         };
@@ -249,11 +275,20 @@ impl DarkfiNode {
 
         // Simulate state transition
         let result = validator.calculate_fee(&tx, *include_fee).await;
-        if result.is_err() {
-            error!(
-                target: "darkfid::rpc::tx_calculate_fee", "Failed to validate state transition: {}",
-                result.err().unwrap()
-            );
+
+        // Purge all unreferenced contract trees from the database
+        if let Err(e) = validator
+            .consensus
+            .purge_unreferenced_trees(&mut self.registry.state.read().await.new_trees())
+            .await
+        {
+            error!(target: "darkfid::rpc::tx_calculate_fee", "Purging unreferenced contract trees from the database failed: {e}");
+            return JsonError::new(InternalError, None, id).into()
+        }
+
+        // Handle result
+        if let Err(e) = result {
+            error!(target: "darkfid::rpc::tx_calculate_fee", "Failed to validate state transition: {e}");
             return server_error(RpcError::TxGasCalculationFail, id, None)
         };