Просмотр исходного кода

validator: check that eta is carried as slots progress

aggstam 3 лет назад
Родитель
Сommit
490436b11e
4 измененных файлов с 35 добавлено и 14 удалено
  1. 20 5
      src/blockchain/block_store.rs
  2. 9 2
      src/blockchain/slot_store.rs
  3. 5 5
      src/validator/consensus/mod.rs
  4. 1 2
      tests/blockchain.rs

+ 20 - 5
src/blockchain/block_store.rs

@@ -16,7 +16,11 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use darkfi_sdk::{blockchain::Slot, crypto::schnorr::Signature};
+use darkfi_sdk::{
+    blockchain::Slot,
+    crypto::schnorr::Signature,
+    pasta::{group::ff::Field, pallas},
+};
 use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable};
 
 use crate::{tx::Transaction, Error, Result};
@@ -148,7 +152,14 @@ impl BlockInfo {
             // All slots exluding the last one must have reward value set to 0.
             // Slots must already be in correct order (sorted by id).
             for slot in &self.slots[..self.slots.len() - 1] {
-                validate_slot(slot, previous_slot, &previous_hash, &previous.header.previous, 0)?;
+                validate_slot(
+                    slot,
+                    previous_slot,
+                    &previous_hash,
+                    &previous.header.previous,
+                    &previous.producer.eta,
+                    0,
+                )?;
                 previous_slot = slot;
             }
         }
@@ -158,6 +169,7 @@ impl BlockInfo {
             previous_slot,
             &previous_hash,
             &previous.header.previous,
+            &previous.producer.eta,
             expected_reward,
         )?;
 
@@ -537,11 +549,13 @@ pub struct BlockProducer {
     pub signature: Signature,
     /// Proposal transaction
     pub proposal: Transaction,
+    /// Block producer ETA
+    pub eta: pallas::Base,
 }
 
 impl BlockProducer {
-    pub fn new(signature: Signature, proposal: Transaction) -> Self {
-        Self { signature, proposal }
+    pub fn new(signature: Signature, proposal: Transaction, eta: pallas::Base) -> Self {
+        Self { signature, proposal, eta }
     }
 }
 
@@ -549,6 +563,7 @@ impl Default for BlockProducer {
     fn default() -> Self {
         let signature = Signature::dummy();
         let proposal = Transaction::default();
-        Self { signature, proposal }
+        let eta = pallas::Base::ZERO;
+        Self { signature, proposal, eta }
     }
 }

+ 9 - 2
src/blockchain/slot_store.rs

@@ -17,7 +17,7 @@
  */
 
 // [`Slot`] is defined in the sdk so contracts can use it
-use darkfi_sdk::blockchain::Slot;
+use darkfi_sdk::{blockchain::Slot, pasta::pallas};
 use darkfi_serial::{deserialize, serialize};
 
 use crate::{validator::consensus::pid::slot_pid_output, Error, Result};
@@ -32,13 +32,15 @@ use super::{parse_u64_key_record, SledDbOverlayPtr};
 ///        up until this slot
 ///     5. Slot previous error value correspond to previous slot one
 ///     6. PID output for this slot is correct
-///     7. Slot reward value is the expected one
+///     7. Slot last eta is the expected one
+///     8. Slot reward value is the expected one
 /// Additional validity rules can be applied.
 pub fn validate_slot(
     slot: &Slot,
     previous: &Slot,
     previous_block_hash: &blake3::Hash,
     previous_block_sequence: &blake3::Hash,
+    last_eta: &pallas::Base,
     expected_reward: u64,
 ) -> Result<()> {
     let error = Err(Error::SlotIsInvalid(slot.id));
@@ -76,6 +78,11 @@ pub fn validate_slot(
     }
 
     // Check reward is the expected one (7)
+    if &slot.last_eta != last_eta {
+        return error
+    }
+
+    // Check reward is the expected one (8)
     if slot.reward != expected_reward {
         return error
     }

+ 5 - 5
src/validator/consensus/mod.rs

@@ -77,7 +77,7 @@ impl Consensus {
         // Generate a time keeper for current slot
         let time_keeper = self.time_keeper.current();
 
-        // Node have already checked for finalization in this slot
+        // Node have already checked for finalization in this slot (1)
         if time_keeper.verifying_slot <= self.checked_finalization {
             warn!(target: "validator::consensus::append_proposal", "Proposal received after finalization sync period.");
             return Err(Error::ProposalAfterFinalizationError)
@@ -86,12 +86,12 @@ impl Consensus {
         // Proposal validations
         let hdr = &proposal.block.header;
 
-        // Ignore proposal if not for current slot
+        // Ignore proposal if not for current slot (2)
         if hdr.slot != time_keeper.verifying_slot {
             return Err(Error::ProposalNotForCurrentSlotError)
         }
 
-        // Check if proposal hash matches actual one
+        // Check if proposal hash matches actual one (3)
         let proposal_hash = proposal.block.blockhash();
         if proposal.hash != proposal_hash {
             warn!(
@@ -102,7 +102,7 @@ impl Consensus {
         }
 
         // TODO: verify if this should happen here or not.
-        // Check that proposal transactions don't exceed limit
+        // Check that proposal transactions don't exceed limit (4)
         if proposal.block.txs.len() > TXS_CAP {
             warn!(
                 target: "validator::consensus::append_proposal", "Received proposal transactions exceed configured cap: {} - {}",
@@ -121,7 +121,7 @@ impl Consensus {
         // Retrieve expected reward
         let expected_reward = next_block_reward();
 
-        // Verify proposal block
+        // Verify proposal block (5)
         if verify_block(
             &fork.overlay,
             &time_keeper,

+ 1 - 2
tests/blockchain.rs

@@ -63,14 +63,13 @@ impl Harness {
             producers,
             vec![previous_hash],
             vec![previous.header.previous.clone()],
-            pallas::Base::ZERO,
             previous_slot.pid.error,
         );
         let (f, error, sigma1, sigma2) = slot_pid_output(&previous_slot, producers);
         let pid = PidOutput::new(f, error, sigma1, sigma2);
         let total_tokens = previous_slot.total_tokens + previous_slot.reward;
         let reward = next_block_reward();
-        let slot = Slot::new(id, previous_slot_info, pid, total_tokens, reward);
+        let slot = Slot::new(id, previous_slot_info, pid, pallas::Base::ZERO, total_tokens, reward);
 
         // We increment timestamp so we don't have to use sleep
         let mut timestamp = previous.header.timestamp;