diff --git a/codex/contracts/requests.nim b/codex/contracts/requests.nim index f3cf87d1..f591b785 100644 --- a/codex/contracts/requests.nim +++ b/codex/contracts/requests.nim @@ -1,3 +1,4 @@ +import std/hashes import pkg/contractabi import pkg/nimcrypto import pkg/ethers/fields @@ -28,9 +29,17 @@ type u*: seq[byte] publicKey*: seq[byte] name*: seq[byte] - SlotId* = array[32, byte] - RequestId* = array[32, byte] - Nonce* = array[32, byte] + SlotId* = distinct array[32, byte] + RequestId* = distinct array[32, byte] + Nonce* = distinct array[32, byte] + +proc `==`*(x, y: Nonce): bool {.borrow.} +proc `==`*(x, y: RequestId): bool {.borrow.} +proc `==`*(x, y: SlotId): bool {.borrow.} +proc hash*(x: SlotId): Hash {.borrow.} + +func toArray*(id: RequestId | SlotId | Nonce): array[32, byte] = + array[32, byte](id) func fromTuple(_: type StorageRequest, tupl: tuple): StorageRequest = StorageRequest( @@ -84,6 +93,9 @@ func solidityType*(_: type StorageAsk): string = func solidityType*(_: type StorageRequest): string = solidityType(StorageRequest.fieldTypes) +func solidityType*[T: RequestId | SlotId | Nonce](_: type T): string = + solidityType(array[32, byte]) + func encode*(encoder: var AbiEncoder, por: StoragePoR) = encoder.write(por.fieldValues) @@ -96,9 +108,17 @@ func encode*(encoder: var AbiEncoder, content: StorageContent) = func encode*(encoder: var AbiEncoder, ask: StorageAsk) = encoder.write(ask.fieldValues) +func encode*(encoder: var AbiEncoder, id: RequestId | SlotId | Nonce) = + encoder.write(id.toArray) + func encode*(encoder: var AbiEncoder, request: StorageRequest) = encoder.write(request.fieldValues) +func decode*[T: RequestId | SlotId | Nonce](decoder: var AbiDecoder, + _: type T): ?!T = + let nonce = ?decoder.read(type array[32, byte]) + success T(nonce) + func decode*(decoder: var AbiDecoder, T: type StoragePoR): ?!T = let tupl = ?decoder.read(StoragePoR.fieldTypes) success StoragePoR.fromTuple(tupl) @@ -121,11 +141,11 @@ func decode*(decoder: var AbiDecoder, T: type StorageRequest): ?!T = func id*(request: StorageRequest): RequestId = let encoding = AbiEncoder.encode((request, )) - keccak256.digest(encoding).data + RequestId(keccak256.digest(encoding).data) func slotId*(requestId: RequestId, slot: UInt256): SlotId = let encoding = AbiEncoder.encode((requestId, slot)) - keccak256.digest(encoding).data + SlotId(keccak256.digest(encoding).data) func slotId*(request: StorageRequest, slot: UInt256): SlotId = slotId(request.id, slot) diff --git a/codex/purchasing.nim b/codex/purchasing.nim index e8d35b3e..c2ff6e3a 100644 --- a/codex/purchasing.nim +++ b/codex/purchasing.nim @@ -1,3 +1,4 @@ +import std/hashes import std/tables import pkg/stint import pkg/chronos @@ -22,13 +23,16 @@ type clock: Clock request*: StorageRequest PurchaseTimeout* = Timeout - PurchaseId* = array[32, byte] + PurchaseId* = distinct array[32, byte] const DefaultProofProbability = 100.u256 const DefaultRequestExpiryInterval = (10 * 60).u256 proc start(purchase: Purchase) {.gcsafe.} func id*(purchase: Purchase): PurchaseId +proc `==`*(x, y: PurchaseId): bool {.borrow.} +proc hash*(x: PurchaseId): Hash {.borrow.} +proc toHex*(x: PurchaseId): string {.borrow.} proc new*(_: type Purchasing, market: Market, clock: Clock): Purchasing = Purchasing( @@ -45,7 +49,9 @@ proc populate*(purchasing: Purchasing, request: StorageRequest): StorageRequest if result.expiry == 0.u256: result.expiry = (purchasing.clock.now().u256 + purchasing.requestExpiryInterval) if result.nonce == Nonce.default: - doAssert randomBytes(result.nonce) == 32 + var id = result.nonce.toArray + doAssert randomBytes(id) == 32 + result.nonce = Nonce(id) proc purchase*(purchasing: Purchasing, request: StorageRequest): Purchase = let request = purchasing.populate(request) @@ -94,7 +100,7 @@ proc wait*(purchase: Purchase) {.async.} = await purchase.future func id*(purchase: Purchase): PurchaseId = - purchase.request.id + PurchaseId(purchase.request.id) func finished*(purchase: Purchase): bool = purchase.future.finished diff --git a/codex/rest/api.nim b/codex/rest/api.nim index 2e3d27f1..9918460b 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -13,6 +13,7 @@ push: {.upraises: [].} import std/sequtils +import std/sugar import pkg/questionable import pkg/questionable/results @@ -104,6 +105,10 @@ proc decodeString(_: type array[32, byte], except ValueError as e: err e.msg.cstring +proc decodeString[T: PurchaseId | RequestId | Nonce](_: type T, + value: string): Result[T, cstring] = + array[32, byte].decodeString(value).map(id => T(id)) + proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter = var router = RestRouter.init(validate) router.api( diff --git a/codex/rest/json.nim b/codex/rest/json.nim index d142f5f3..16f88e3b 100644 --- a/codex/rest/json.nim +++ b/codex/rest/json.nim @@ -45,6 +45,9 @@ func `%`*(stint: StInt|StUInt): JsonNode = func `%`*(arr: openArray[byte]): JsonNode = %("0x" & arr.toHex) +func `%`*(id: RequestId | SlotId | Nonce): JsonNode = + % id.toArray + func `%`*(purchase: Purchase): JsonNode = %*{ "finished": purchase.finished, diff --git a/codex/storageproofs/timing/proofs.nim b/codex/storageproofs/timing/proofs.nim index 3d261076..6995a346 100644 --- a/codex/storageproofs/timing/proofs.nim +++ b/codex/storageproofs/timing/proofs.nim @@ -2,12 +2,12 @@ import pkg/chronos import pkg/stint import pkg/upraises import ./periods -from ../../contracts/requests import SlotId, RequestId +import ../../contracts/requests export chronos export stint export periods -export SlotId, RequestId +export requests type Proofs* = ref object of RootObj diff --git a/tests/examples.nim b/tests/examples.nim index 933fc990..c0021ed2 100644 --- a/tests/examples.nim +++ b/tests/examples.nim @@ -1,5 +1,6 @@ import std/random import std/sequtils +import pkg/codex/proving import pkg/stint proc example*[T: SomeInteger](_: type T): T = @@ -15,3 +16,6 @@ proc example*[T](_: type seq[T]): seq[T] = proc example*(_: type UInt256): UInt256 = UInt256.fromBytes(array[32, byte].example) + +proc example*[T: RequestId | SlotId | Nonce](_: type T): T = + T(array[32, byte].example)