Giter VIP home page Giter VIP logo

waves's Introduction

🔷 Waves Node

Checks status Downloads Docker pulls
Twitter: Waves Tech Medium: Waves Tech Telegram Awesome Waves

Waves is an open source blockchain protocol.
You can use it to build your own decentralized applications. Waves provides full blockchain ecosystem including smart contracts language called RIDE.

✨ Demo

Waves Node Run Demo

Waves node is a host connected to the blockchain network with the following functions:

Learn more about Waves Node in the documentation.

🚀️ Getting started

A quick introduction of the minimal setup you need to get a running node.

Prerequisites:

  • configuration file for a needed network from here
  • waves-all*.jar file from releases

Linux systems:

sudo apt-get update
sudo apt-get install openjdk-11-jre
java -jar node/target/waves-all*.jar path/to/config/waves-{network}.conf

Mac systems (assuming already installed homebrew):

brew cask install adoptopenjdk/openjdk/adoptopenjdk11
java -jar node/target/waves-all*.jar path/to/config/waves-{network}.conf

Windows systems (assuming already installed OpenJDK 11):

java -jar node/target/waves-all*.jar path/to/config/waves-{network}.conf

Using docker, follow the official image documentation.

More details on how to install a node for different platforms you can find in the documentation.

🔧 Configuration

The best starting point to understand available configuration parameters is this article.

The easiest way to start playing around with configurations is to use default configuration files for different networks; they're available in network-defaults.conf.

Logging configuration with all available levels and parameters is described here.

👨‍💻 Development

The node can be built and installed wherever Java can run. To build and test this project, you will have to follow these steps:

Show instructions

1. Setup the environment.

  • Install Java for your platform:
sudo apt-get update
sudo apt-get install openjdk-11-jre                     # Ubuntu
# or
# brew cask install adoptopenjdk/openjdk/adoptopenjdk11 # Mac
  • Install SBT (Scala Build Tool)

Please follow the SBT installation instructions depending on your platform (Linux, Mac, Windows)

2. Clone this repo

git clone https://github.com/wavesplatform/Waves.git
cd Waves

3. Compile and run tests

sbt checkPR

4. Run integration tests (optional)

Create a Docker image before you run any test:

sbt node-it/docker
  • Run all tests. You can increase or decrease number of parallel running tests by changing waves.it.max-parallel-suites system property:
sbt -Dwaves.it.max-parallel-suites=1 node-it/test
  • Run one test:
sbt node-it/testOnly *.TestClassName
# or 
# bash node-it/testOnly full.package.TestClassName

5. Build packages

sbt packageAll                   # Mainnet
sbt -Dnetwork=testnet packageAll # Testnet

sbt packageAll ‌produces only deb package along with a fat jar.

6. Install DEB package

deb package is located in target folder. You can replace '*' with actual package name:

