Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion masq_lib/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::data_version::DataVersion;
use const_format::concatcp;

pub const DEFAULT_CHAIN: Chain = Chain::PolyMainnet;
pub const CURRENT_SCHEMA_VERSION: usize = 10;
pub const CURRENT_SCHEMA_VERSION: usize = 11;

pub const HIGHEST_RANDOM_CLANDESTINE_PORT: u16 = 9999;
pub const HTTP_PORT: u16 = 80;
Expand Down
64 changes: 63 additions & 1 deletion node/src/database/db_initializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl DbInitializerReal {
Self::create_config_table(conn);
Self::initialize_config(conn, external_params);
Self::create_payable_table(conn);
Self::create_sent_payable_table(conn);
Self::create_pending_payable_table(conn);
Self::create_receivable_table(conn);
Self::create_banned_table(conn);
Expand Down Expand Up @@ -258,6 +259,31 @@ impl DbInitializerReal {
Self::set_config_value(conn, "max_block_count", None, false, "maximum block count");
}

pub fn create_sent_payable_table(conn: &Connection) {
conn.execute(
"create table if not exists sent_payable (
rowid integer primary key,
tx_hash text not null,
receiver_address text not null,
amount_high_b integer not null,
amount_low_b integer not null,
timestamp integer not null,
gas_price_wei integer not null,
nonce integer not null,
status text not null,
retried integer not null
)",
[],
)
.expect("Can't create sent_payable table");

conn.execute(
"CREATE UNIQUE INDEX sent_payable_tx_hash_idx ON sent_payable (tx_hash)",
[],
)
.expect("Can't create transaction hash index in sent payments");
}

