Giter Site home page Giter Site logo

faucet's Introduction

Faucet

Your friendly transaction-happy bot

Description

Faucet's goal is to generate transactions for the POC Agora Blockchain network. This involves a broad array of use cases:

  • As a test tool, it can generate transaction in test setups;
  • As the name suggest, it can also be used as a faucet for TestNet;
  • As a stress-test tool targeting specific attack;

Faucet is available on the docker registry.

faucet's People

Contributors

andrejmitrovic avatar geod24 avatar hewison-chris avatar omerfirmak avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar

faucet's Issues

Find the source of crashes in the live system

Currently, we have a workaround in place to work around a weird behavior observed in the live system: an assert which should only be triggered far into the future by our calculation fires after roughly 100 transactions. That's very unexpected, and a sign that something else is wrong.

We need to find why it actually asserts (how do we end up with a 0 output), if it makes sense, and eventually fix it.

Timer callback fails

With;

Feb 04 07:07:39 eu-001.bosagora.io docker[975018]: 2022-02-04 07:07:39,297 Info [faucet.main] -         L: 594499999843900, H: 595000000000000
Feb 04 07:07:39 eu-001.bosagora.io docker[975018]: 2022-02-04 07:07:39,390 Error [faucet.main] - Insufficient UTXOs in storage. # of UTXOs: 1
Feb 04 07:07:39 eu-001.bosagora.io docker[975018]: Timer callback failed: Orphan format arguments: args[0..1]
Feb 04 07:07:44 eu-001.bosagora.io docker[975018]: 2022-02-04 07:07:44,223 Info [faucet.main] - About to send transactions...
Feb 04 07:07:44 eu-001.bosagora.io docker[975018]: 2022-02-04 07:07:44,224 Info [faucet.main] -         UTXO set: 8/57 UTXOs are owned by Faucet

Expose a basic API

Faucet should expose a basic API so it can be called from a frontend service (website) to make Transactions.
Additionally, some functionality could be useful for debugging or management.

The basic API is comprised of:

  • GET /utxos => Return an array of all UTXOs known;
  • POST /send?recv=KEY&amount=1234: Send amount BOA to KEY, using owned UTXOs;

Once this is in place, it can be extended as needed.

Agora node stops receiving transactions

The faucet continuously sends transactions, but the agora node stops receiving them at some point.
This usually happens around mid-30 blocks.
It may be related to combineCandidates.

Add monitoring endpoint

Currently we have no overview on what Faucet is doing, e.g. how many transactions it sends / minute, or even if it is running at all. This needs to be changed to work like Agora (prometheus endpoint) and be added to our Grafana.

Expand the transaction generator to sometimes merge UTXOs

Currently, Faucet will forever split the outputs among keys.
This is a very predictable behavior that does not reflect a live settings.

We currently only have the following variables:

  • Interval: how often we send
  • Count: How many transactions we generate per run

What we don't have is a way to control the structure of the transactions. We don't need to send homogenous transactions, and we definitely need to send transactions what will "merge" UTXOs (have inputs.length > outputs.length) as opposed to the current approach of always "splitting" (inputs.length < outputs.length).

Use the configured keypair for `TxBuilder`

Currently, we read seeds from the config file, but do not use them.
Since the TxBuilder supports it, we should start using them, but keep a backward-compatibility option to use the WK ones (especially for the integration tests of Agora).

Faucet no longer works in single Agora test node setup

When testing with a limited set of the test validators the Test Genesis Block must only include the validators in that set. The single node setup, which is useful to quickly test Faucet with a single Agora node, was broken when the ledger was added to the Faucet.

Faucet is very slow to exit

Just noticed that starting faucet, then pressing Ctrl + C leads to a few seconds delay before it actually exits.
Agora is much faster to exit, so there might be something off at play here.

Build a frontend for Faucet

This could potentially be a separate project.

We need to have a simple frontend for users to ask for coins.

It should include the following feature:

  • Have a field to input a public key (and verify its consistency);
  • Have a mean to identify the user (e.g. email verification + token);

