feat: millis part in sorter for Arweave transactions

This commit is contained in:
ppedziwiatr
2022-01-26 17:31:06 +01:00
committed by Piotr Pędziwiatr
parent 29decd6deb
commit 1c38f6f146
3 changed files with 265 additions and 1 deletions

View File

@@ -0,0 +1,250 @@
import Arweave from 'arweave';
import fs from 'fs';
import * as path from 'path';
import { GQLEdgeInterface, LexicographicalInteractionsSorter } from '@smartweave';
import { JWKInterface } from 'arweave/node/lib/wallet';
import { arrayToHex } from 'smartweave/lib/utils';
describe('Sequencer', () => {
const arweave = Arweave.init({
host: 'arweave.net',
port: 443,
protocol: 'https',
timeout: 60000,
logging: false
});
const baseTime = 1643210931796;
const sorter = new LexicographicalInteractionsSorter(arweave);
const wallet = JSON.parse(fs.readFileSync(path.join(__dirname, '/test-wallet.json')).toString());
function mapSorted(s: GQLEdgeInterface) {
return `[${s.node.id}] : ${s.sortKey}`;
}
it('should properly assign sequence for transactions within the same block', async () => {
const interactions = [
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk',
millis: baseTime
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 1
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0',
millis: baseTime + 2
}
];
const transactions = await mapInteractions(interactions);
const sorted = await sorter.sort(transactions as unknown as GQLEdgeInterface[]);
expect(sorted.map((s) => mapSorted(s))).toEqual([
'[JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860512,1643210931796,81e1bea09d3262ee36ce8cfdbbb2ce3feb18a717c3020c47d206cb8ecb43b767',
'[UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860512,1643210931797,ba45da3dc691d607f94aa90e5e2121928164b624872f277d708ed807330eb390',
'[cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860512,1643210931798,558e456b249d174bc47ca665a3f6162c5ad61e63c12a1a868cc0e18d9e5cb768'
]);
// note that without the "millis" part, the ordering would be:
// "[cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860512,558e456b249d174bc47ca665a3f6162c5ad61e63c12a1a868cc0e18d9e5cb768",
// "[JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860512,81e1bea09d3262ee36ce8cfdbbb2ce3feb18a717c3020c47d206cb8ecb43b767",
// "[UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860512,ba45da3dc691d607f94aa90e5e2121928164b624872f277d708ed807330eb390",
});
it('should properly assign sequence for transactions from different blocks', async () => {
const interactions = [
{
height: 860511,
blockId: 'Al2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'ATzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk',
millis: baseTime
},
{
height: 860511,
blockId: 'Al2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: '0dFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 1
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk',
millis: baseTime + 2
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 3
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0',
millis: baseTime + 4
},
{
height: 860513,
blockId: 'Bl2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'CdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 5
},
{
height: 860513,
blockId: 'Bl2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'DqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0',
millis: baseTime + 6
}
];
const transactions = await mapInteractions(interactions);
const sorted = await sorter.sort(transactions as unknown as GQLEdgeInterface[]);
expect(sorted.map((s) => mapSorted(s))).toEqual([
'[ATzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860511,1643210931796,0233bf40009ae4ae32d6125cf5375da8d77cb024a86b26623cf8e9816b4b7a48',
'[0dFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860511,1643210931797,580a0405284ac42c75c2336c0efac2c5fcd3b379b4f51b7f842a501a704c1038',
'[JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860512,1643210931798,81e1bea09d3262ee36ce8cfdbbb2ce3feb18a717c3020c47d206cb8ecb43b767',
'[UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860512,1643210931799,ba45da3dc691d607f94aa90e5e2121928164b624872f277d708ed807330eb390',
'[cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860512,1643210931800,558e456b249d174bc47ca665a3f6162c5ad61e63c12a1a868cc0e18d9e5cb768',
'[CdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860513,1643210931801,26844bd597465eae300253dd923bad9db037e15f4f6bd26e1f4a9aac27152f4f',
'[DqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860513,1643210931802,854d60e74c8c9298dfa72ce9fda56c5e7b40aca41dd47290c5ff17fb3a94e87d'
]);
});
it('should properly assign sequence for transactions from different origins', async () => {
const interactions = [
{
height: 860511,
blockId: 'Al2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'ATzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk',
origin: 'arweave'
},
{
height: 860511,
blockId: 'Al2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'BdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 1
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk',
millis: baseTime + 2
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
millis: baseTime + 3
},
{
height: 860512,
blockId: '-l2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0',
origin: 'arweave'
},
{
height: 860513,
blockId: 'Bl2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'CdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss',
origin: 'arweave'
},
{
height: 860513,
blockId: 'Bl2bujityzUrM4YI7P_s6zqG1RBmkALSpXdEEd2XOoaErXse94KnNaXGFWVf8jNq',
wallet: wallet,
transactionId: 'DqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0',
millis: baseTime + 6
}
];
const transactions = await mapInteractions(interactions);
const sorted = await sorter.sort(transactions as unknown as GQLEdgeInterface[]);
expect(sorted.map((s) => mapSorted(s))).toEqual([
'[BdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860511,1643210931797,ce88782c6a2005ef504ef74223fc864e8cef2aa158cea3dec2266b6871e9aae0',
'[ATzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860511,9999999999999,e2199366ba729c3cb9580b0757858689a66e3435aa7462ffa466eba2b2f8f449',
'[JTzWaG_tiagnoCNlPpdWvN1r16rw47MbNgZn6Fd1dNk] : 000000860512,1643210931798,81e1bea09d3262ee36ce8cfdbbb2ce3feb18a717c3020c47d206cb8ecb43b767',
'[UdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860512,1643210931799,ba45da3dc691d607f94aa90e5e2121928164b624872f277d708ed807330eb390',
'[cqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860512,9999999999999,bb6d3084dd5770a43234e253154fb75cd886b57adf3df52901bf67789247b9b9',
'[DqehSNlOvnqHoRRs56Cex8PEhHsaGYLz1m4j19kWB-0] : 000000860513,1643210931802,854d60e74c8c9298dfa72ce9fda56c5e7b40aca41dd47290c5ff17fb3a94e87d',
'[CdFlfj5IUYh-7lHJuLLC94P9M1mqxKhkpuuiMzKUKss] : 000000860513,9999999999999,12d814fd50a9fabcf334075b3dd5d4e8d4455fb729b6063b092967c99143e084'
]);
});
async function mapInteractions(interactions: any[]) {
return await Promise.all(
interactions.map(async (i) => {
if (i.origin == 'arweave') {
return {
node: {
id: i.transactionId,
block: {
id: i.blockId,
height: i.height
}
}
};
} else {
// note: that's how sequencer would behave
const sortKey = await createSortKey(arweave, wallet, i.blockId, i.millis, i.transactionId, i.height);
return {
node: {
id: i.transactionId,
source: 'redstone-sequencer',
sortKey,
block: {
id: i.blockId,
height: i.height
}
}
};
}
})
);
}
});
// TODO: c/p from GW code.
async function createSortKey(
arweave: Arweave,
jwk: JWKInterface,
blockId: string,
mills: number,
transactionId: string,
blockHeight: number
) {
const blockHashBytes = arweave.utils.b64UrlToBuffer(blockId);
const txIdBytes = arweave.utils.b64UrlToBuffer(transactionId);
const jwkDBytes = arweave.utils.b64UrlToBuffer(jwk.d as string);
const concatenated = arweave.utils.concatBuffers([blockHashBytes, txIdBytes, jwkDBytes]);
const hashed = arrayToHex(await arweave.crypto.hash(concatenated));
const blockHeightString = `${blockHeight}`.padStart(12, '0');
return `${blockHeightString},${mills},${hashed}`;
}

