Some initial considerations about the Java API and in general

First I want to apologize if some of the topics are already discussed.

  1. CompletableFuture boilerplate

Currently all operations that call NativeBindings.* use CompletableFuture to store the result even for operations which are definitely non-blocking like appContainerName().

The result is that each time we need to call future.get(); which is kind of tedious and verbose. It also may throw InterruptedException which I am not sure if it is needed for (at least for) non-blocking operations.

One possible solution is to wrap the entire, lets call it Level 1 API in a wrapper API which hides the boilerplate and gives the Java developers synchronous API which is easier to use.

Other solution might be if the bindings are generated in a way that is synchronous, so no wrapper is needed.

  1. Estimating the cost of operations

At some point we will need a way to estimate the cost of a operation or series of operations. For example if a user queues several write operations that produce logical unit it is good idea if he is able to call some method in order to see it he has enough balance to execute all of the operations. Otherwise if the last operation fails the logical unit will be incomplete and all the "money" spend on the previous operations will be wasted.

Is there an idea how this problem will be approached?

  1. "Manual" mode for the Authenticator

Currently the app authentication process is interactive. But what about headless server programs, for example a daemon that acts like an indexing crawler. How it will get its authentication data? I imagine that it will have a command line parameter to generate the auth request as string and then the user will have to copy and paste it in the authenticatior and copy and paste the auth result in a config file.

Is that the idea?

  1. Auto-expandable mutable data (paginated Key-Value store)

Currently when new items are added to a mData it expands until it reaches the 1MB limit and then is starting to return error (ERR_DATA_TOO_LARGE).

From practical point of view it is quite tedious to check each time if that is the case and handle it appropriately. It will be very nice if there is a new mData type that automatically creates new internal mData (page) and also automatically handles the requests, i.e. the developer just feeds the mDataInfo of the first page and the API handles the rest. Currently I am creating this functionality in my java lib but I was wondering if it is good idea to be implemented in the lower level since it will be used by all client libs (c#, js, etc.)

  1. The sudden death problem

Currently if the user loses his login credentials, or worst, they get stolen that leads to sudden "safe network" death (for him). Losing login credential happens rather often and I think that many users will be frustrated if they are unable to recover their account.

I saw discussions about this problem in the forum, but did not saw any "final" decision. Is there an idea if there will be some more user friendly solution or we will stay with the current?

Btw, probably Level 2/3 (wrapper/app level) solution can be forged where accounts are created in pairs - one is “hot” for day to day usage, which shares everything with the second account which is “cold” and login credentials are kept offline (and used only on (more) secure device only when needed in case first account is lost or stolen. If the first account is compromised, all the owned objects can be transferred to newly created “hot” account (and first account’s Permissions are removed)

  1. Aging (and prunable) data

I know that a main principle of Safe network is that no data is really ever deleted but for some type of data this seems wasteful. For example I am working now on a chat app. Each user has separate mData for his part of the conversation and that mDatas are constantly updated. I don’t care about the previous versions of the mData, I just need the last one. The old versions are totally useless since the latest version contains the whole conversation.

Probably it will be good idea to have mData type that prunes older versions of the mData after some period or even the latest version if its age is above predefined limit.

  1. Pay or burn

This is controversial, I am sorry.

The idea that GET operations are free really bothers me. I have raised this question before in this forum. The more I think about the problem the more I am convinced that in order to prevent DDOS attacks we need to force the user to either pay "money" or burn CPU cycles in order to get the right to execute GET request.

If the user does not want to pay he will have to provide proof of work to the proxy server in order to get the right to execute given number of requests. The idea is user to be forced to burn at least the same amount of CPU cycles as the network uses to handle his request.

The other alternative is user to pay for executing GET requests with safecoin or other means.

Btw, burning can be alternative form of payment if some POW cryptocurrency is mined in the process.

5 Likes

Hi, nice to see the questions. I have some input on a couple of them.

  1. It is a common example, what happens when we run out of funds. I think the case when your wallet is dry is in reality more of an edge case. Nevertheless, there is a defined PUT cost currently for operations, and I assume that will always be so. So, when you design your set of writes forming a ‘transaction’, then you could calculate the PUT sum of such, and set a check before starting it.
    Now this is a very general functionality, that any app could use, so I would think someone produced a small helper, a builder for example:

var txBuilder = new TxBuilder()
.WithWrites(listOfWriteOps);

var result = txBuilder.Execute();

if (result == TxResults.NotEnoughBalance)
   // ... not enough balance

But there’s another question looming here.
If we don’t have cross data structure ACID (i.e. you want to write to MD 1 and MD 2 in single tx), then you should have a Saga pattern, as to be able to compensate write to MD 1 if write to MD 2 fails.

This will be a very important thing eventually, how it will be enabled.


  1. This exists. So, some github examples use the SAFEBrowser, which would be suitable for some apps. But there are also examples (maybe not java ones though) that have an implementation of the authenticator included, so that you would just call it directly. You could store your credentials in any way you want, and let the device load them at startup and call the authenticator with them.

  2. I have deviced an algo for this in C#. If you are doing the same you can probably get some idea from my repos. You’ll find them at https://github.com/oetyng/SAFE.DataStore.
    DataTree.cs is the essential component. But Database.cs with TypeStore.cs and Indexer.cs are needed to get fast access.
    I have also asked the question if it wouldn’t be a good idea to include this in the core libraries. It seems to me that a vast majority of use cases would need it, and that it would be beneficial for adoption if not everyone had to implement it.

  3. Interesting question where I think we will see different sorts of services which provide you with simple ways to handle this (possibly at various costs in terms of privacy or security).

  4. There’s a currently a discussion going on in the other forum, which sheds some light on the thinking in this area : https://safenetforum.org/t/appendable-data-discussion

  5. Caching is the primary answer to this question. And as far as I have read, the requesting client will need to do a larger CPU work, than the nodes serving the data, so it won’t be a feasible attack.

2 Likes

Thank you for your questions @ogrebgr. @oetyng has covered most of it but here’s my two cents :slight_smile:

1 - All native calls across the FFI layer are async in nature as mentioned in this RFC. Although some operations do not include network operations, the native functions always take a callback that is executed later. We can add .get() in the API wrapper itself thus exposing a synchronous API. We’ll consider this for the upcoming versions.

3 - The authenticator API that is currently available only in the mock version of the packages can be called from any kind of application. The idea of a CLI authenticator is indeed being considered for your scenario and others too (IoT devices etc.)

5 - Self-authentication is possible with the password never leaving the system. Although recovery is a good-to-have from a UX perspective, it will come at some security costs.

4 Likes

As far as I can image that means the “master” login credentials should be available to the self-authenticating app. Isn’t that bigger security risk? For example in a situation where some CLI app is running on a remote machine.

1 Like