Give the user the txid once the tx has been send (and in the future, a link to the block explorer).

Listen to HTTP requests

Some API endpoints have been implemented and a port number has been assigned.
Now faucet needs to listen to HTTP requests so that the endpoints can be called.
e.g. http://127.0.0.1:2766/utxos

Prevent sending coins when there is less than one UTXO

Attempting to use the last UTXO results in an assertion error. There would be no UTXOs left if that one was used.
The faucet should check the number of UTXOs before sending and prevent sending if there is only one .
The log is very clear :

Jun 28 05:12:55 eu-001.bosagora.io docker[537610]: [main(gbGR) INF] About to send transactions...
Jun 28 05:12:55 eu-001.bosagora.io docker[537610]: [main(gbGR) INF]         UTXO set: 31 entries
Jun 28 05:12:55 eu-001.bosagora.io docker[537610]: [main(gbGR) INF]         Median: 180740740740740, Avg: 157419354838709
Jun 28 05:12:55 eu-001.bosagora.io docker[537610]: [main(gbGR) INF]         L: 2, H: 542222222222222
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF] Updating state: blocks [530 .. 530] (1)
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF] UTXO delta: -30
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF] About to send transactions...
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF]         UTXO set: 1 entries
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF]         Median: 4880000000000000, Avg: 4880000000000000
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(yZVg) INF]         L: 4880000000000000, H: 4880000000000000
Jun 28 05:13:00 eu-001.bosagora.io docker[537610]: [main(EE3r) INF] Sending 100 BOA to boa1xpy00m8r9qpmkh8zznkn3jc9w9n3t6x3wdzx4sdsd9xqjk3m0dwzx9ecvul
Jun 28 05:13:02 eu-001.bosagora.io docker[537610]: core.exception.AssertError@/usr/include/d/std/algorithm/iteration.d(1408): Attempting to fetch the front of an empty filter.

The `Average` amount in `send()` is broken

It shows 0 because it is not calculated properly.

Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF] Updating state: blocks [5440 .. 5440] (1)
Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF] UTXO delta: 81
Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF] About to send transactions...
Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF]         UTXO set: 179 entries
Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF]         Median: 48795177417, Avg: 0
Aug 30 05:30:52 eu-001.bosagora.io docker[244901]: [main(j6eP) INF]         L: 10224522, H: 3988242477544347

Implement "Create validator stake" button

Name up for discussion.

