This repository has been archived by the owner on Nov 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3537c54
commit 1604bf5
Showing
13 changed files
with
308 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { OfferStore } from './buckets/offer-store' | ||
import all from 'it-all' | ||
|
||
export async function mergeOffers (date: Date, offerStore: OfferStore) { | ||
const d = getPreviousUtcDateName(date) | ||
const offers = (await all(offerStore.list(d))) | ||
await offerStore.putMergedOffers(d, offers) | ||
|
||
return d | ||
} | ||
|
||
function getPreviousUtcDateName(date: Date) { | ||
// normalize date to multiple of 15 minutes | ||
const currentMinute = date.getUTCMinutes() | ||
const factor = Math.floor(currentMinute / 15) // difference between previous and next | ||
const additionalTime = ((factor * 15) - currentMinute) * 60000 | ||
|
||
const nDate = new Date(date.getTime() + additionalTime) | ||
|
||
return `${nDate.getUTCFullYear()}-${nDate.getUTCMonth()}-${nDate.getUTCDay()} ${nDate.getUTCHours()}:${nDate.getUTCMinutes()}:00` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { randomCARs } from './utils.js' | ||
|
||
/** | ||
* @param {number} length | ||
* @param {number} size | ||
*/ | ||
export async function generateOffers(length, size) { | ||
return (await randomCARs(length, size)) | ||
// Inflate size for testing within range | ||
.map((car) => ({ | ||
...car, | ||
size: car.size * 10e5, | ||
})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { CID } from 'multiformats' | ||
import { webcrypto } from 'crypto' | ||
import { sha256 } from 'multiformats/hashes/sha2' | ||
import * as CAR from '@ucanto/transport/car' | ||
import * as raw from 'multiformats/codecs/raw' | ||
import { CarWriter } from '@ipld/car' | ||
import { Blob } from '@web-std/blob' | ||
|
||
/** @param {number} size */ | ||
export async function randomBytes(size) { | ||
const bytes = new Uint8Array(size) | ||
while (size) { | ||
const chunk = new Uint8Array(Math.min(size, 65_536)) | ||
webcrypto.getRandomValues(chunk) | ||
|
||
size -= bytes.length | ||
bytes.set(chunk, size) | ||
} | ||
return bytes | ||
} | ||
|
||
/** @param {number} size */ | ||
export async function randomCAR(size) { | ||
const bytes = await randomBytes(size) | ||
const hash = await sha256.digest(bytes) | ||
const root = CID.create(1, raw.code, hash) | ||
|
||
const { writer, out } = CarWriter.create(root) | ||
writer.put({ cid: root, bytes }) | ||
writer.close() | ||
|
||
const chunks = [] | ||
for await (const chunk of out) { | ||
chunks.push(chunk) | ||
} | ||
const blob = new Blob(chunks) | ||
const cid = await CAR.codec.link(new Uint8Array(await blob.arrayBuffer())) | ||
|
||
return Object.assign(blob, { cid, roots: [root] }) | ||
} | ||
|
||
/** | ||
* @param {number} length | ||
* @param {number} size | ||
* @param {object} [options] | ||
* @param {string} [options.origin] | ||
*/ | ||
export async function randomCARs(length, size, options = {}) { | ||
const origin = options.origin || 'https://carpark.web3.storage' | ||
|
||
return ( | ||
await Promise.all(Array.from({ length }).map(() => randomCAR(size))) | ||
).map((car) => ({ | ||
link: car.cid, | ||
size: car.size, | ||
commitmentProof: 'todo-commP', | ||
src: [`${origin}/${car.cid.toString()}`], | ||
})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
GetObjectCommand, | ||
} from '@aws-sdk/client-s3' | ||
|
||
import { test } from './helpers/context.js' | ||
import { createS3, createBucket } from './helpers/resources.js' | ||
import { generateOffers } from './helpers/offers.js' | ||
|
||
import { mergeOffers } from '../merge-offers.js' | ||
import { useOfferStore } from '../buckets/offer-store.js' | ||
|
||
test.before(async (t) => { | ||
Object.assign(t.context, { | ||
s3: (await createS3()).client, | ||
}) | ||
}) | ||
|
||
test('can merge offers', async t => { | ||
const { s3 } = t.context | ||
const bucketName = await createBucket(s3) | ||
const offerStore = useOfferStore(s3, bucketName) | ||
|
||
const offers = (await generateOffers(10, 10)) | ||
|
||
const dateToFront = new Date() | ||
dateToFront.setMinutes(dateToFront.getMinutes() + 15) | ||
const dataSegments = [ | ||
'commP0', | ||
'commP1' | ||
] | ||
await Promise.all( | ||
dataSegments.map(commitmentProof => offerStore.queue({ commitmentProof, offers }, new Uint8Array([1, 2, 3]))) | ||
) | ||
|
||
const mergedOfferId = await mergeOffers(dateToFront, offerStore) | ||
t.truthy(mergedOfferId) | ||
|
||
const mergedOffersGetCmd = new GetObjectCommand({ | ||
Bucket: bucketName, | ||
Key: mergedOfferId | ||
}) | ||
const mergedOffersResponse = await s3.send(mergedOffersGetCmd) | ||
const rawMergedOffers = await mergedOffersResponse.Body?.transformToString() | ||
if (!rawMergedOffers) { | ||
throw new Error('merged offer not written') | ||
} | ||
const mergedOffers = JSON.parse(rawMergedOffers) | ||
t.is(mergedOffers.length, dataSegments.length) | ||
for (const segment of dataSegments) { | ||
t.truthy(mergedOffers.find(o => o.commitmentProof === segment)) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import * as Sentry from '@sentry/serverless' | ||
|
||
import { mergeOffers } from '@spade-proxy/core/merge-offers' | ||
import { createOfferStore } from '@spade-proxy/core/buckets/offer-store' | ||
|
||
import { mustGetEnv } from '../utils' | ||
|
||
Sentry.AWSLambda.init({ | ||
environment: process.env.SST_STAGE, | ||
dsn: process.env.SENTRY_DSN, | ||
tracesSampleRate: 1.0, | ||
}) | ||
const AWS_REGION = process.env.AWS_REGION || 'us-west-2' | ||
|
||
export async function main() { | ||
const { offerBucketName } = getLambdaEnv() | ||
const date = new Date() | ||
const offerStore = createOfferStore(AWS_REGION, offerBucketName) | ||
|
||
return mergeOffers(date, offerStore) | ||
} | ||
|
||
function getLambdaEnv () { | ||
return { | ||
offerBucketName: mustGetEnv('OFFER_BUCKET_NAME'), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export async function main() { | ||
const d = checkDate() | ||
console.log(d) | ||
return {} | ||
} | ||
|
||
function checkDate() { | ||
return (new Date()).toISOString() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export function mustGetEnv (name: string) { | ||
const value = process.env[name] | ||
if (!value) throw new Error(`missing ${name} environment variable`) | ||
return value | ||
} |
Oops, something went wrong.