sudo dpkg -i node/target/*.deb

7. Run an extension project locally during development (optional)

sbt "extension-module/run /path/to/configuration"

8. Configure IntelliJ IDEA (optional)

The majority of contributors to this project use IntelliJ IDEA for development, if you want to use it as well please follow these steps:

  1. Click Add configuration (or Edit configurations...).
  2. Click + to add a new configuration, choose Application.
  3. Specify:
    • Main class: com.wavesplatform.Application
    • Program arguments: /path/to/configuration
    • Use classpath of module: extension-module
  4. Click OK.
  5. Run this configuration.

🤝 Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.

For major changes, please open an issue first to discuss what you would like to change. Please make sure to update tests as appropriate.

Please follow the code of conduct during communication with each other.

ℹ️ Support (get help)

Keep up with the latest news and articles, and find out all about events happening on the Waves Protocol.

⛓ Links

📝 Licence

The code in this project is licensed under MIT license

👏 Acknowledgements

We use YourKit full-featured Java Profiler to make Waves node faster. YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications.

Take a look at YourKit's leading software products: YourKit Java Profiler and YourKit .NET Profiler.

waves's People

Contributors

alexeykiselev avatar alxndrmkd avatar asolovyov avatar b83ypoj avatar catena2w avatar chepiov avatar d-kiselev avatar denisserebryansky avatar drblast avatar dvshur avatar ebceu4 avatar finnoio avatar gagarin55 avatar givanovwaves avatar ismagin avatar ivan-mashonskiy avatar karasiq avatar kiselev-bitrete avatar koloale avatar kushti avatar monroid avatar mrkraft avatar msmolyakov avatar phearnot avatar potan avatar pozharko avatar rigidus avatar tolsi avatar vsuharnikov avatar xrtm000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

waves's Issues

Timeout issue when launching waves-0.3.6 on macOS Sierra

Launching waves-0.3.6 on macOS Sierra produces the following output and the process dies:

$ java -jar waves-0.3.6.jar waves-mainnet.json
[WARN] [12/27/2016 09:11:41.987] [main] [EventStream(akka://wavesplatform)] Logger log1-Slf4jLogger did not respond within Timeout(5000 milliseconds) to InitializeLogger(bus)
error while starting up loggers
akka.ConfigurationException: Logger specified in config can't be loaded [akka.event.slf4j.Slf4jLogger] due to [akka.event.Logging$LoggerInitializationException: Logger log1-Slf4jLogger did not respond with LoggerInitialized, sent instead [TIMEOUT]]
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$1.applyOrElse(Logging.scala:119)
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$1.applyOrElse(Logging.scala:118)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:216)
at scala.util.Try$.apply(Try.scala:192)
at scala.util.Failure.recover(Try.scala:216)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:118)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:113)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:683)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:682)
at akka.event.LoggingBus$class.startDefaultLoggers(Logging.scala:113)
at akka.event.EventStream.startDefaultLoggers(EventStream.scala:28)
at akka.actor.LocalActorRefProvider.init(ActorRefProvider.scala:667)
at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:657)
at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:654)
at akka.actor.ActorSystemImpl._start(ActorSystem.scala:654)
at akka.actor.ActorSystemImpl.start(ActorSystem.scala:670)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:119)
at com.wavesplatform.actor.RootActorSystem$.start(RootActorSystem.scala:22)
at com.wavesplatform.Application$.main(Application.scala:81)
at com.wavesplatform.Application.main(Application.scala)
Caused by: akka.event.Logging$LoggerInitializationException: Logger log1-Slf4jLogger did not respond with LoggerInitialized, sent instead [TIMEOUT]
at akka.event.LoggingBus$class.akka$event$LoggingBus$$addLogger(Logging.scala:188)
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$4.apply(Logging.scala:117)
at akka.event.LoggingBus$$anonfun$4$$anonfun$apply$4.apply(Logging.scala:116)
at scala.util.Success$$anonfun$map$1.apply(Try.scala:237)
at scala.util.Try$.apply(Try.scala:192)
at scala.util.Success.map(Try.scala:237)
at akka.event.LoggingBus$$anonfun$4.apply(Logging.scala:116)
... 19 more
Exception in thread "main" akka.ConfigurationException: Could not start logger due to [akka.ConfigurationException: Logger specified in config can't be loaded [akka.event.slf4j.Slf4jLogger] due to [akka.event.Logging$LoggerInitializationException: Logger log1-Slf4jLogger did not respond with LoggerInitialized, sent instead [TIMEOUT]]]
at akka.event.LoggingBus$class.startDefaultLoggers(Logging.scala:147)
at akka.event.EventStream.startDefaultLoggers(EventStream.scala:28)
at akka.actor.LocalActorRefProvider.init(ActorRefProvider.scala:667)
at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:657)
at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:654)
at akka.actor.ActorSystemImpl._start(ActorSystem.scala:654)
at akka.actor.ActorSystemImpl.start(ActorSystem.scala:670)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:119)
at com.wavesplatform.actor.RootActorSystem$.start(RootActorSystem.scala:22)
at com.wavesplatform.Application$.main(Application.scala:81)
at com.wavesplatform.Application.main(Application.scala)
2016-12-27 09:11:42 INFO [lt-dispatcher-4] a.event.slf4j.Slf4jLogger - Slf4jLogger started

I have been able to reproduce the issue on different macs with macOS Sierra. I don’t know if this problem also occurs with previous version of OS X.
Increasing ‘logger-startup-timeout’ from 5 seconds to 10 seconds in reference.conf seems to solve the problem.

Improvement proposal: Scaling the network to 1000TPS with a Balance Sheet.

Here is my proposal on how to scale the network to very fast speeds:

  1. Redesign the block. Currently the block has:
- Consensus data
- Transaction data
- Miner's signature

My idea is to change the block to a Block Header:

- Consensus data
- Transaction data hash
- Balance Sheet hash
- Miner's signature

The difference is that transaction data is separate from the block, yet it's still protected&referenced by it. This will allow clients to verify all block headers in a very short time [appx. 10s per year on a modern CPU].

  1. Balance Sheet.
    A Balance Sheet is a structure that holds the current state of the cryptocurrency. It includes all data required to apply transactions from the next block including accounts, assets, aliases, ...
    I see it being implemented as a B-tree combined with a Merkle tree, so that after a new transaction is applied, we instantly have a new Balance Sheet hash.
    Every miner applies transactions from a block to his own Balance Sheet. If the Balance Sheet hash is invalid, the block is invalid. Thus, the miner has no possibility of fraud.

In practice there may be a need to store 3 Balance Sheets - one for blocks that are 1440 blocks back [due to consensus calculation & possibility of a rollback], one for the newest block and one for mining purposes.

The balance sheet should be 5-1000 times smaller than the corresponding transaction chain for the account depending on the exact usage.

  1. Database engine redesign.
    Let's ditch H2 for financial calculations. H2 is a terrific engine for general use, but because of this it's very slow. JL777's iguana proves that you can do much better with mmap and custom data structures.

What would this give us?

  1. Instant, verified full-node blockchain bootstrapping.
    Because the Balance Sheet is what's really important, a new node will have to:
  • Download&Verify all Block Headers from the genesis [or from a hardcoded hash] up to a current point in time.
  • Request a Balance sheet for a block[current_block-1440]
  • Request&Apply all transactions that were executed since the block[current_block-1440]
  1. An easy way to prune old data if a disk space is low.

  2. With a fast Balance Sheet [also called a Database] implementation, it should be possible to achieve 1000tx/s on a modern hardware.

/transactions/address/../limit/1001+

/transactions/address/../limit can only return 1000 last records. if limit is bigger than 1000 node responding with
{"error": 10, "message": "Too big sequences requested"}

So if account have, for example, 2000 transactions and we need to get oldest txs /transactions/address/../limit/ became useless.

Improvement proposal: Smooth fee rewards.

Right now current a miner can have free transactions by putting transactions into blocks mined by him.
That is suboptimal because of free blockchain bloat. Let's make a miner pay! >:-B
Let's split the reward from the block. There are few alternatives:

  1. Sending a fee to the past. When a miner mines a block, he takes 50% of the reward, and he gives 50% of the reward to a miner who mined a block 60 blocks ago.
  2. Smoothing: Like [1], but the reward is split 50%-1%-1%-1%...

I think that [2] is slightly superior because it smooths fees more. Thus, it makes rewards from getting large-fee-transactions [ex. asset creation - 1000NXT] much more fairly distributed.

Regardless of implementation, there are things to keep in mind:

  • Fees have to be sent back in time, not forward.
  • Miner needs to have some big % of the reward for himself to encourage him to include transactions in a block.

Asset naming conventions

In order to avoid confusion creating assets under the same name like existing ones should be prohibited.

Proposal: Remove seed and password from full node config

for security reasons I would propose to remove the seed and the password from the config file.

If there is a zero day exploit in java / waves an attacker could get access to the wave daemon / waves user. as waves user he get access to the wallet, the seed and the password via the config.file

From my understanding the wallet is created using the seed. the Seed may be used to recover the wallet but with a wallet in place there is no need to have the seed anymore.

The process of encrypting and unlocking the wallet should be moved to runtime which could be triggered by a new action "/wallet/encrypt" and "/wallet/unlock" similar to well known qt-wallets. The encrypted wallet could remain in memory.

If the seed is needed for address generation it could also be stored in the encrypted wallet.

seed and password in cleartext in a (on default install) world readable file should be avoided.

regards

Proposal: Tx validation before UTX

Before validate tx according the state make sure the sender account exist in current state. Non existent accounts haven't got funds and can't send anything

Add old address to wallet (full node)

Hello!
As i see, method /waves/address is deprecated in the full node.
There is an only one way to create(add) address in the wallet now: POST /addresses
Is it possible to add address from my Web wallet (https://waveswallet.io/) into Full node wallet using public key (like /waves/address)?
Thanks

Proposal : Change the default accessrights to /usr/shared/waves

In the default installation of the deb package the directory /usr/shared/waves is created and the config file is placed there.

The default right allow to view the directory and the settings file from anyone:

drwxr-xr-x 5 root root 4096 Nov 17 22:36 ./
drwxr-xr-x 148 root root 4096 Nov 17 22:36 ../
drwxr-xr-x 2 root root 4096 Nov 17 22:36 bin/
drwxr-xr-x 2 root root 4096 Nov 17 22:39 conf/
drwxr-xr-x 2 root root 12288 Nov 17 22:36 lib/
lrwxrwxrwx 1 root root 14 Nov 17 16:56 logs -> /var/log/waves/
-rw-r--r-- 1 root root 1320 Nov 18 10:57 settings.json

Also the owner could be moved to waves:waves

Rename feeAsset -> feeAssetId in transfer transaction

Please rename the field 'feeAsset' to 'feeAssetId' to reflect field's content in its name. Now the transfer transaction look like

{  
      "type":4,
      "id":"Dx9ikj58GqEXLA1vQ8K3sjKAgqRKRn7jThCAYQs9ofYx",
      "sender":"3MtMoVbAHSitzohEvd6dJGR3kmJZHSePUkS",
      "senderPublicKey":"FJuErRxhV9JaFUwcYLabFK5ENvDRfyJbRz8FeVfYpBLn",
      "recipient":"3N9UuGeWuDt9NfWbC5oEACHyRoeEMApXAeq",
      "assetId":"GAXAj8T4pSjunDqpz6Q3bit4fJJN9PD4t8AK8JZVSa5u",
      "amount":5000,
      "feeAsset":null,
      "fee":100000,
      "timestamp":1479462208828,
      "attachment":"",
      "signature":"4jWTZcRxuFpG4XdCbAhkiWdBjXMHEayPcEhk3yQ3oLYASJ7Fn8ij9C1nAQv61Z7Yo9DoLgy1fysGaaPGbxCWHrfT"
}

Update the config wiki to be clearer

Hi,

The config wiki is not very clear about the "api_key" part. I figured it out but it took me a bit of time.
Here is my suggested changes :

Replace :
Decide what api_key you require and call /utils/hash/secure using http method to calculate apiKeyHash.
By :
Create your API key, think of it as a password that you have to input in order to access each POST request on your node. Call /utils/hash/secure and write the API key you chose in the field then press " Try it out". The response will contain a field called : apiKeyHash, copy this value and paste it in your waves-config.json as the value for the apiKeyHash attribute.

After :
"Call /scorex/stop using http post method to stop node.

Put your walletSeed and apiKeyHash values into waves-testnet.json. "

Add :
Prior to using the swagger UI, type your plain text API key that you created a few steps above in the field provided on the top right of the swagger UI as showed in the following screenshot.
image

Let me know if you have any objections !

API problem: Asset transfer transaction disappears in the destination account

Steps to reproduce:

  1. Sign in to your "Waves" account with assets. (1)
  2. Create another one account (2)
  3. Send to the second account(2) a few assets

Actual Result:

you see that transaction only when doesn't confirmed yet
After full confirmation this transaction disappears

You'll see new transaction in the account (1) tx list, but you won't see this tx in the account (2) tx list.

Proof

account (1): 3MtMoVbAHSitzohEvd6dJGR3kmJZHSePUkS
account (2): 3N9UuGeWuDt9NfWbC5oEACHyRoeEMApXAeq

Transaction with id=D4awUpuZ5vSkigHhqagexupAC1JZ1r4nDdh6ixhnstMF is visible in the transactions list of the account (1): http://testnet.wavesexplorer.com/address/3MtMoVbAHSitzohEvd6dJGR3kmJZHSePUkS (top tx in the list)
The same transaction is not visible in the transactions list of the account (2):
http://testnet.wavesexplorer.com/address/3N9UuGeWuDt9NfWbC5oEACHyRoeEMApXAeq

This API method /transactions/address/3N9UuGeWuDt9NfWbC5oEACHyRoeEMApXAeq/limit/50 just doesn't return the incoming transaction for some reason.

Miners should vote on some network parameters.

Two aspects of a cryptocurrency right now are ridiculous:

  1. The fact that Bitcoin devs for 3 years cannot achieve consensus to raise the blocksize.
  2. That Ethereum needs to make a HARD FORK to change transaction fees.

So I propose that miners should vote on some parameters of the network. Miners definitely should vote on:

  • The transaction fee - If the fee is set today 1c and Waves rises 100_, it'll become $1, which would be ridiculous. We need a mechanism to adjust it fairly quickly without breaking consensus. [The same problem is if Waves falls down 100_, allowing a blockchain bloat through ridiculously cheap transactions]
  • Amount of transactions in a block

Miners would make a mandatory vote on these parameters with each block. The value for current block could be a median of 2880 last votes/blocks.

The change is relatively easy to implement.

unsafe init and config

If the testnet is the same as the production later, you should change the setup process as described at https://github.com/wavesplatform/Waves/wiki/How-to-configure-Waves-node , because the server is open to public internet access by default and before generating the API hash, so the wallet seed can be queried without an API key and other funny things can be done, like stopping the server. And you should mention, that the wallet dir and data dir in waves-testnet.json is configured in /tmp. On some Linux system the /tmp directory is deleted on reboot (or even a RAM disk), which would result in some interesting support requests, if people loses their wallets or have to re-sync the whole blockchain every time they reboot their system.

Non-valid peers

It seems like there are a couple of non-valid peers propagated through the network, e.g., IPs like 127.0.0.2 and others. Usually it helped to delete peers.dat and restart the node, but this issue should be solved anyhow...

Default value of "walletDir" and "dataDir" in the json file

The default values of the properties "walletDir": "/tmp/scorex/waves/wallet" and "dataDir": "/tmp/scorex/waves/data/"in the .json file should be changed to "/var/lib/waves/wallet" and to "dataDir": "/var/lib/waves/data/" respectively. The tmp directory is getting deleted by default in ubuntu during reboot, so the node will have to do a full sync which currently takes a few hours to complete. Thanks.

Problems running the 0.3.5 jar on a RaspberryPI

After the latest update to the 0.3.5 the jar file stopped working for me. It starts up fine, but whenever i try to reach and endpoint (e.g., /blocks/height) or the swagger UI, the node crashes with the following error:

Uncaught error from thread [wavesplatform-akka.actor.default-dispatcher-11] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[wavesplatform]
java.lang.NoClassDefFoundError: akka/http/scaladsl/marshalling/PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7$$anonfun$apply$8
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7.apply(PredefinedToResponseMarshallers.scala:60)
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7.apply(PredefinedToResponseMarshallers.scala:60)
	at scala.collection.immutable.List.map(List.scala:273)
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6.apply(PredefinedToResponseMarshallers.scala:60)
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6.apply(PredefinedToResponseMarshallers.scala:60)
	at akka.http.scaladsl.util.FastFuture$$anonfun$map$extension$1.apply(FastFuture.scala:23)
	at akka.http.scaladsl.util.FastFuture$$anonfun$map$extension$1.apply(FastFuture.scala:23)
	at akka.http.scaladsl.util.FastFuture$.akka$http$scaladsl$util$FastFuture$$strictTransform$1(FastFuture.scala:41)
	at akka.http.scaladsl.util.FastFuture$.transformWith$extension1(FastFuture.scala:45)
	at akka.http.scaladsl.util.FastFuture$.map$extension(FastFuture.scala:23)
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5.apply(PredefinedToResponseMarshallers.scala:60)
	at akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5.apply(PredefinedToResponseMarshallers.scala:59)
	at akka.http.scaladsl.marshalling.Marshaller$$anon$1.apply(Marshaller.scala:92)
	at akka.http.scaladsl.marshalling.Marshaller$$anonfun$compose$1$$anonfun$apply$15.apply(Marshaller.scala:73)
	at akka.http.scaladsl.marshalling.Marshaller$$anonfun$compose$1$$anonfun$apply$15.apply(Marshaller.scala:73)
	at akka.http.scaladsl.marshalling.Marshaller$$anon$1.apply(Marshaller.scala:92)
	at akka.http.scaladsl.marshalling.Marshal.toResponseFor(Marshal.scala:42)
	at akka.http.scaladsl.marshalling.ToResponseMarshallable$class.apply(ToResponseMarshallable.scala:17)
	at akka.http.scaladsl.marshalling.ToResponseMarshallable$$anon$1.apply(ToResponseMarshallable.scala:22)
	at akka.http.scaladsl.server.RequestContextImpl.complete(RequestContextImpl.scala:39)
	at akka.http.scaladsl.server.directives.RouteDirectives$$anonfun$complete$1.apply(RouteDirectives.scala:47)
	at akka.http.scaladsl.server.directives.RouteDirectives$$anonfun$complete$1.apply(RouteDirectives.scala:47)
	at akka.http.scaladsl.server.StandardRoute$$anon$1.apply(StandardRoute.scala:19)
	at akka.http.scaladsl.server.StandardRoute$$anon$1.apply(StandardRoute.scala:19)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.Directive$$anonfun$recover$1$$anonfun$apply$8$$anonfun$apply$9$$anonfun$apply$10.apply(Directive.scala:93)
	at akka.http.scaladsl.server.Directive$$anonfun$recover$1$$anonfun$apply$8$$anonfun$apply$9$$anonfun$apply$10.apply(Directive.scala:93)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.Directive$$anonfun$recover$1$$anonfun$apply$8.apply(Directive.scala:93)
	at akka.http.scaladsl.server.Directive$$anonfun$recover$1$$anonfun$apply$8.apply(Directive.scala:90)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:60)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:42)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:42)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1$$anonfun$apply$1.apply(RouteConcatenation.scala:47)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1$$anonfun$apply$1.apply(RouteConcatenation.scala:44)
	at akka.http.scaladsl.util.FastFuture$.akka$http$scaladsl$util$FastFuture$$strictTransform$1(FastFuture.scala:41)
	at akka.http.scaladsl.util.FastFuture$.transformWith$extension1(FastFuture.scala:45)
	at akka.http.scaladsl.util.FastFuture$.flatMap$extension(FastFuture.scala:26)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:44)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:42)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:44)
	at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:42)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResultWith$1$$anonfun$apply$4.apply(BasicDirectives.scala:66)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResultWith$1$$anonfun$apply$4.apply(BasicDirectives.scala:66)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:153)
	at akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:32)
	at akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:28)
	at akka.http.scaladsl.server.Route$$anonfun$asyncHandler$1.apply(Route.scala:73)
	at akka.http.scaladsl.server.Route$$anonfun$asyncHandler$1.apply(Route.scala:72)
	at akka.stream.impl.fusing.MapAsync$$anon$21.onPush(Ops.scala:1008)
	at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:747)
	at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:649)
	at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:471)
	at akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:423)
	at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:603)
	at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:618)
	at akka.actor.Actor$class.aroundReceive(Actor.scala:484)
	at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:529)
	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
	at akka.actor.ActorCell.invoke(ActorCell.scala:495)
	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
	at akka.dispatch.Mailbox.run(Mailbox.scala:224)
	at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
	at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
	at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
	at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: java.lang.ClassNotFoundException: akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers$$anonfun$fromStatusCodeAndHeadersAndValue$1$$anonfun$apply$5$$anonfun$apply$6$$anonfun$apply$7$$anonfun$apply$8
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 91 more
2016-11-26 09:50:27 ERROR [lt-dispatcher-9] akka.actor.ActorSystemImpl - Uncaught error from thread [wavesplatform-akka.actor.default-dispatcher-11] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled

I'm running the node with Oracle Java 8 (1.8.0_65) on Raspbian.

Here comes the config file (security related information removed) i'm using for running the node:

{
  "p2p": {
    "nodeName": "hawky-private",
    "myAddress": "jansen.myftp.org:6863",
    "bindAddress": "0.0.0.0",
    "port": 6863,
    "upnp": false,
    "upnpGatewayTimeout": 7000,
    "upnpDiscoverTimeout": 3000,
    "knownPeers": [
      "52.30.47.67:6863",
      "52.28.66.217:6863",
      "52.77.111.219:6863",
      "52.51.92.182:6863"
    ],
    "maxConnections": 30
  },
  "walletDir": "/home/pi/waves/wallet",
  "walletSeed": "",
  "walletPassword": "",
  "dataDir": "/home/pi/waves/data",
  "rpcEnabled": true,
  "rpcPort": 6869,
  "rpcAddress": "0.0.0.0",
  "blockGenerationDelay": 15000,
  "historySynchronizerTimeout": 15,
  "cors": true,
  "maxRollback": 100,
  "apiKeyHash": "9o87btrdHL6KADxA3TP7MtFdeXbBSWn2Gc7QAwQq96hx",
  "history": "blockchain",
  "offlineGeneration": false,
  "testnet": true,
  "loggingLevel": "debug",
  "genesisSignature": "4YJxQUyWx6qJYKPePN1CWjzZAbZ3rNPXZ9JteU1G9J4j2zK1Pa5LjvFtMs5ZdM8JRmZKAKqsNmLyuXjBUSCXyS8k",
  "checkpoints": {
    "publicKey": "4PvoqxpWi7kCA9N3UXcEB9CZx4iPPeHX9jSYdAioPhnr"
  }
}

I'm starting the node with: java -jar waves.jar waves-testnet.json (where waves.jar is the waves-0.3.5.jar from the releases page).

Anyone any ideas what's happening here?

Cheers
Marc

Deb packages overwriting conf file

It seems like a lot of people ran into problems since the .deb packages overwrite existing config files. I would suggest to provide a /etc/waves.json.dist file as an example and not overwrite the original config file.

Additionally, a note in the release notes for new versions about potential changes to the config file would be much appreciated. :)

walletSeed is interpreted incorrectly.

"walletSeed" is interpreted as Base58. This is incorrect. It should be interpreted in exactly the same way as in the webwallet.
For example:

"walletSeed": 4g7jtUbVJ1vpvJynsP8ZphQEt9R8eoQvbqGMzpuFmhAzSyu5kFgT7fDi92hEi1NCnzJ1M3CDLMVGvxcFZXoNXxN9
node: 3MuuBsiZjAkWETNNgY3JdQ7shy1Az8aEQ4Q
testnet.waveswallet.io: 3MySMuhh6QeN3Uejafd37WiEoZqg4PtieHb

Node should try to forge with the same address as a wallet created from that seed. Currently this is not the case.

Mandatory SEED backup

For obvious security reasons and user protection SEED backup should be mandatory in the Waves Lite Client. I suggest when importing an existing account or creating a new account the client should prompt the user to do a file back up AND to print out account recovery information on a physical printer.

generatingBalanceDepth is too small

Default generatingBalanceDepth [in file NxtLikeConsensusModule.scala] is only 50.
Default in NXT is 1440. 50 is too small and could allow an attacker [with a miniscule stake] to hijack the network.

If this is just a temporary value for testnet, then it should be:
generatingBalanceDepth = 1440 if mainnet else 50

Spending problem with partial tokens of an asset

During the test ico, i tried to also spend partial tokens (from a tokens defined with 8 digits). Nevertheless, the /assets/transfer endpoint only accepts a long value (no decimals) for the amount of tokens to transfer. On the other hand, this value does not seem to be interpreted as (amountOfTokens * 10^digits) since amounts higher than the current amount of tokens of an address yield to invalid transactions.

Very very slow sync + error

Hi,

the sync is suspiciously slow ( 12h for 100 blocks ) and I keep on getting this error :

java.lang.IllegalStateException: Chunk 102703 no longer exists [1.4.192/9]
at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:773)
at org.h2.mvstore.MVStore.getChunkIfFound(MVStore.java:951)
at org.h2.mvstore.MVStore.getChunk(MVStore.java:933)
at org.h2.mvstore.MVStore.removePage(MVStore.java:1981)
at org.h2.mvstore.MVMap.removePage(MVMap.java:1097)
at org.h2.mvstore.Page.removePage(Page.java:935)
at org.h2.mvstore.Page.copy(Page.java:307)
at org.h2.mvstore.MVMap.put(MVMap.java:119)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

I'm connected to 10+ peers and my current height is 100732

Thanks

Endpoints not responding

It seems that on machines with less than 2GB of RAM some endpoints do not respond at all or take very long time to respond, e.g., /debug/info is not working. At the same time other endpoints (e.g., /blocks/height) are working properly.

RAM requirements

The node crashes with out of memory exceptions, if it runs on a system with limited RAM, like a VPS with 2 GB RAM. But if it is started with the-Xmx1024m command line argument to the Java program
(or -J-Xmx1024m if started with the waves wrapper program), it works even on such a small system. Looks like if there is no max memory limit specified, it needs between 4 GB and 8 GB RAM. Don't know if it needs to be examined, but the RAM requirements should be at least mentioned in the docs. A few people in testnet-maintainers reported such crashes.

Array too small

From time to time, i find errors as the following in my logs:

java.lang.IllegalArgumentException: array too small: 0 < 4
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:145)
at com.google.common.primitives.Ints.fromByteArray(Ints.java:321)
at scorex.network.Handshake$$anonfun$parseBytes$1.apply(Handshake.scala:72)
at scorex.network.Handshake$$anonfun$parseBytes$1.apply(Handshake.scala:43)
at scala.util.Try$.apply(Try.scala:192)
at scorex.network.Handshake$.parseBytes(Handshake.scala:43)
at scorex.network.PeerConnectionHandler$$anonfun$handshake$1.applyOrElse(PeerConnectionHandler.scala:86)
at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:170)
at akka.actor.Actor$class.aroundReceive(Actor.scala:484)
at scorex.network.PeerConnectionHandler.aroundReceive(PeerConnectionHandler.scala:31)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
at akka.actor.ActorCell.invoke(ActorCell.scala:495)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
at akka.dispatch.Mailbox.run(Mailbox.scala:224)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)

The server seems to be working properly, even after these errors, but i think it should be checked anyway.

Transaction is not in blockchain

GET /transactions/info/{signature} returns error "Transaction is not in blockchain" for all transactions with assets (issue, transfer, reissue)

MVStore: Chunk not found

Sometimes when App loads blocks and folds them in a local database application fails and it is not starts again with the old base. The error is repeated on some OS, allegedly due to the fact that some file systems change the order of write operations and is critical for this storage.

Refers to h2database/h2database#373 #30 #205

Node doesn't detect a change in "walletSeed" automatically.

After changing "walletSeed" node still tries to forge using the previous seed.
It starts forging using a new seed only after removing wallet.s.dat.

Expected behavior is obviously to respect "walletSeed" parameter when the node starts.

Missing height from lots of calls

/transactions/info/{signature} reports height [in which block was Tx included].
Other calls [like /transactions/address/{address}/limit/{limit}] don't report that argument.

I think it should be added, it would be helpful. :-)

Testnet API needs updating

As far as I know some API issues have been fixed, but I can't see them on testnet. In particular, the node http://52.30.47.67:6869/ gives me the following.

Transfer request:

{  
   "recipient":"3N9UuGeWuDt9NfWbC5oEACHyRoeEMApXAeq",
   "timestamp":1479462208828,
   "assetId":"GAXAj8T4pSjunDqpz6Q3bit4fJJN9PD4t8AK8JZVSa5u",
   "amount":5000,
   "fee":100000,
   "senderPublicKey":"FJuErRxhV9JaFUwcYLabFK5ENvDRfyJbRz8FeVfYpBLn", 
   "signature":"4jWTZcRxuFpG4XdCbAhkiWdBjXMHEayPcEhk3yQ3oLYASJ7Fn8ij9C1nAQv61Z7Yo9DoLgy1fysGaaPGbxCWHrfT",
   "attachment":""
}

Response:
{"error":1,"message":"failed to parse json message"}

It works as expected if I use null as the attachment value (see #72)

Request to the list of last transactions API (/transactions/address/3MtMoVbAHSitzohEvd6dJGR3kmJZHSePUkS/limit/50) gives me this (omitted other tx's to be short):

{  
         "type":3,
         "id":"GAXAj8T4pSjunDqpz6Q3bit4fJJN9PD4t8AK8JZVSa5u",
         "sender":"3MtMoVbAHSitzohEvd6dJGR3kmJZHSePUkS",
         "senderPublicKey":"FJuErRxhV9JaFUwcYLabFK5ENvDRfyJbRz8FeVfYpBLn",
         "assetId":"GAXAj8T4pSjunDqpz6Q3bit4fJJN9PD4t8AK8JZVSa5u",
         "name":"4wHKwCUAGbpPVg3gk",
         "description":"ziu6bcfZ1gm5fRDb9R79HUnHMoE",
         "quantity":100000000,
         "decimals":2,
         "reissuable":true,
         "fee":100000000,
         "timestamp":1479119236120,
         "signature":"2Tc7kQDPE2LnhtkuN4CPgFaMPcdP6wUAJPaWDnZ16HcCurezt8oJPyGwo7wDGF7r7TSeEgsQXDCqDC5Qqb9z6JUu"
}

Notice the name and description fields encoding.

BTW. The transaction info request works fine (/transactions/info/GAXAj8T4pSjunDqpz6Q3bit4fJJN9PD4t8AK8JZVSa5u)

Wallet<-->Gateway communication proposal

The GatewayServer is a service that runs on a Gateway's infrastructure. It communicates with a wallet through HTTPS. Since Gateways are centralized, it makes no sense to use a decentralized communication protocol between Wallet<->Gateway.

Wallet needs an easy way to facilitate things like KYC/AML or registering the deposit account for user. GatewayServer makes it easy to integrate this process directly into the wallet.

Wallet

When the user is registering to the Gateway, the wallet reads the latest "Subscribe to Gateway" transaction. This transaction points user to the https://gateway.com/v1/details file that describes the plugin.
The plugin is also loaded every time the user opens a wallet. Wallet reads all PluginRegistered transactions and installs all plugins during runtime.

Plugin

A gateway's plugin is a lightweight json file that is pretty inflexible. The only actions that can be performed in the plugin are:

  • Registering the asset as a currency [ex. USD] plugin.
  • One-time greeting message.
  • Small messages in the footer, maybe some message list for that particular asset.
  • Adding buttons to the currency/asset, such as "Deposit", "Withdraw", "Perform KYC", "Change settings".

After the button is pressed, the user is presented with a form in a modal window. Modal window is a sandboxed iframe that is communicating directly with the Gateway.

GatewayServer

The GatewayServer serves as a middleware between a Wallet and a Gateway's internal workings. On the wallet side the GatewayServer will expose:

  • HTTPS Rest API, used for all of the communication with the Wallet.
  • iframes with forms presented to the user.

I propose that we write the GatewayServer in Python.

  1. It's a very popular language, definitely more popular than Scala.
  2. It's extremely easy to extend. GatewayServer can be configured so that just dropping a folder inside a GatewayServer extends it's functionality.
  3. Python is my favorite language. It has a sexy syntax. :-P

Though Java is also ok due to it's unparalleled popularity.

Off-chain communication API:

Secure Limited Markdown

A stripped version of Markdown that is secure against XSS attacks.

Sandboxed iframe

Forms&messages displayed by Gateways are presented in the form of iframe modal windows. Every time a user clicks a Gateway-specific button, a modal window with an iframe is loaded.
IFrame communicates with the wallet through postMessage API.

Messages

Do we need a centralized messaging system? Should we ask a Gateway periodically if it has some messages to display to the user?
This is an anonymity breach IMO [Gateway knows when the user opens/closes his wallet every time], that's why I'm reluctant to include this...
It can be implemented later if it's needed.

Authentication challenge

We need for the client to be able to reliably authenticate itself with the GatewayServer.
This method must:

  1. Use existing keys from the blockchain.
  2. Be resistant to key-repetition attack.
  3. Preferably it shouldn't need any authentication.

We don't want Gateway to spy on it's clients. That's why the wallet needs to cache it's buttons by default and ask for changes only when a button is pressed.

GatewayServer<->Wallet API:

Every message between Gateway<-->Wallet is encrypted with HTTPS and it's additionally signed with Curve25519 of the issuer and Wallet.
Thus, MITM with a spoofed HTTPS key [NSA] can only read communication from&to Gateway, it cannot spoof it. To spoof such communication requires a GAC_private_key to become compromised.

Wallet Authentication Challenge - WAC headers

To authenticate itself to the GatewayServer, the Wallet uses HTTP header parameters. The parameters are as follows:

"asset_id": "FYNEWP6uuaM53hCHuJzj8dw2zamoipokZpKQLNFZLVmP", # GatewayServer's asset ID
"public_key": "FkoFqtAeibv2E6Y86ZDRfAkZz61LwUMjLAP2gmS1j7xe", # Wallet's address public key - Base58
"gateway_public_key": "zkweWR234SZFzbiorj5t5BFCBOetepo4gkdbzZA2342a",
"timestamp": 192831989048, # Unix time with millisecond resolution
"auth_hash": "Blake2b256 hash" # MAC that authenticates the message and the wallet

gateway_public_key is the public key taken from the GAC_private_key. It's the same key that is published on the blockchain with "Asset details" transaction.

Auth_hash is calculated as follows: blake2b256(asset_id(256bit)+public_key(256bit)+timestamp(64bit)+CONTENT)

We're protecting ourselves against replay attacks by having GatewayServer accept only newer timestamps. If wallet_nonce.timestamp <= last_known_timestamp or auth_hash is incorrect, GatewayServer ignores the request.

Ajax API

Every message is GAC and WAC protected.

Description Call: GET - /v1/details

WAC_headers
Response:

{
    "description": "This is a super duper BTC Gateway! Please enter <KYC> to continue.",
    "icon": "https://gateway.com/icon.png",
    "version": 1,
    "interactive": true
}

"description" - this is an asset description. It's shown when the user clicks on an asset. 100kB is the limit. It's a Secure Limited Markdown.
"version" - API version supported by the GatewayServer. The wallet will use the newest version it understands.
"interactive" - This call informs the Wallet if this is a static .json file [false], or is it a live GatewayServer [true]. If it's a live GatewayServer, the wallet will continue interaction with GatewayServer with the API's below.
"icon" - Small icon representing the asset. Everyone loves icons.

The description is shown when the user is presented with an asset in a wallet. It's a greeting from an asset issuer describing the asset and what it does.

Register Call: POST - /v1/register/

WAC_headers
Request:

{
    "subscribe_to_gateway_timestamp": 18273891728947129,
    "subscribe_to_gateway_recipient_signature": "af934nuv8ajwdfnvhuwvhiuawv74yn87v"
}

"subscribe_to_gateway_timestamp" - Timestamp for "Subscribe to Gateway" transaction. Optional.
"subscribe_to_gateway_recipient_signature" - Recipient signature for "Subscribe to Gateway" transaction. Optional.

Response:

{
    "greeting": "greeting",
    "asset_details_message": "SecureMarkdown",
    "buttons": [
        {
            "name": "KYC",
            "description": "To start using this gateway you must first fill the KYC",
            "iframe": "kyc",
            "main_page": 1
        },
        {
            "name": "Deposit",
            "description": "Deposit money to the gateway",
            "iframe": "deposit"
            "main_page": 2
        },
        {
            "name": "Withdraw",
            "description": "Withdraw money from the gateway",
            "iframe": "withdraw"
            "main_page": 3
        },
        {
            "name": "Convert",
            "description": "Convert money from one currency to the other",
            "iframe": "convert"
        },
        {
            "name": "Loan",
            "description": "Fill a form and take a loan",
            "iframe": "loan"
        }
    ]
}

"greeting" - optional - Presents a greeting from the Gateway [iframe modal] just after the asset is registered. The iframe points to "{$asset_details_tx_url}/v1/forms/{$greeting}" specifically.
"asset_details_message" - optional - A Secure Markdown message that is displayed on "Asset Details" page, just below asset_id, balance and whatnot info.

"buttons" - Buttons that are displayed on "Assetransferred to his "Assets" page. The Asset is displayed t Details" page in the Wallet. The buttons are ordered as they appear in the "Asset Details" page.
"name" - Name of the button. Should be short [< 16 chars], preferably one word.
"description" - Short description of a button.
"main_page" - optional, int - Should the button be displayed on the main page of the wallet? [As one of up to 3 default buttons - 1 - left, 2 - center, 3 - right]
"iframe" - The iframe points to "{$asset_details_tx_url}/v1/forms/{$iframe}" specifically.

This call is used to register the Wallet with the Gateway. This method is called when the user accepts the asset. The "Subscribe to gateway" transaction can be sent by the Gateway if the Wallet wants it to.

Form Call: iframe - /v1/forms/$form_name?WAC_headers

These calls will be done through iframes, so we have to rely on GET method to carry WAC headers.

Response:
A web page from the Gateway containing the particular form.
A form call should contain some logic for communicating with the Wallet [through postMessage]. The iframe at least needs to inform when it should be closed...

Form<-->Wallet API:

I'm not familiar with postMessage capabilities, so this part will be less detailed.
The messages we need include:

  • Close the modal window
  • Ask the Gateway again for Buttons

Blockchain transactions:

Asset details

SPEC: [sender, asset_id, GatewayServer_api_URL, GAC_public_key, sender_signature]
This transaction is sent by an address that issued or has owner rights to the asset. It specifies the API of the GatewayServer of particular asset.
It can be pointed to a static .json file for assets that just want a fancy description, but don't need any of the GatewayServer's features.
GatewayServer_api_URL. If the URL doesn't start with "https://", the transaction is invalid.
if sender.is_an_issuer(asset_id): transaction_is_not_valid
Only the newest Asset details transaction is taken into account when wallet engages the Gateway, all older ones are ignored. This transaction can be prunable.
GAC_public_key is a key that is used by the Wallet to make sure that it's really talking to the Gateway. It's different from an issuer account public key because it's impossible to keep this key in cold storage - GAC_public_key has to be running on a live server 24/7, thus it's exposed to compromise.

Transfer asset issuer rights

SPEC: [sender, recipient, asset_id, sender_signature]
This transaction transfers privileges of an asset issuer [ex. Asset Details Transaction] to a new account.
After this transaction is made, the old "Asset details transaction" is still valid until the newer one is generated. [Even though it's on an older account]

Subscribe to Gateway

SPEC: [sender, recipient, asset_id, sender_signature, recipient_signature]
This transaction informs the Wallet that it's subscribed to the particular gateway.
For user's convenience the Gateway pays the transaction fee. The user may have 0 Waves in his account right now.

Unsubscribe from the Gateway

SPEC: [sender, asset_id, sender_signature]

The user experience:

ITB - In the background

  1. User clicks on the asset of the gateway [for example through the link from the Gateway's website: waves://assets/18731273194817823713].
  2. The user is greeted with an asset page, pretty similar to NXT's asset pages.
    ITB - 0.5s: Wallet requests Asset Details transaction from the node.
    ITB - 0.5s: Wallet requests Description Call from the Gateway.
    ITB - 0.5s: Wallet parses Secure Limited Markdown. Wallet downloads all prerequisite images.
  3. The user is presented with a full-fledged asset description with logos and whatnot.
  4. The user clicks on "Register asset" button.
    ITB - 0.5s: Wallet requests "Register Call".
    ITB - 0.5s: Wallet opens a modal with an iframe with "greetingskyc" form.
  5. The user is presented with a greeting&KYC form.
  6. The user fills his KYC form.
    ITB - Iframe sends a postMessage to the Wallet - close the iframe & resend register call
  7. The iframe closes.
    ITB - 0.5s: Wallet requests "Register Call" from the Gateway.
  8. User is presented with new buttons.
  9. User clicks on a "Deposit" button.
    ...

It is also possible to make a live help chat through iframes with the Gateway.

Things to consider:

Maybe we should ask Gateway for "Register Call" every time? The Wallet may be waiting for KYC confirmation for example...

maxConnections is not being respected on some nodes

I have 4 nodes running Release0 v0.2.3-SNAPSHOT that have specified "maxConnections": 20, but have > 45 nodes connected to them. [checked using /peers/connected API]

Most of these connections are inbound, only few are outbound. Is this intentional?

Critical : Node not syncing

Hi,

My node is not syncing for more than 12 hours, I tried to restart it, delete and regenerate wallet.dat and a seed and nothing works. My node is stuck at the height 100777

On the swagger UI I did the GET /debug/state && GET /debug/info and here are the logs :

java.lang.IllegalArgumentException: requirement failed: accountChanges(3MpErnxpibaoH7uoMAH7cbSekaRX2iFVfVm).get(100776) is null. lastStates.get(address)=100776
at scala.Predef$.require(Predef.scala:224)
at scorex.transaction.state.database.blockchain.StoredState.loop$1(StoredState.scala:126)
at scorex.transaction.state.database.blockchain.StoredState.scorex$transaction$state$database$blockchain$StoredState$$balanceByAddress(StoredState.scala:131)

The trace is much longer and I can provide it in full if requested.

Thanks

Documentation for the /asset/issue endpoint

According to SimpleTransactionModule.issueAsset, it seems like assedItOpt, name and descritption need to be Base58 encoded strings. This should be obvious from the documentation of the endpoint.

Furthermore, the documentation of the endpoint describes the decimals field as a string, which should actually be an int.

Empty attachment is not allowed in asset transfer tx API

Hello,

If I trying to transfer assets with this json:

{
  "recipient": "3NAf58V1VT7zF2PudxjMQjJbXgBM8idqAWi",
  "assetIdOpt": "8kpmPAy1pjyy16iaNMENvKYyFzfFvaFGBLTBC5nAvvba",
  "feeAsset": "",
  "feeAmount": 1000,
  "amount": 100000000,
  "attachment": "",
  "sender": "3N5LA4aaw4hrSGq5w1xMXsryXxB7s7WHFwp"
}

I get error status 400:

{
  "error": 1,
  "message": "failed to parse json message"
}

This code make transfer:

{
  "recipient": "3NAf58V1VT7zF2PudxjMQjJbXgBM8idqAWi",
  "assetIdOpt": "8kpmPAy1pjyy16iaNMENvKYyFzfFvaFGBLTBC5nAvvba",
  "feeAsset": null,
  "feeAmount": 1000,
  "amount": 100000000,
  "attachment": "3N5LA4aaw4hrSGq5w1xMXsryXxB7s7WHFwp",
  "sender": "3N5LA4aaw4hrSGq5w1xMXsryXxB7s7WHFwp"
}

Endpoints answering with swagger ui source code

the following endpoints answer with the swagger ui itself (it’s source code) if you enter negative numbers as inputs:

http:///addresses/seq/123123123/-123123125
http:///blocks/at/-123123123123123123
http:///blocks/seq/-1212/10
http:///debug/state/-123
http:///debug/blocks/-121231231
http:///transactions/address/3Mvtz6QNaxBgS2o8nBkJLhaeDKE38U8V68Y/limit/12123123123

HTTPS + strong passwords

  • Will the Swagger websites of the nodes be made more secure by making it https instead of http?
    As password now go in clear text.
  • Will strong passwords be fixed? As we now can set normal characters only, and no special characters. (So no @#€&$~= etc. )

Thanks,

Clipto
wavesnode.net

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.