View File

@@ -0,0 +1,11 @@
{
"kty": "RSA",
"n": "oAtCRi4vAnw74NgKeQN6Y0Ut595XQ8mKEwSxCCOFoQlgqjPsvajWj__WpCpLQOU_D87QQFJ5sGw6G-1SOZSK0nsbzCa00JGiT60X6DOCPueAAD1vN_Ge7druy9bPBtH4Xlounm6QFznfhUuIIp3F19eHOxEJcu8HxljWrvqlDvssh5ayBln06O5le7hn_fNPWTleW8EwOKvcKO11pyJtvLhbXctNNd1OThpW6OxRgU6-Ay3leIWr7BwKSEccj315V-x2kbFK2lNvAI95Sl7pc_CMK6iRYIlmFqF-BI55nMojYHL6PybrB2QLamplm2gpJfS_Le9UKbaCU3hb2k-2xjKLZjp765Nm-LekSsrppqpUKxeTNeQ_dS2uWMSk1vnrOYt_335-jRW3mbvHZItpeNYJO-JKGRJbq2Gksw_wHQBwuuzYucrqsIMxiggN2sgBW8E33gUMewBq9A7iJg5JlK4_-lUeBO32reDh7zrKeAqe8BV6ZCpuB3ZRjK1SCU_yGIpR7HZTtTysE7OIfYWh3bqcBq8ti6LyxRS5BeKWF7xMuK2jKBnQqEzOWJObFhxCF1g2AOgjvqK6NeGLVWtkb7z8xOjPVHGBtAS4ezd1dT2JaoS6J8c3CFMZTOKq6dirSa2sTJmfsG3DDEXo7LXa9HHs5Rx1Szr6IO9NXVZirfc",
"e": "AQAB",
"d": "IY760JhyhwTh0V27pHBUQ2iIHayDg9VIvIApVtmL9Z5vxICqzYIPq5YrvbSYnvzy4i-tfy9MEPBApwZ2TViWW1gxFfevxmQjMq3K64eRcfs83dAD-CkT-DAGDnv2YSm5-J7UU6g_Un9yHRMfcpK-n2m0E3CZGJ6CdNa__WTVI3ULe0rf_XDzZ7xFT1H1jExugPkEjhzOLbPrsDFKkEcp136YuewdPoQvHTVsr96NoJ2QPj5rdYAh8ppWlZ1DodrfjM4qdpZEac9A4U80UaHhNcxkt-rawPFOlMQ8FlyBp5zDGkBBtOhGNACIXEH_GD0ZE7pkNA-RCEYawcHlELvSSRwAkBVMm3FDbZEyw2SyWGRnxnp4uzj3jq3mFb-V-9Z4JHhvNPoxdkDg-qH-xX805wObLWkXWl_5scYvYL_DbSOr7TrE0V6z_busPdOSpOIlDiw6MxHkgWNyEfoUk387EfeAO-6IO3K_7kTMSNJP-9XYnuY5ivvqzAnbp2019yIi8uphbJVTGIn4gtqucDS90aKNenXpvevjcTAFm6l6BwEg5yIcXhV1raOzIthKEl_OWo3lofvmjzrokLYJjfnXMRflQcLcJSohYlmTr348VTdu0Hb6tWzzboGYid8tfyASs9EbtdFTjIvG8jeX2RnnqTPRl9the1NNVKx8XnnvxUE",
"p": "y9qo-Clh9f5NriDhQY5wdLLI9EjkTC0AW7BhSEKJoBFUgfLQm1WMlM3hl7N2ltuIoAkxoTNZsxKKA3kJw0hK3-S1KTqPpta_lV2r6rrJOPWSwO20Q3hqXf7-Oku_C2M26Nflf4Q95A23KB8qIu4Q3YaLGVz_Rm4o8sJ1yQE2s0wAxVKgWeVwy3yIJ6_MsC7oHo9gWryE5eCUUySPnmCa3-wmZ5kekTqshtMQhSPGryXRKrDjiCUjyoaCPVPnJA0aFrdvJmjFQyxAjxp2AKrvkqJLUvNHuVcFu2uSKgvYdUVqygl3Uqf3R1RQoB8Yab3NP_gviCv1fFKVzppbN4NZEQ",
"q": "yPuzbO7IsfWGebDuOPVT9vWR73EcK-9KlG1zCifkbISOZtBbbTFp-YgTN_wYBSB4V6P-ZrSLmJZVa2m3P_wLX06RNUEEVTuv9Q5fQR7mGehr3pBx4tIJ2rqMWaAr_4k8c6ifdQ_ixxSmAdnNbYoY5nIPiVCG4UiijbLoYLHC_7dl8wq3ssXdEYZXSc0WQ_S43z3_bNd9MFJwxoU6tTfmilY1cea2hp2Z1WRWyL07Mob5dXY2uBmFd-TL2RSrNPOAvJ5_-Ha6lNuSLe6geEG4h3hH9WWfylj1uCXvCWiXTTuMLgyXaNjWtVOb993cdiByzSh3fTxuNWu-qLV8lQNWhw",
"dp": "L8yiyCWz8aFih4zwJJYIqmRtmFIrLe1zYwx1kyL-8Eh__0R3Q6UIpK-t0QtkqDTr0VK2j2ziAIo9UFkmP-MIo30WOYegvWcnXxeqwwxvOGrksVZLaXKnxkiPRg4SytHFw000Y_UXKg1JQCAmmjAmRjtRDG5w8QvNkDamta4SLHKKz7nzHYEeNKiLqHqhTUKCbQADgOMpalmBjglJn8JZLl5KFwqhTz5py-dbvUxJPzJn3FHD2F2VCd0GVukAjsR_tInohyIT9w8-SA_VUYzDRifF77pZvAy6rFqp2DAU3lKbmqojj38RDWmoyhLgf5LguLoyMwTTuAYJWHt7HgYvcQ",
"dq": "qidOFF9kUiWHn-cHB_nLCD2HO6wLKbcA8QBocKStYqIm3Sxw-tTm33cwrikjPNPsjmYsr08TEC_WSYXKusTr69hcXzWYMYDCyzlLs5oxPKXlDRxFDr670Q42XHqaRVEueMy9kyHL4Le-g7qdjKtpwU-3j405Y-lWlZht288jQ9NE4KqmMxgIvRl7NOQIgafiDD40zTTyq8Jf7_JDbcDR0TSDMtccmIM9BchZIMH0KCbVc3iNgvc4Y_S0ECjLeZzd1NJrjTMXa4cpDvIDsUwSqb5PTZan3WvLPAgBg3mk_qH3X9URKpbJz-HlHcgbKXb3OnGUF9bdhySc2cAspQuaaQ",
"qi": "YopbwOk1bHSAWos8uRKmLHffxWLRynMGTlO-AiS29qdoGqBqg0AuG1q-SRqZGetrZKUBJYaHsKOiTlMOqWZr1Sh2Yoolw1imlQYD3wVulCHkfVXT26cPf1u2gNNbT7JJ5CHYbukVN0f-aFBivAifj9YTLfnOMVKcyloUAbetYOX9Xie6yuyv9Jn0FRqQK9vDpzIQByfNwwA4DZIH8HUZnsXTdus79TJwIdTupq7SfZyoI2PIM694FpjGiM0CHT1sLcOQotWAKdUB6bDzaty7A8jy3rBCaw_XP08pS_jXzZe_0lCYEeTsDogTmFUwzCbRd-q6nxVoALBz7Ev9Q0R6AA"
}

View File

@@ -1,6 +1,9 @@
import { arrayToHex, GQLEdgeInterface, InteractionsSorter, LoggerFactory, SourceType } from '@smartweave';
import Arweave from 'arweave';
// note: this (i.e. padding to 13 digits) should be safe between years ~1966 and ~2286
const defaultArweaveMs = "".padEnd(13, "9");
/**
* implementation that is based on current's SDK sorting alg.
*/
@@ -36,6 +39,6 @@ export class LexicographicalInteractionsSorter implements InteractionsSorter {
const hashed = arrayToHex(await this.arweave.crypto.hash(concatenated));
const blockHeightString = `${blockHeight}`.padStart(12, '0');
return `${blockHeightString},${hashed}`;
return `${blockHeightString},${defaultArweaveMs},${hashed}`;
}
}