pub fn create_pending_payable_table(conn: &Connection) {
conn.execute(
"create table if not exists pending_payable (
Expand Down Expand Up @@ -652,7 +678,7 @@ mod tests {
#[test]
fn constants_have_correct_values() {
assert_eq!(DATABASE_FILE, "node-data.db");
assert_eq!(CURRENT_SCHEMA_VERSION, 10);
assert_eq!(CURRENT_SCHEMA_VERSION, 11);
}

#[test]
Expand Down Expand Up @@ -713,6 +739,42 @@ mod tests {
)
}

#[test]
fn db_initialize_creates_sent_payable_table() {
let home_dir = ensure_node_home_directory_does_not_exist(
"db_initializer",
"db_initialize_creates_sent_payable_table",
);
let subject = DbInitializerReal::default();

let conn = subject
.initialize(&home_dir, DbInitializationConfig::test_default())
.unwrap();

let mut stmt = conn.prepare("select rowid, tx_hash, receiver_address, amount_high_b, amount_low_b, timestamp, gas_price_wei, nonce, status, retried from sent_payable").unwrap();
let mut sent_payable_contents = stmt.query_map([], |_| Ok(42)).unwrap();
assert!(sent_payable_contents.next().is_none());
let expected_key_words: &[&[&str]] = &[
&["rowid", "integer", "primary", "key"],
&["tx_hash", "text", "not", "null"],
&["receiver_address", "text", "not", "null"],
&["amount_high_b", "integer", "not", "null"],
&["amount_low_b", "integer", "not", "null"],
&["timestamp", "integer", "not", "null"],
&["gas_price_wei", "integer", "not", "null"],
&["nonce", "integer", "not", "null"],
&["status", "text", "not", "null"],
&["retried", "integer", "not", "null"],
];
assert_create_table_stm_contains_all_parts(&*conn, "sent_payable", expected_key_words);
let expected_key_words: &[&[&str]] = &[&["tx_hash"]];
assert_index_stm_is_coupled_with_right_parameter(
conn.as_ref(),
"sent_payable_tx_hash_idx",
expected_key_words,
)
}

#[test]
fn db_initialize_creates_payable_table() {
let home_dir = ensure_node_home_directory_does_not_exist(
Expand Down
2 changes: 2 additions & 0 deletions node/src/database/db_migrations/db_migrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::database::db_initializer::ExternalData;
use crate::database::db_migrations::migrations::migration_0_to_1::Migrate_0_to_1;
use crate::database::db_migrations::migrations::migration_10_to_11::Migrate_10_to_11;
use crate::database::db_migrations::migrations::migration_1_to_2::Migrate_1_to_2;
use crate::database::db_migrations::migrations::migration_2_to_3::Migrate_2_to_3;
use crate::database::db_migrations::migrations::migration_3_to_4::Migrate_3_to_4;
Expand Down Expand Up @@ -80,6 +81,7 @@ impl DbMigratorReal {
&Migrate_7_to_8,
&Migrate_8_to_9,
&Migrate_9_to_10,
&Migrate_10_to_11,
]
}

Expand Down
95 changes: 95 additions & 0 deletions node/src/database/db_migrations/migrations/migration_10_to_11.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use crate::database::db_migrations::db_migrator::DatabaseMigration;
use crate::database::db_migrations::migrator_utils::DBMigDeclarator;

#[allow(non_camel_case_types)]
pub struct Migrate_10_to_11;

impl DatabaseMigration for Migrate_10_to_11 {
fn migrate<'a>(
&self,
declaration_utils: Box<dyn DBMigDeclarator + 'a>,
) -> rusqlite::Result<()> {
let sql_statement = "create table if not exists sent_payable (
rowid integer primary key,
tx_hash text not null,
receiver_address text not null,
amount_high_b integer not null,
amount_low_b integer not null,
timestamp integer not null,
gas_price_wei integer not null,
nonce integer not null,
status text not null,
retried integer not null
)";

declaration_utils.execute_upon_transaction(&[&sql_statement])
}

fn old_version(&self) -> usize {
10
}
}

#[cfg(test)]
mod tests {
use crate::database::db_initializer::{
DbInitializationConfig, DbInitializer, DbInitializerReal, DATABASE_FILE,
};
use crate::test_utils::database_utils::{
assert_create_table_stm_contains_all_parts, assert_table_exists,
bring_db_0_back_to_life_and_return_connection, make_external_data,
};
use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler};
use masq_lib::test_utils::utils::ensure_node_home_directory_exists;
use std::fs::create_dir_all;

#[test]
fn migration_from_10_to_11_is_applied_correctly() {
init_test_logging();
let dir_path = ensure_node_home_directory_exists(
"db_migrations",
"migration_from_10_to_11_is_properly_set",
);
create_dir_all(&dir_path).unwrap();
let db_path = dir_path.join(DATABASE_FILE);
let _ = bring_db_0_back_to_life_and_return_connection(&db_path);
let subject = DbInitializerReal::default();

let result = subject.initialize_to_version(
&dir_path,
10,
DbInitializationConfig::create_or_migrate(make_external_data()),
);

assert!(result.is_ok());

let result = subject.initialize_to_version(
&dir_path,
11,
DbInitializationConfig::create_or_migrate(make_external_data()),
);

let connection = result.unwrap();
assert_table_exists(connection.as_ref(), "sent_payable");
let expected_key_words: &[&[&str]] = &[
&["rowid", "integer", "primary", "key"],
&["tx_hash", "text", "not", "null"],
&["receiver_address", "text", "not", "null"],
&["amount_high_b", "integer", "not", "null"],
&["amount_low_b", "integer", "not", "null"],
&["timestamp", "integer", "not", "null"],
&["gas_price_wei", "integer", "not", "null"],
&["nonce", "integer", "not", "null"],
&["status", "text", "not", "null"],
&["retried", "integer", "not", "null"],
];
assert_create_table_stm_contains_all_parts(
&*connection,
"sent_payable",
expected_key_words,
);
TestLogHandler::new().assert_logs_contain_in_order(vec![
"DbMigrator: Database successfully migrated from version 10 to 11",
]);
}
}
1 change: 1 addition & 0 deletions node/src/database/db_migrations/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved.

pub mod migration_0_to_1;
pub mod migration_10_to_11;
pub mod migration_1_to_2;
pub mod migration_2_to_3;
pub mod migration_3_to_4;
Expand Down
5 changes: 5 additions & 0 deletions node/src/test_utils/database_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ pub fn retrieve_config_row(conn: &dyn ConnectionWrapper, name: &str) -> (Option<
})
}

pub fn assert_table_exists(conn: &dyn ConnectionWrapper, table_name: &str) {
let result = conn.prepare(&format!("select * from {}", table_name));
assert!(result.is_ok(), "Table {} should exist", table_name);
}

pub fn assert_table_does_not_exist(conn: &dyn ConnectionWrapper, table_name: &str) {
let error_stm = conn
.prepare(&format!("select * from {}", table_name))
Expand Down
Loading