Essentially, a button that, when clicked, generates a frozen output of 40,000 BOA to the provided address.
This might be more easily abused than the test BOA (since it's 400x more BOAs), so perhaps we'll need to mitigate it in the future, but for now, let's just make it work.

Make Faucet easier to configure and improve logging

Currently configuring Faucet to get a range of transactions per block is not very easy.
This is not helped by the fact that what we log by default is not helpful in determining what it is actually doing.

Faucet does not respond to Ctrl+C / Ctrl+\ when running in docker

Run:

$ docker run -it bpfk/faucet http://127.0.0.1:2826

Press either Ctrl+C or Ctrl+\, and provided you don't have a weird shell config, it should send SIGQUIT or SIGKILL (respectively) to Docker, which then forwards it to faucet. However this doesn't seem to have an effect.

Merging transactions is broken

When mergeTx is called, the transaction is rejected with the following log:

Rejected tx. Reason: LockType.Key signature in unlock script failed validation.

Faucet needs to be restarted sometimes to find utxo

If the Faucet has no utxo to send and the last block was empty then it will remain waiting for utxo. After a restart it does find utxo and can recover. It should not need to be restarted to keep up to date with utxo.

'An Exception occured' if someone inputs a private key instead of a public key

Screen Shot 2022-02-09 at 10 51 35

This is not very helpful.

% curl 'https://faucet.bosagora.io/stake' \
  -H 'authority: faucet.bosagora.io' \
  -H 'sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"' \
  -H 'dnt: 1' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' \
  -H 'content-type: application/json' \
  -H 'accept: */*' \
  -H 'x-requested-with: XMLHttpRequest' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'origin: https://faucet.bosagora.io' \
  -H 'sec-fetch-site: same-origin' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-dest: empty' \
  -H 'referer: https://faucet.bosagora.io/index.html' \
  -H 'accept-language: en-US,en;q=0.9,fr-FR;q=0.8,fr;q=0.7,ko;q=0.6' \
  --data-raw '{"recv":"SB3EENDWPUGQZL7KLWGJS2ILMGRBB2MLVLRBUVKDYTO6A4WYLPIQWEE3"}' \
  --compressed
{"statusMessage":"An Exception occured","statusDebugMessage":"agora.common.Ensure.FormattedException@submodules/agora/source/agora/crypto/Bech32.d(140): Invalid HRP for Bech32: SB3EENDWPUGQZL7KLWGJS2ILMGRBB2MLVLRBUVKDYTO6A4WYLPIQWEE3 (pos: -1)\n----------------\nsubmodules/agora/source/agora/common/Ensure.d:102 @safe void agora.common.Ensure.ensure!(const(char)[], long).ensure(bool, immutable(char)[], lazy const(char)[], lazy long, immutable(char)[], int) [0x55ac009c0920]\nsubmodules/agora/source/agora/crypto/Bech32.d:127 @safe agora.crypto.Bech32.DecodeResult agora.crypto.Bech32.decodeBech32(in char[]) [0x55ac009c0070]\nsubmodules/agora/source/agora/crypto/Key.d:186 @trusted agora.crypto.Key.PublicKey agora.crypto.Key.PublicKey.fromString(scope const(char)[]) [0x55ac006ec610]\nsource/faucet/main.d:496 @safe void faucet.main.Faucet.sendTo(immutable(char)[], bool) [0x55ac009cde10]\nsource/faucet/main.d:491 @safe void faucet.main.Faucet.createValidatorStake(immutable(char)[]) [0x55ac00914dd0]\nsubmodules/agora/submodules/vibe.d/web/vibe/web/rest.d:1463 @safe void vibe.web.rest.jsonMethodHandler!(faucet.API.FaucetAPI.createValidatorStake(immutable(char)[]), 2uL, faucet.main.Faucet).jsonMethodHandler(faucet.main.Faucet, ref vibe.web.internal.rest.common.RestInterface!(faucet.main.Faucet).RestInterface).handler(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse) [0x55ac009141e0]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/router.d:211 /usr/bin/faucet [0x55ac008ab1a0]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/router.d:718 const @safe bool vibe.http.router.MatchTree!(vibe.http.router.Route).MatchTree.doMatch(immutable(char)[], scope bool delegate(ulong, scope immutable(char)[][]) @safe) [0x55ac008af730]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/router.d:662 @safe bool vibe.http.router.MatchTree!(vibe.http.router.Route).MatchTree.match(immutable(char)[], scope bool delegate(ulong, scope immutable(char)[][]) @safe) [0x55ac008ab140]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/router.d:194 @safe void vibe.http.router.URLRouter.handleRequest(vibe.http.server.HTTPServerRequest, vibe.http.server.HTTPServerResponse) [0x55ac008aab40]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/server.d:2100 @safe bool vibe.http.server.handleRequest(vibe.internal.interfaceproxy.InterfaceProxy!(vibe.core.stream.Stream).InterfaceProxy, vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext, ref vibe.http.server.HTTPServerSettings, ref bool, scope stdx.allocator.IAllocator) [0x55ac00899070]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/server.d:245 /usr/bin/faucet [0x55ac00898f00]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/server.d:196 @safe void vibe.http.server.handleHTTPConnection(vibe.core.net.TCPConnection, vibe.http.server.HTTPServerContext) [0x55ac008983b0]\nsubmodules/agora/submodules/vibe.d/http/vibe/http/server.d:2042 /usr/bin/faucet [0x55ac008a3010]\nsubmodules/agora/submodules/vibe-core/source/vibe/core/task.d:708 nothrow void vibe.core.task.TaskFuncInfo.set!(void delegate(vibe.core.net.TCPConnection) nothrow @safe, vibe.core.net.TCPConnection).set(ref void delegate(vibe.core.net.TCPConnection) nothrow @safe, ref vibe.core.net.TCPConnection).callDelegate(ref vibe.core.task.TaskFuncInfo) [0x55ac008213f0]\nsubmodules/agora/submodules/vibe-core/source/vibe/core/task.d:737 void vibe.core.task.TaskFuncInfo.call() [0x55ac0081f890]\nsubmodules/agora/submodules/vibe-core/source/vibe/core/task.d:403 nothrow void vibe.core.task.TaskFiber.run() [0x55ac0081ec10]\n??:? void core.thread.context.Callable.opCall() [0x7f05bc3e2710]\n??:? void core.thread.fiber.Fiber.run() [0x7f05bc3e2900]\n??:? fiber_entryPoint [0x7f05bc3e27c0]"}%

`Faucet` is sending excessive number of `double spend transactions`

When Faucet is creating transactions it is creating many using the same utxo, which results in Agora rejecting them, as they are double spend without an increased fee. This is the correct behavior for Agora but it would be desirable to not get a flood of warning in the log output of Agora when running tests.

`getOwnedUTXOs().length` assert(0)

The faucet is unable to retrieve its owned UTXOs. This error prevents the faucet from sending additional transactions.

core.exception.AssertError@source/faucet/main.d(176): Assertion failure
----------------
??:? _d_assert [0x105071407]
??:? @safe bool faucet.main.State.update(agora.api.FullNode.API, agora.common.Types.Height) [0x104f37cba]
??:? void faucet.main.Faucet.send() [0x104f38623]
??:? void faucet.main.main(immutable(char)[][]).__lambda21() [0x104f3a988]
??:? nothrow @safe void vibe.core.core.setTimer(core.time.Duration, void delegate(), bool).__lambda4() [0x104c2ef43]
??:? nothrow @safe void vibe.core.core.createTimer(void delegate() nothrow @safe).C.opCall(vibe.core.core.Timer).__lambda2(vibe.core.core.Timer) [0x104c2f281]
??:? nothrow void vibe.core.task.TaskFuncInfo.set!(void delegate(vibe.core.core.Timer) nothrow @safe, vibe.core.core.Timer).set(ref void delegate(vibe.core.core.Timer) nothrow @safe, ref vibe.core.core.Timer).callDelegate(ref vibe.core.task.TaskFuncInfo) [0x104c6ece5]
??:? void vibe.core.task.TaskFuncInfo.call() [0x104c6c34b]
??:? nothrow void vibe.core.task.TaskFiber.run() [0x104c6b898]
??:? fiber_entryPoint [0x10508ea23]

Fix docker integration

Currently, docker integration doesn't work, and complains about a non-existent commit in a subdirectory.
We need to fix this so that builds are correctly pushed and can be deployed.

Properly send coins in faucet frontend

The "send" button in the faucet frontend is not sending coins properly, most likely due to the query parameter type.
The code has to be fixed so that the coins are properly sent to the recipient.

The following error is shown:

{"statusMessage":"Missing non-optional query parameter 'recv'."}

owned_utxos not modified at sendTransaction

what if someone quickly request 100 and then again 100 BOA before the new block is created?

auto owned_utxo_rng = this.state.owned_utxos.byKeyValue()

I don't see that we are deleting the used UTXO from the this.state.owned_utxos map, I only see some calls to popFront on the owned_utxo_rng variable that will not prevent us from trying to spend the same UTXO again.

Also owned_utxo_rng = this.state.owned_utxos.byKeyValue() is not really random, but called owned_utxo_rng :)

Migrate tool into repository

The tool in agora needs to be migrated into this repository.

Definition of done:

  • dub: Organize submodules and dependencies
  • UTXO: Use TestUTXOSet instead of UTXOSet, implement updateUTXOCache
  • agora#1286 (?)

Part of agora#1227

Std.json.JSONException occurs when running

henry@BOSAGORA ~/work/boa/Github/faucet (git)-[v0.x.x] % ./bin/faucet http://eu-002.bosagora.io:2826
[main(----) INF] The address of node is http://eu-002.bosagora.io:2826
Exception while connecting: std.json.JSONException@../../../../.dub/packages/vibe-d-0.9.2/vibe-d/data/vibe/data/json.d(1824): Expected JSON object, got string
----------------
??:? pure @safe void std.exception.bailOut!(std.json.JSONException).bailOut(immutable(char)[], ulong, scope const(char)[]) [0x106b41818]
??:? pure @safe bool std.exception.enforce!(std.json.JSONException).enforce!(bool).enforce(bool, lazy const(char)[], immutable(char)[], ulong) [0x106b41725]
??:? pure @safe void vibe.data.json.enforceJson!("../../../../.dub/packages/vibe-d-0.9.2/vibe-d/data/vibe/data/json.d", 1824uL).enforceJson(bool, lazy immutable(char)[]) [0x106b7bed1]
??:? @safe void vibe.data.json.JsonSerializer.readDictionary!(vibe.data.serialization.Traits!(agora.common.BitField.BitField!(uint).BitField, vibe.data.serialization.DefaultPolicy).Traits).readDictionary(scope void delegate(immutable(char)[]) @safe) [0x106b81c54]
??:? @safe agora.common.BitField.BitField!(uint).BitField vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(agora.common.BitField.BitField!(uint).BitField).deserializeValueDeduced(ref vibe.data.json.JsonSerializer) [0x106b81b8c]
??:? @safe agora.common.BitField.BitField!(uint).BitField vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValue!(agora.common.BitField.BitField!(uint).BitField).deserializeValue(ref vibe.data.json.JsonSerializer) [0x106b8124c]
??:? @safe void vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(agora.consensus.data.Block.BlockHeader).deserializeValueDeduced(ref vibe.data.json.JsonSerializer).__lambda2!(immutable(char)[]).__lambda2(immutable(char)[]) [0x106b80f46]
??:? @safe int vibe.data.json.JsonSerializer.readDictionary!(vibe.data.serialization.Traits!(agora.consensus.data.Block.BlockHeader, vibe.data.serialization.DefaultPolicy).Traits).readDictionary(scope void delegate(immutable(char)[]) @safe).__foreachbody3(ref immutable(char)[], ref vibe.data.json.Json) [0x106b81585]
??:? _aaApply2 [0x1070fd91d]
??:? @safe void vibe.data.json.JsonSerializer.readDictionary!(vibe.data.serialization.Traits!(agora.consensus.data.Block.BlockHeader, vibe.data.serialization.DefaultPolicy).Traits).readDictionary(scope void delegate(immutable(char)[]) @safe) [0x106b80c5f]
??:? @safe agora.consensus.data.Block.BlockHeader vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(agora.consensus.data.Block.BlockHeader).deserializeValueDeduced(ref vibe.data.json.JsonSerializer) [0x106b80910]
??:? @safe agora.consensus.data.Block.BlockHeader vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValue!(agora.consensus.data.Block.BlockHeader).deserializeValue(ref vibe.data.json.JsonSerializer) [0x106b80533]
??:? @safe void vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(agora.consensus.data.Block.Block).deserializeValueDeduced(ref vibe.data.json.JsonSerializer).__lambda2!(immutable(char)[]).__lambda2(immutable(char)[]) [0x106b8039c]
??:? @safe int vibe.data.json.JsonSerializer.readDictionary!(vibe.data.serialization.Traits!(agora.consensus.data.Block.Block, vibe.data.serialization.DefaultPolicy).Traits).readDictionary(scope void delegate(immutable(char)[]) @safe).__foreachbody3(ref immutable(char)[], ref vibe.data.json.Json) [0x106b80825]
??:? _aaApply2 [0x1070fd91d]
??:? @safe void vibe.data.json.JsonSerializer.readDictionary!(vibe.data.serialization.Traits!(agora.consensus.data.Block.Block, vibe.data.serialization.DefaultPolicy).Traits).readDictionary(scope void delegate(immutable(char)[]) @safe) [0x106b802af]
??:? @safe agora.consensus.data.Block.Block vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(agora.consensus.data.Block.Block).deserializeValueDeduced(ref vibe.data.json.JsonSerializer) [0x106b8009d]
??:? @safe agora.consensus.data.Block.Block vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValue!(agora.consensus.data.Block.Block).deserializeValue(ref vibe.data.json.JsonSerializer) [0x106b7ffc3]
??:? @safe const(agora.consensus.data.Block.Block) vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(const(agora.consensus.data.Block.Block)).deserializeValueDeduced(ref vibe.data.json.JsonSerializer) [0x106b7ff61]
??:? @safe const(agora.consensus.data.Block.Block) vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValue!(const(agora.consensus.data.Block.Block)).deserializeValue(ref vibe.data.json.JsonSerializer) [0x106b7fb63]
??:? @safe void vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(const(agora.consensus.data.Block.Block)[]).deserializeValueDeduced(ref vibe.data.json.JsonSerializer).__lambda3() [0x106b7fabd]
??:? @safe void vibe.data.json.JsonSerializer.readArray!(vibe.data.serialization.Traits!(const(agora.consensus.data.Block.Block)[], vibe.data.serialization.DefaultPolicy).Traits).readArray(scope void delegate(ulong) @safe, scope void delegate() @safe) [0x106b7f9bc]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValueDeduced!(const(agora.consensus.data.Block.Block)[]).deserializeValueDeduced(ref vibe.data.json.JsonSerializer) [0x106b7f85f]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.data.serialization.deserializeValueImpl!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy).deserializeValue!(const(agora.consensus.data.Block.Block)[]).deserializeValue(ref vibe.data.json.JsonSerializer) [0x106b7f808]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.data.serialization.deserializeWithPolicy!(vibe.data.json.JsonSerializer, vibe.data.serialization.DefaultPolicy, const(agora.consensus.data.Block.Block)[], vibe.data.json.Json).deserializeWithPolicy(vibe.data.json.Json) [0x106b7f7eb]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.data.serialization.deserialize!(vibe.data.json.JsonSerializer, const(agora.consensus.data.Block.Block)[], vibe.data.json.Json).deserialize(vibe.data.json.Json) [0x106b7f779]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.data.json.deserializeJson!(const(agora.consensus.data.Block.Block)[]).deserializeJson(vibe.data.json.Json) [0x106b7f419]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.web.rest.executeClientMethod!(agora.api.FullNode.API, 4, vibe.web.rest.RestInterfaceClient!(agora.api.FullNode.API).RestInterfaceClient.__mixin24.getBlocksFrom(ulong, uint).block_height, vibe.web.rest.RestInterfaceClient!(agora.api.FullNode.API).RestInterfaceClient.__mixin24.getBlocksFrom(ulong, uint).max_blocks).executeClientMethod(scope ref const(vibe.web.internal.rest.common.RestInterface!(agora.api.FullNode.API).RestInterface), void delegate(vibe.http.client.HTTPClientRequest) @safe, scope void delegate(vibe.http.client.HTTPClientRequest, scope vibe.core.stream.InputStream) @safe) [0x106b6870d]
??:? @safe const(agora.consensus.data.Block.Block)[] vibe.web.rest.RestInterfaceClient!(agora.api.FullNode.API).RestInterfaceClient.__mixin24.getBlocksFrom(ulong, uint) [0x106b680f1]
??:? @safe bool faucet.main.State.update(agora.api.FullNode.API, agora.common.Types.Height) [0x106b9029b]
??:? void faucet.main.setup(ref faucet.main.State, agora.api.FullNode.API, uint) [0x106b9098b]
??:? _Dmain [0x106b91415]
Usage: ./faucet <address>
Where <address> is a http endpoint, such as 'http://192.168.0.42:8080'

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.