-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move safety store to rust #982
Conversation
Docker tags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Sergiy! For this review, I've just started with a high level / architectural review. Happy to do a more detailed review once the high level stuff feels correct.
In terms of the architecture, I think we need to move around the crate structure on the Rust side, and separate out the databases better -- I've captured more detailed thoughts in comments.
The code itself is looking nice though, we just want to make sure the architecture is right first.
@@ -316,7 +325,30 @@ public void configure() { | |||
|
|||
switch (this.safetyRecoveryConfig) { | |||
case MOCKED -> install(new MockedSafetyStoreModule()); | |||
case BERKELEY_DB -> install(new BerkeleySafetyStoreModule()); | |||
case REAL -> install( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this now use Rocks / Rust, not Berkeley as the default test implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
properties.set("db.location", dataDir.toString()); | ||
properties.set("db.location.node", new File(dataDir, "node").toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion we shouldn't be introducing explicit configuration for e.g. the db.location.node
field - it should just be a fixed path under db.location
. Having the layout fixed under db.location
means we don't have to worry about people changing this when people build backup scripts.
Side note - if we're introducing a new config, it should be included in the env_subst file so it works in Docker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked to use the same config variable and fixed subdirectories under it.
@@ -122,13 +125,16 @@ pub struct JNINodeRustEnvironment { | |||
pub state_manager: StateManager, | |||
pub metric_registry: Arc<Registry>, | |||
pub running_task_tracker: UntilDropTracker, | |||
pub node_store: Arc<DbLock<ActualNodeDatabase>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things here:
- I thought we were having separate databases for Safety and Address Book (and possibly migrations)?
- If we did have one database, in my opinion we shouldn't call it the "node database" - it's a very misleading name as it doesn't include e.g. the ledger database.
- I don't see why we need a lock around them here - this seems like it will be uselessly contentioned (particularly with a combined database, where e.g. a write of the address book would block reading the safety store) - Rocks does locking internally anyway where it needs to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this is a misunderstanding because I got the conclusion that these stores should be separate from the ledger, but otherwise it's fine to keep them together. But I see no problems separating them now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked to make databases separate.
@@ -101,7 +101,7 @@ public final class BerkeleyAddressBookStore implements AddressBookPersistence { | |||
public BerkeleyAddressBookStore( | |||
Serialization serialization, | |||
Metrics metrics, | |||
@NodeStorageLocation String nodeStorageLocation, | |||
@StateManagerStorageLocation String nodeStorageLocation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this - it looks like we're effectively moving the Berkeley address book here?
I'd assumed we only want this class around still for the purposes of migrating to the new address book store? So we should be using the old/existing location, so we can migrate from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to preserve the Berkeley address book location where it was before. It might be a bit misleading as the old NodeStorageLocation
annotation is renamed to StateManagerStorageLocation
and the new NodeStorageLocation
annotation is now responsible for node-specific data - address book and safety state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh right - well as mentioned elsewhere, I think for now it's better to keep @NodeStorageLocation
as the root directory, and just have each store use a different sub-directory from it :).
I want to avoid any node runners needing to add new configuration to take this update 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restored old naming
|
||
/// The ID of the node stored in the Address book (Secp256k1 public key) | ||
#[derive(Clone, Copy, Sbor)] | ||
pub struct AddressBookNodeId(pub [u8; AddressBookNodeId::LENGTH]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stuff shouldn't be in the state-manager
crate as it's not relevant to the ledger / state manager database.
We may want to introduce new crates for consensus
to stick the safety store, and p2p
for the address book?
Where jni-export
includes consensus
, p2p
etc.
We may then want to move some of the ledger helpers into node-common
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Will refactor these.
#[derive(Clone, Sbor)] | ||
pub struct AddressBookEntry { | ||
pub node_id: AddressBookNodeId, | ||
pub banned_until: Option<i64>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's a timestamp we probably want to create an EpochTimestamp
new-type wrapping e.g. chrono's DateTime - with this to make it SBOR encode as an i64:
#[sbor(
as_type = "i64",
as_ref = "self.timestamp()",
from_value = "Self(DateTime::from_timestamp(value, 0))"
)]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the hint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking deeper, I realized that implementation must make assumptions about future use and convenient representation. Also, it requires adding a new dependency on crono
just to make the code compile, there is no use of this representation on the Rust side for now. So, I've created a type alias and added a comment how this can be changed if necessary. Actual change, better to postpone until these timestamps will be actually used on the Rust side. Someone who will be implementing this part will be free to choose the most convenient underlying type without breaking binary compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds fine / good to me :). We do have crono already on Core API - but I'm happy to push this back till later.
@@ -738,6 +767,41 @@ impl DbCodec<()> for UnitDbCodec { | |||
} | |||
} | |||
|
|||
/// A [`DbCodec]` capable of representing [`MigrationId]`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of interest, why did we opt for manual codecs rather than SBOR encoding the id and migration status?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I've created them at the beginning, when I had a very basic understanding of how things done here. Will change to SBOR encoding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
…re working (address book is only partially tested)
2284dab
to
8679a93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
I haven't checked the DTO code -- ideally I'd like to see some tests that the migrations are working as expected, by writing to Berkeley, migrating, then reading from Rocks and comparing.
Separately, I think it'd be better in the long run to not have a migration store, and move the migration state into the individual stores; to avoid having to explain to node runners what this migration store is :)
@@ -101,7 +101,7 @@ public final class BerkeleyAddressBookStore implements AddressBookPersistence { | |||
public BerkeleyAddressBookStore( | |||
Serialization serialization, | |||
Metrics metrics, | |||
@NodeStorageLocation String nodeStorageLocation, | |||
@StateManagerStorageLocation String nodeStorageLocation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh right - well as mentioned elsewhere, I think for now it's better to keep @NodeStorageLocation
as the root directory, and just have each store use a different sub-directory from it :).
I want to avoid any node runners needing to add new configuration to take this update 👍
@@ -163,18 +165,51 @@ impl JNINodeRustEnvironment { | |||
|
|||
let running_task_tracker = scheduler.into_task_tracker(); | |||
|
|||
let address_book_db_path = Self::combine(&base_path, "address_book"); | |||
let safety_store_db_path = Self::combine(&base_path, "safety_store"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Berkeley paths were address_book
and consensus_safety_store
.
Are we okay using the same paths? I guess Berkeley and Rocks don't share any file names; so we can just put them in the same directory; and the old Berkeley files will become irrelevant (but that's okay).
If we're okay with using the same paths, then we should use the same names:
address_book
is goodsafety_store
needs to be renamedconsensus_safety_store
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -391,7 +391,6 @@ protected void configure() { | |||
ScenariosExecutionConfig.resolveForNetwork(network))); | |||
|
|||
// Recovery | |||
install(new BerkeleySafetyStoreModule()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file needs to be deleted I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is. For some reason, git thinks that it was renamed into BFTValidatorDTO.
|
||
@Provides | ||
@Singleton | ||
BerkeleySafetyStateStore bdbSafetyStateStore( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent any risk of confusion, I'd rather we don't provide the berkeley stores at all to guice, and just create them inline in the migration methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, I'd suggest we don't need to provide any of these in guice, except the AddressBookPersistence
and the PersistentSafetyStateStore
|
||
@Provides | ||
@Singleton | ||
RocksDbHighPriorityPeersStore rocksDbHighPriorityPeersStore( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this if the RocksDbAddressBookStore
does both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RocksDbAddressBookStore
holds only the address book part. I wanted to keep all stores separate. On the Java side, putting it all together looked like an ad-hoc solution.
@@ -383,6 +302,51 @@ public void test_rust_mempool_getRelayTxns() throws Exception { | |||
} | |||
} | |||
|
|||
private NodeRustEnvironment createNodeRustEnvironment() throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it's worth moving this to some unit test helper or something? Given that we've duplicated it across a few tests now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the tests, we've been following the "Good Scout" rule and leaving our Java tests in a better shape than we found them every change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked tests to reuse common code. Unfortunately, due to Gradle issues it appeared too time-consuming to attempt to reuse test dependencies, and I ought to create two similar (but not identical) base classes for tests which require NodeRustEnvironment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what core/src/test-core
is for :). Create a new file NodeRustEnvironmentBuilder.java
in core/src/test-core/java/com/radixdlt/rev2
.
We've agreed as a team to use composition over inheritance for any new test utilities, so please don't introduce base classes :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such a location does not allow using it from core-rust-bridge
, where 3 tests are located.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked to have it as a utility class, rather than a base class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see any tests of the migration?
I'd like to see a test where we:
- Create a Berkeley store (e.g. just via a constructor) and commit various bits of data
- Boot up a node. Wait for it to boot up. This should trigger the migration of the data.
- Delete the data from the Berkeley store.
- Check the state can be read from the node (ie that it must have migrated to Rust)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(for each of the stores).
Booting up the node can be done with a SimulationTest
builder, setting a FunctionalRadixNodeModule set to use the same temporary folder for its database as the Berkeley store.
} | ||
|
||
/// A RocksDB-backed persistence layer for safety store. | ||
pub struct SafetyStoreDatabase<R> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect the SafetyStore
to be in a separate consensus crate. But I'm happy for us to move it at a later date if we just want to get this ticket in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think further refactoring (including moving p2p JNI part) should be done at the next stage, after discussion and making decision on final structure.
@@ -86,7 +86,7 @@ public PrefixedNodeStorageLocationModule(String baseLocation) { | |||
@Provides | |||
@Singleton | |||
@NodeStorageLocation | |||
private String nodeStorageLocation(@Self ECDSASecp256k1PublicKey publicKey) { | |||
private String stateManagerStorageLocation(@Self ECDSASecp256k1PublicKey publicKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is still the nodeStorageLocation
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
|
||
import java.util.Optional; | ||
|
||
public class MigratingSafetyStore implements PersistentSafetyStateStore { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is unused / can be deleted? 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Sergiy - it's looking a lot better, we're nearly there! Most of my comments can be left to a follow-up review, but the following should be done before merge - as they are core parts of the migration logic / end-state:
- Changing the Cfs to be VersionedCfs over SBOR state (sorry I missed this before in such a large review)
- Ensuring we don't instantiate Berkeley stores during bootstrapping unless we need to because we're not migrated.
- Ensuring the address book migration test is complete (I think we're missing high priority peers at the moment)
throw new IllegalStateException("Can't construct"); | ||
} | ||
|
||
public static NodeRustEnvironment createNodeRustEnvironment(String dbPath) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't really a builder pattern... I'd expect something like: .new().dbPath(X).build()
But anyway, no need to change in this PR :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Builder pattern makes sense when there are no (or very few) mandatory parameters. In this case, there is only one (and mandatory) parameter. The Factory Method better suits in such a use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed class to avoid confusion.
@@ -115,6 +115,21 @@ pub fn jni_sbor_coded_fallible_call<Args: ScryptoDecode, Response: ScryptoEncode | |||
.unwrap_or_else(std::ptr::null_mut) | |||
} | |||
|
|||
/// A convenience method for the case when input should remain in the form of raw byte array | |||
/// (i.e. no SBOR decoding is needed). Output is still properly encoded with SBOR. | |||
pub fn jni_raw_sbor_fallible_call<Response: ScryptoEncode>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason we chose not to SBOR encode as a byte array? It's pretty cheap.
We used to have these kinds of raw methods, but they were confusingly inconsistent so I believe we got rid of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an SBOR encoded structure, and it is automatically SBOR-encode on the Java side. On the Rust side it has no use now and there is no sense decoding it because DB contains SBOR encoded struct anyway. There were two reasonable solutions
- manually encode SBOR on the Java side, wrap it into array and when it comes back - manually unwrap and decode
- get direct access to a byte array before it is decoded on the Rust side and pass it to the relevant underlying method
The second approach looked much simpler to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer an issue, and the corresponding helper is removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice separation :)
@@ -238,6 +238,14 @@ impl<'r, 'w, KC: BoundedDbCodec, CF: TypedCf<KeyCodec = KC>, R: WriteableRocks> | |||
self.cf.key_codec.upper_bound_encoding(), | |||
); | |||
} | |||
|
|||
/// Retrieves all entries. | |||
pub fn get_all(&self) -> Vec<CF::Value> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this necessarily needs to be put on the BoundedDbCodec
impl. Perhaps it could be put on a more general impl? Or I imagine there's one there already?
We should also probably add to the Rust doc that this should only be used in prod when we know the total entries are bounded due to some kind of application limit?
I assume this is true in the case where we're using it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, I found nothing like get_all
. To me, it looked consistent to put it together with delete_all
in the TypedCfApi
implementation. It relies on the bounds in the key too, so the location looked about right.
Yes, this code could retrieve a lot of data, but it is used for address book, which rarely contains significant number of entries. There is no specific limit at the best of my knowledge, but the Java version has no limit either. So, if some kind of limit should be implemented, we need to discuss it first. Again, this is the reason to not put it in a more generic location as of now. Currently, it is used only in the AddressBook.
} | ||
|
||
/// Safety store | ||
pub struct SafetyStoreCf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nicer conceptually to put the safety store and address book in separate mod
s (both the store and relevant CFs). But I guess we'll be moving the safety store to a separate consensus
crate next PR, so that's okay for now.
new AbstractModule() { | ||
@Override | ||
protected void configure() { | ||
bind(AddressBookPersistence.class).to(BerkeleyAddressBookStore.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we using Berkeley here instead of Rocks / the default?
Did Rocks break? This feels like a scary change to me - in that it might suggest this test breaks with the standard DB, and this was a work-around for a broken test :).
Either this test should be changed to use FunctionalNodeModule if it's an integration test; or if that's too big a change, at least at a comment here to explain we're hacking in the deprecated address Berkeley stores for now because it's too disruptive to add a node rust environment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to replace the implementation here, but got a very strange error:
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) An exception was caught and reported. Message: called `Result::unwrap()` on an `Err` value: Error { message: "IO error: lock hold by current process, acquire time 1724758428 acquiring thread 6169243648: /var/folders/kq/xrwzyf4j3yq7pqnx_zkx9tym0000gn/T/junit5819788118170431666/state_manager/LOCK: No locks available" }
at [unknown source]
2) [Guice/MissingConstructor]: No injectable constructor for type NodeRustEnvironment.
class NodeRustEnvironment does not have a @Inject annotated constructor or a no-arg constructor.
Requested by:
1 : NodeRustEnvironment.class(NodeRustEnvironment.java:75)
at P2PTestNetworkRunner$1.configure(P2PTestNetworkRunner.java:198)
I'm going to add a comment and leave this part as is.
public class AddressBookMigrationTest { | ||
@Rule public TemporaryFolder folder = new TemporaryFolder(); | ||
|
||
private Module createCommonModule() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've had a rule to avoid creating Guice injectors for new tests, outside of FunctionalNodeModule
- because they're very flakey to changes.
Why can't we just create the BerkeleyAddressBookStore
in a private method in the test code without DI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, if we change the AddressBookModule
to have a static ensureMigrated(rocksAddressBookStore, <config>)
method, then we can just test that method here without creating any test injectors at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked
|
||
// Create some entries in the Berkeley address book | ||
try (var berkeleyAddressBook = injector.getInstance(BerkeleyAddressBookStore.class)) { | ||
addresses.forEach(berkeleyAddressBook::upsertEntry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice test - but I notice it's not complete? Can we also add some high priority peers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
public class SafetyStoreMigrationTest { | ||
@Rule public TemporaryFolder folder = new TemporaryFolder(); | ||
|
||
private Module createCommonModule() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the other test - can we avoid adding new guice modules in tests? They create a maintenance burden
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked
var injector = | ||
Guice.createInjector( | ||
createCommonModule(), | ||
new NodePersistenceModule(AddressBookPolicy.DISABLED), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The address book persistence state should be irrelevant to this test - something feels off here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked.
…ove-safety-store-to-rust
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Sergiy 👍
Happy for us to merge this, as any remaining comments are not related to how we persist things.
We can pick up any outstanding comments in a later PR which re-orgs the crates on the rust side.
} | ||
|
||
#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] | ||
pub struct LedgerHeader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This duplicates LedgerHeader
from StateManager, but that's fine for now. Perhaps we should add a comment to de-duplicate it / create some common models when we take out a consensus crate 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment
core-rust/p2p/src/components.rs
Outdated
Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode, PartialOrd, Ord, PartialEq, Eq, | ||
)] | ||
#[sbor(transparent)] | ||
pub struct RawPublicKey(pub [u8; RawPublicKey::LENGTH]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor - one to consider on a follow-up PR - perhaps we should call this a NodeSecp256k1PublicKey
and be a wrapper around Secp256k1PublicKey
from radix-common
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to NodeSecp256k1PublicKey
. This clearly references the source where this data comes from and should later help with merging/wrapping existing type/etc.
core-rust/p2p/src/components.rs
Outdated
|
||
/// The Secp256K1 signature | ||
#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] | ||
pub struct Signature(pub [u8; Signature::LENGTH]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One for a follow-up PR - we should use Secp256k1Signature
from radix-common
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to NodeSignature
for the same reasons ad for NodeSecp256k1PublicKey
.
|
||
fn combine(base: &String, ext: &str) -> PathBuf { | ||
let mut path = base.clone(); | ||
path.push(MAIN_SEPARATOR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor - can be done in the follow-up PR - this should be done after converting to path buf, then you don't need to add a MAIN_SEPARATOR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked. Realized that we can build PathBuf
from the collection of strings.
@@ -188,7 +191,8 @@ public static REv2StateManagerModule createForTesting( | |||
ledgerSyncLimitsConfig, | |||
protocolConfig, | |||
noFees, | |||
scenariosExecutionConfig); | |||
scenariosExecutionConfig, | |||
false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see anywhere where FunctionalRadixNodeModule
installs an AddressBookPersistence
, directly or indirectly.
I believe what you're referring to is in the TestP2PModule
which is installed in DeterministicNodes
/ SimulationTest
. If necessary, feel free to add an option to TestP2PModule
which allows using a real database.
But the following have no reason to live in a state manager module, so they should not be added here. And this state manager module should not have an installPersistence
flag.
I really don't want more messy hacks to get some tests to work:
install(new PersistentSafetyStateStoreModule());
install(new AddressBookModule());
Please give me a ping if you'd like to pair on this and show me in person.
|
||
@Provides | ||
@Singleton | ||
BerkeleySafetyStateStore safetyStateStore( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor - do we need a BerkeleySafetyStateStore
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked module.
e0cb7b4
to
5323631
Compare
Signed-off-by: Sergiy Yevtushenko <[email protected]> Signed-off-by: Sergiy Yevtushenko <[email protected]>
5323631
to
a2829da
Compare
Quality Gate passedIssues Measures |
Summary
This PR moves Address Book and Safety Store to RocksDB (i.e. at Rust side of the Node code). The migration is of the existing stores is performed automatically at startup.