* [marketplace] get active slots from chain
# Conflicts:
# codex/contracts/market.nim
* [marketplace] make on chain event callbacks async
# Conflicts:
# tests/codex/helpers/mockmarket.nim
* [marketplace] make availability optional for node restart
# Conflicts:
# tests/codex/testsales.nim
* [marketplace] add async state machine
Allows for `enterAsync` to be cancelled.
* [marketplace] move sale process to async state machine
* [marketplace] sales state machine tests
* bump dagger-contracts
* [marketplace] fix ci issue with chronicles output
* PR comments
- add slotIndex to `SalesAgent` constructor
- remove `SalesAgent.init`
- rename `SalesAgent.init` to `start` and `SalesAgent.deinit` to `stop`.
- rename `SalesAgent. populateRequest` to `SalesAgent.retreiveRequest`.
- move availability removal to the downloading state. once availability is persisted to disk, it should survive node restarts.
-
* [marketplace] handle slot filled by other host
Handle the case when in the downloading, proving, or filling states, that another host fills the slot.
* [marketplace] use requestId for mySlots
* [marketplace] infer slot index from slotid
prevents reassigning a random slot index when restoring state from chain
* [marketplace] update to work with latest contracts
* [marketplace] clean up
* [marketplace] align with contract changes
- getState / state > requestState
- getSlot > getRequestFromSlotId
- support MarketplaceConfig
- support slotState, remove unneeded Slot type
- collateral > config.collateral.initialAmount
- remove proofPeriod contract call
- Revert reason “Slot empty” > “Slot is free”
- getProofEnd > read SlotState
Tests for changes
* [marketplace] add missing file
* [marketplace] bump codex-contracts-eth
* [config] remove unused imports
* [sales] cleanup
* [sales] fix: do not crash when fetching state fails
* [sales] make slotIndex non-optional
* Rebase and update NBS commit
Rebase on top of main and update NBS commit to the CI fix.
* [marketplace] use async subscription event handlers
* [marketplace] support slotIndex no longer optional
Previously, SalesAgent.slotIndex had been moved to not optional. However, there were still many places where optionality was assumed. This commit removes those assumuptions.
* [marketplace] sales state machine: use slotState
Use `slotState` instead of `requestState` for sales state machine.
* [marketplace] clean up
* [statemachine] adds a statemachine for async workflows
Allows events to be scheduled synchronously.
See https://github.com/status-im/nim-codex/pull/344
Co-Authored-By: Ben Bierens <thatbenbierens@gmail.com>
Co-Authored-By: Eric Mastro <eric.mastro@gmail.com>
* [market] make market callbacks synchronous
* [statemachine] export Event
* [statemachine] ensure that no errors are raised
* [statemachine] add machine parameter to run method
* [statemachine] initialize queue on start
* [statemachine] check futures before cancelling them
* [sales] use new async state machine
- states use new run() method and event mechanism
- StartState starts subscriptions and loads request
* [statemachine] fix unsusbscribe before subscribe
* [sales] replace old state transition tests
* [sales] separate state machine from sales data
* [sales] remove reference from SalesData to Sales
* [sales] separate sales context from sales
* [sales] move decoupled types into their own modules
* [sales] move retrieveRequest to SalesData
* [sales] move subscription logic into SalesAgent
* [sales] unsubscribe when finished or errored
* [build] revert back to released version of nim-ethers
* [sales] remove SaleStart state
* [sales] add missing base method
* [sales] move asyncSpawn helper to utils
* [sales] fix imports
* [sales] remove unused variables
* [sales statemachine] add async state machine error handling (#349)
* [statemachine] add error handling to asyncstatemachine
- add error handling to catch errors during state.run
- Sales: add ErrorState to identify which state to transition to during an error. This had to be added to SalesAgent constructor due to circular dependency issues, otherwise it would have been added directly to SalesAgent.
- Sales: when an error during run is encountered, the SaleErrorState is constructed with the error, and by default (base impl) will return the error state, so the machine can transition to it. This can be overridden by individual states if needed.
* [sales] rename onSaleFailed to onSaleErrored
Because there is already a state named SaleFailed which is meant to react to an onchain RequestFailed event and also because this callback is called from SaleErrored, renaming to onSaleErrored prevents ambiguity and confusion as to what has happened at the callback callsite.
* [statemachine] forward error to state directly
without going through a machine method first
* [statemachine] remove unnecessary error handling
AsyncQueueFullError is already handled in schedule()
* [statemachine] test that cancellation ignores onError
* [sales] simplify error handling in states
Rely on the state machine error handling instead
of catching errors in the state run method
---------
Co-authored-by: Mark Spanbroek <mark@spanbroek.net>
* [statemachine] prevent memory leaks
prevent memory leaks and nil access defects by:
- allowing multiple subscribe/unsubscribes of salesagent
- disallowing individual salesagent subscription calls to be made externally (requires the .subscribed check)
- allowing mutiple start/stops of asyncstatemachine
- disregard asyncstatemachine schedules if machine not yet started
* [salesagent] add salesagent-specific tests
1. test multiple subscribe/unsubscribes
2. test scheduling machine without being started
3. test subscriptions are working correctly with external events
4. test errors can be overridden at the state level for ErrorHandlingStates.
---------
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
Co-authored-by: Mark Spanbroek <mark@spanbroek.net>
Co-authored-by: Ben Bierens <thatbenbierens@gmail.com>
* Sets up working dockerized build and codex docker image creation
* Making codex configurable from the docker environment
* Sets up two networks with three codex nodes
* enables and exposes metrics endpoint for first node
* Manually performed two-client test scenario with docker containers
* Sets up docker-ignore and docker github workflow
* Wires up all codex CLI arguments to docker env vars
* Makes API_PORT variable optional as well
* Removes duplicate docker-login step
* Fixes path to docker file
* Switches target dockerhub for debugging
* Adds git tag info to --version output
* Exposes version information via debug endpoint
* Debugging docker image
* specifies target platforms for docker build
* specifies platform for QEMU and buildx steps
* Attempt to debug line endings
* Disables march-native in config.nims as test
* Applies make argument to disable architecture optimization during docker build
* Removes subset version tags from docker build
* Restore multi-arch build
* Removes docker-build test branch from CI branches
* initial implementation of repo store
* allow isManifest on multicodec
* rework with new blockstore
* add raw codec
* rework listBlocks
* remove fsstore
* reworking with repostore
* bump datastore
* fix listBlocks iterator
* adding store's common tests
* run common store tests
* remove fsstore backend tests
* bump datastore
* add `listBlocks` tests
* listBlocks filter based on block type
* disabling tests in need of rewriting
* allow passing block type
* move BlockNotFoundError definition
* fix tests
* increase default advertise loop sleep to 10 mins
* use `self`
* add cache quota functionality
* pass meta store and start repo
* add `CacheQuotaNamespace`
* pass meta store
* bump datastore to latest master
* don't use os `/` as key separator
* Added quota limits support
* tests for quota limits
* add block expiration key
* remove unnesesary space
* use idleAsync in listBlocks
* proper test name
* re-add contrlC try/except
* add storage quota and block ttl config options
* clarify comments
* change expires key format
* check for block presence before storing
* bump datastore
* use dht with fixed datastore `has`
* bump datastore to latest master
* bump dht to latest master
* attach `wait` to handle fut
* fix crash when can't find a CID and timeout hits
the exception was not raised, thus a Nil was returned that was
than wrapped in an option, leading to crash.
Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
* add inFlight flag
* adding pending blocks tests
Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
Co-authored-by: Csaba Kiraly <csaba.kiraly@gmail.com>
* [purchasing] Simplify test
* [utils] Move StorageRequest.example up one level
* [purchasing] Load purchases from market
* [purchasing] load purchase states
* Implement myRequest() and getState() methods for OnChainMarket
* [proofs] Fix intermittently failing tests
Ensures that examples of proofs in tests are never of length 0;
these are considered invalid proofs by the smart contract logic.
* [contracts] Fix failing test
With the new solidity contracts update, a contract can only
be paid out after it started.
* [market] Add method to get request end time
* [purchasing] wait until purchase is finished
Purchase.wait() would previously wait until purchase
was started, now we wait until it is finished.
* [purchasing] Handle 'finished' and 'failed' states
* [marketplace] move to failed state once request fails
- Add support for subscribing to request failure events.
- Add supporting contract tests for subscribing to request failure events.
- Allow the PurchaseStarted state to move to PurchaseFailure once a request failure event is emitted
- Add supporting tests for moving from PurchaseStarted to PurchaseFailure
- Add state transition tests for PurchaseUnknown.
* [marketplace] Fix test with longer sleepAsync
* [integration] Add function to restart a codex node
* [purchasing] Set client address before requesting storage
To prevent the purchase id (which equals the request id)
from changing once it's been submitted.
* [contracts] Fix: OnChainMarket.getState()
Had the wrong method signature before
* [purchasing] Load purchases on node start
* [purchasing] Rename state 'PurchaseError' to 'PurchaseErrored'
Allows for an exception type called 'PurchaseError'
* [purchasing] Load purchases in background
No longer calls market.getRequest() for every purchase
on node start.
* [contracts] Add `$` for RequestId, SlotId and Nonce
To aid with debugging
* [purchasing] Add Purchasing.stop()
To ensure that all contract interactions have both a
start() and a stop() for
* [tests] Remove sleepAsync where possible
Use `eventually` loop instead, to make sure that we're
not waiting unnecessarily.
* [integration] Fix: handle non-json response in test
* [purchasing] Add purchase state to json
* [integration] Ensure that purchase is submitted before restart
Fixes test failure on slower CI
* [purchasing] re-implement `description` as method
Allows description to be set in the same module where the
state type is defined.
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
* [contracts] fix typo
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
* [market] Use more generic error type
Should we decide to change the provider type later
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
* setup and persist private key
* return dht record spr
* helper to remap multiaddr ip and port
* set/update discovery and announce addrs
* add nat and discovery IPs
* allow for announce and DHT addresses separatelly
* update tests
* check for nat or discoveryIp
* fix integration tests
* misc align
* don't share data dirs and and set bootstrap node
* add log scope
* remap announceAddrs after node start
* simplify discovery initialization
* make nat and disc-ip required
* add log scope don't init dht spr in constructor
* bump dht
* dissallow `0.0.0.0` for `--nat`
* add format for cid
* cid formatIt change
* track nim-libp2p-unstable
* rework probuf serialization for por
* add missing include
* removing nim protobuf serialization
* rollback to dht to main
* remove protobuf serialization import
1. use `ProviderError` to catch contract errors instaed of `JsonRpcProviderError`.
2. Add tests for `isProofRequired`, `willProofBeRequired`, and `getProofEnd` when slot is empty (and is call is reverted)
3. bump nim-ethers to branch that has new `reverts` API and `ProviderError` support.
4. Update to new `reverts` API.
Support storage contract parameters to free slots after too many proofs missed, as well as fail a contract after too many slots have been freed.
# Conflicts:
# vendor/dagger-contracts
Remove `isSlotCancelled` and `isCancelled` from proving, as it did not fit in the module.
Update the proving module to not rely on checking the contract to understand if a request was cancelled. Instead, `proofEnd` was modified in `dagger-contracts` such that it returns a past timestamp when the contract is cancelled. This successfully removes
- remove RequestState as no longer being used
- remove RequestState check on purchase timeout
- add tests for `withdrawFunds` and `subscribeRequestCancelled`
- update `dagger-contracts` so that `RequestCancelled.requestId` property is indexed in the event
- rename `ContractId` to `SlotId`
- rename `Proving.contracts` to `Proving.slots`
- change signatures of `isSlotCancelled` and `isCancelled` to use `SlotId` and `RequestId` types, respectively.
- change all references to `RequestId`, `SlotId`
Add or remove proof requirements when a request contract’s state changes. When a request sale has completed (for a slot), the host who purchased that slot now must provide regular proofs for the data they are contracted to hold. This is now enforced by adding the slotId to the HashSet of Ids for which to require proofs. When a request has been cancelled (not all slots were filled before the request expired), proofs no longer need to be provided and the slotId is removed from teh HashSet.
Add `isCancelled` and `isSlotCancelled` checks to query the contract state without relying the on the state context variable in the contract. Because contract state can only be updated in a transaction, and the client withdrawing funds is responsible for changing the contract state to “Cancelled”, the `isCancelled` and `isSlotCancelled` functions were introduced to check the state regardless of whether or not the client had already withdrawn their funds.
When a request for storage times out (not enough slots filled), the client will initiate a withdraw request to retrieve its funds out of the contract, setting the state of the request to RequestState.Cancelled. The client will also emit a RequestCancelled event for others to listen to (ie hosts will need to listen for this event to withdraw its collateral).
Add unit test that checks for emission of RequestCancelled after request is purchased request expires.
Update dagger-contracts dependency to commit that holds the changes supporting withdrawing of funds.
Increase blocksize from ~8KiB to ~64KiB and remove useless unbounded prefetching on download
* increased upload/download speed on my Win10 Zen3 box to 50/150 MB/s (with FSStore)
* made manifest files 8x smaller
* two more changes in the tests to make them pass
Closes#263
* upgrading nimbus build system to latest
* use new `updateRecord`
* bump nim-libp2p-dht
* bump nimbus build system
* bumping deps
* update to latest dht
Make RequestId, SlotId, Nonce, PurcahseId distinct types.
Add/modify conversions to support the distinct type (ABI encoding/decoding, JSON encoding, REST decoding).
Update tests
- rename `ContractId` to `SlotId`
- add `RequestId`, `PurchaseId`, `Nonce` types as aliases of `array[32, byte]`
- rename `Proving.contracts` to `Proving.slots`
- change signatures of `isSlotCancelled` and `isCancelled` to use `SlotId` and `RequestId` types, respectively.
- change all references to `RequestId`, `SlotId`, and `PurchaseId`
The initial goal of this patch was to allow to download of a file via REST API in exactly the same size as it was uploaded, which required adding fields Chunker.offset and Manifest.originalBytes to keep that size. On top of that, we added more integrity checks to operations on Manifest, and reorganized TestNode.nim to test the actual interaction between node.store and node.retrieve operations.
Note that the wire format of Manifest was changed, so we need to recreate all BlockStores.
* Download without padding
* Fixed chunker tests
* Chunker: get rid of RabinChunker
* Verify offset in the chunker tests
* Use manifest.originalBytesPadded in StoreStream.size
* StoreStream: replace emptyBlock with zeroMem
* Manifest.bytes: compute how many bytes corresponding StoreStream(Manifest, pad) will return
* Manifest: verify originalBytes and originalLen on new/encode/decode
Also set originalBytes in each Manifest creation/update scenario
* Manifest: comments, split code into sections
* Reordered parameters to deal with int64 size in 32-bit builds
* TestNode.nim: combine Store and Retrieve tests
1. Instead of copy-pasting code from node.nim, new test calls node.store() and node.retrieve() in order to check that they can correctly store and then retrieve data
2. New test compares only file contents, manifest contents considered an implementation detail
3. New test chunks at odd chunkSize=BlockSize/1.618 in order to ensure that data retrieved correctly even when buffer sizes mismatch
* TestNode.nim: code refactoring
* Manifest.add: one more test
* Manifest.verify: return Result instead of raising Defect
* Node.store: added blockSize parameter
change return type for `method getBlock` from `Future[?!(?Block)]` to
`Future[?!Block]`
use `type BlockNotFoundError = object of CodexError` to differentiate between
"block not found in the store" and other errors
also make some logic and error handling/messages more consistent across
BlockStore implementations
closes#177closes#182closes#210
alternative to #205, #209
ECC decoding can be done with any encoded.K blocks, and now we start it once any K blocks arrived.
Previous code essentially waited for all blocks to arrive (or fail to arrive), that may mean unnecessary delays.
New code will sometimes ECC-decode when parity blocks were retrieved faster that data blocks (instead of waiting for data blocks from network), but we expect that it's OK due to extremely fast Leopard decoding (~~500 MB/s)
* [contracts] ContractInteractions.new() now requires account parameter
* [cli] Only perform Ethereum interactions when --eth-account is specified
* [cli] Add --persistence option that is disabled by default
* [cli] Use Option for ethDeployment parameter
* [node] Better error reporting when Ethereum node cannot be reached
also fix a discrepancy where cli option `--cache-size` is documented as
`0 disables the cache` in `codex/conf.nim`, but previously the value `0` would
result in a cache being constructed with default parameter values for
`CacheStore.new()`
Closes#180
BlockStore API got new return types (rationale in https://github.com/status-im/nim-codex/issues/123#issuecomment-1163797753):
- getBlock: Future[?! (?Block)]
- putBlock/delBlock/listBlocks: Future[?!void]
- hasBlock: Future[?!bool]
Plus refactored readOnce(StoreStream) and check received data in its tests.
And replaced local use of AsyncHeapQueue with seq.sort.
As discussed in team:
- Retrieving of blocks that are mentioned in the
manifest should be moved into a BlockStore.
- Sales should be given an instance of BlockStore,
and an instance of StorageProofs, instead of the
onStore, onClear, and onProve callbacks
Reason: with the new design there are no offers and
selection, making this less like a negotation, and
more like an agent trying to fulfill a storage request
* initial implementation of storage proofs upload
* make sure proof verifies with after deserializing
* add por store
* rename por store to stp store
* rename porstore to stpstore
* add support for host discovery to discovery mock
* add tags upload network tests