Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Credential indexer #4

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e0ba924
feat(tx-projection): add projection for transaction projected indexed…
will-break-it Jul 18, 2024
2a6cdad
feat(ogmios): add input source for cbor deserialization for transactions
will-break-it Aug 5, 2024
18e305b
refactor(byron-output-mapping): fix too long byron output addresses b…
will-break-it Aug 7, 2024
16c36f5
refactor(ogmios-byron-block) update byron block mapper for signatures
will-break-it Aug 7, 2024
97076f5
refactor(circular-deps): merged and adjusted imports for circular dep…
will-break-it Aug 8, 2024
fec9f87
feat(block-type): add block type to distinguish between bft and praos…
will-break-it Aug 8, 2024
dbe7ca1
feat(projector-mapper): add byron output address transformer for very…
will-break-it Aug 8, 2024
06b5717
refactor(circular-deps): merged and adjusted imports for circular dep…
will-break-it Aug 8, 2024
e0aac02
refactor(block-type): use of block type
will-break-it Aug 8, 2024
1d2acbd
refactor(blockmodel) update block model to include block type
will-break-it Aug 8, 2024
baf500a
reafactor(utxo-projection-mapper): Fix tests
will-break-it Aug 8, 2024
e7cad32
refactor(ogmios): address mapping; handled byron address transform in…
will-break-it Aug 8, 2024
71d7e5e
refactor(clean-up): removed unused constant; add docs
will-break-it Aug 8, 2024
f3195c5
refactor(projection-mapper): byron output address transformer
will-break-it Aug 8, 2024
2ecd968
Merge pull request #3 from will-break-it/credential-indexer-prototype
will-break-it Aug 9, 2024
5a5d5a5
test(cardano-services): group existing pgboss service tests under an …
mkazlauskas Aug 5, 2024
2dc1b9c
chore: update start-pg-boss-worker command in Dockerfile and docs
mkazlauskas Aug 6, 2024
fb4529e
fix: do not run schema migrations when starting pgboss worker
mkazlauskas Aug 5, 2024
3cad5b6
fix: add timeout to TypeormService withDataSource/withQueryRunner
mkazlauskas Aug 6, 2024
4d2b154
feat!: replace updateWitness with addSignatures in observable wallet
AngelCastilloB Aug 7, 2024
e799113
fix(hardware-ledger): delegate vote drep is a hash not key path
mirceahasegan Aug 5, 2024
1b98ec8
ci: publish packages [skip actions]
lace-bot Aug 7, 2024
414b75a
feat(tx-projection): add projection for transaction projected indexed…
will-break-it Jul 18, 2024
d450b32
refactor(ogmios-tests): add block type as expected output
will-break-it Aug 9, 2024
282ec11
refactor(circular-deps): Remove specific import & use serialization i…
will-break-it Aug 9, 2024
b490778
Merge branch 'master' into credential-indexer
will-break-it Aug 9, 2024
6effed6
refactor(ogmios-mapper): add cbor field explicitely
will-break-it Aug 9, 2024
5180e85
refactor(variable-length-decoding): support overflowing pointer addre…
will-break-it Aug 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ export const mapBlock = (
: Cardano.SlotLeader(blockModel.slot_leader_hash.toString('hex')),
totalOutput: BigInt(blockOutputModel?.output ?? 0),
txCount: Number(blockModel.tx_count),
type: blockModel.type,
vrf: blockModel.vrf as unknown as Cardano.VrfVkBech32
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface BlockModel {
slot_no: string;
time: string;
tx_count: string;
type: Cardano.BlockType;
vrf: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
AssetEntity,
BlockDataEntity,
BlockEntity,
CredentialEntity,
CurrentPoolMetricsEntity,
DataSourceExtensions,
HandleEntity,
Expand All @@ -17,28 +18,33 @@ import {
StakeKeyRegistrationEntity,
StakePoolEntity,
TokensEntity,
TransactionEntity,
createStorePoolMetricsUpdateJob,
createStoreStakePoolMetadataJob,
storeAddresses,
storeAssets,
storeBlock,
storeCredentials,
storeHandleMetadata,
storeHandles,
storeNftMetadata,
storeStakeKeyRegistrations,
storeStakePoolRewardsJob,
storeStakePools,
storeTransactions,
storeUtxo,
willStoreAddresses,
willStoreAssets,
willStoreBlockData,
willStoreCredentials,
willStoreHandleMetadata,
willStoreHandles,
willStoreNftMetadata,
willStoreStakeKeyRegistrations,
willStoreStakePoolMetadataJob,
willStoreStakePoolRewardsJob,
willStoreStakePools,
willStoreTransactions,
willStoreUtxo
} from '@cardano-sdk/projection-typeorm';
import { Cardano, ChainSyncEventType } from '@cardano-sdk/core';
Expand All @@ -57,6 +63,7 @@ export enum ProjectionName {
StakePoolMetadataJob = 'stake-pool-metadata-job',
StakePoolMetricsJob = 'stake-pool-metrics-job',
StakePoolRewardsJob = 'stake-pool-rewards-job',
Transaction = 'transaction',
UTXO = 'utxo'
}

Expand Down Expand Up @@ -101,7 +108,8 @@ const createMapperOperators = (
withNftMetadata: Mapper.withNftMetadata({ logger }),
withStakeKeyRegistrations: Mapper.withStakeKeyRegistrations(),
withStakePools: Mapper.withStakePools(),
withUtxo: Mapper.withUtxo()
withUtxo: Mapper.withUtxo(),
withValidByronAddresses: Mapper.withValidByronAddresses()
};
};
type MapperOperators = ReturnType<typeof createMapperOperators>;
Expand All @@ -112,6 +120,7 @@ export const storeOperators = {
storeAddresses: storeAddresses(),
storeAssets: storeAssets(),
storeBlock: storeBlock(),
storeCredentials: storeCredentials(),
storeHandleMetadata: storeHandleMetadata(),
storeHandles: storeHandles(),
storeNftMetadata: storeNftMetadata(),
Expand All @@ -123,6 +132,7 @@ export const storeOperators = {
storeStakePoolMetadataJob: createStoreStakePoolMetadataJob()(),
storeStakePoolRewardsJob: storeStakePoolRewardsJob(),
storeStakePools: storeStakePools(),
storeTransactions: storeTransactions(),
storeUtxo: storeUtxo()
};
type StoreOperators = typeof storeOperators;
Expand All @@ -138,13 +148,15 @@ type WillStore = {
const willStore: Partial<WillStore> = {
storeAddresses: willStoreAddresses,
storeAssets: willStoreAssets,
storeCredentials: willStoreCredentials,
storeHandleMetadata: willStoreHandleMetadata,
storeHandles: willStoreHandles,
storeNftMetadata: willStoreNftMetadata,
storeStakeKeyRegistrations: willStoreStakeKeyRegistrations,
storeStakePoolMetadataJob: willStoreStakePoolMetadataJob,
storeStakePoolRewardsJob: willStoreStakePoolRewardsJob,
storeStakePools: willStoreStakePools,
storeTransactions: willStoreTransactions,
storeUtxo: willStoreUtxo
};

Expand All @@ -153,6 +165,7 @@ const entities = {
asset: AssetEntity,
block: BlockEntity,
blockData: BlockDataEntity,
credential: CredentialEntity,
currentPoolMetrics: CurrentPoolMetricsEntity,
handle: HandleEntity,
handleMetadata: HandleMetadataEntity,
Expand All @@ -165,7 +178,8 @@ const entities = {
poolRewards: PoolRewardsEntity,
stakeKeyRegistration: StakeKeyRegistrationEntity,
stakePool: StakePoolEntity,
tokens: TokensEntity
tokens: TokensEntity,
transaction: TransactionEntity
};
export const allEntities = Object.values(entities);
type Entities = typeof entities;
Expand All @@ -176,6 +190,7 @@ const storeEntities: Partial<Record<StoreName, EntityName[]>> = {
storeAddresses: ['address'],
storeAssets: ['asset'],
storeBlock: ['block', 'blockData'],
storeCredentials: ['credential', 'transaction', 'output'],
storeHandleMetadata: ['handleMetadata', 'output'],
storeHandles: ['handle', 'asset', 'tokens', 'output'],
storeNftMetadata: ['asset'],
Expand All @@ -186,13 +201,15 @@ const storeEntities: Partial<Record<StoreName, EntityName[]>> = {
storeStakePoolMetadataJob: ['stakePool', 'currentPoolMetrics', 'poolMetadata'],
storeStakePoolRewardsJob: ['poolRewards', 'stakePool'],
storeStakePools: ['stakePool', 'currentPoolMetrics', 'poolMetadata', 'poolDelisted'],
storeTransactions: ['block', 'transaction'],
storeUtxo: ['tokens', 'output']
};

const entityInterDependencies: Partial<Record<EntityName, EntityName[]>> = {
address: ['stakeKeyRegistration'],
asset: ['block', 'nftMetadata'],
blockData: ['block'],
credential: [],
currentPoolMetrics: ['stakePool'],
handle: ['asset'],
handleMetadata: ['output'],
Expand All @@ -203,7 +220,8 @@ const entityInterDependencies: Partial<Record<EntityName, EntityName[]>> = {
poolRetirement: ['block'],
stakeKeyRegistration: ['block'],
stakePool: ['block', 'poolRegistration', 'poolRetirement'],
tokens: ['asset']
tokens: ['asset'],
transaction: ['block', 'credential']
};

export const getEntities = (entityNames: EntityName[]): Entity[] => {
Expand Down Expand Up @@ -235,12 +253,14 @@ const mapperInterDependencies: Partial<Record<MapperName, MapperName[]>> = {
withHandles: ['withMint', 'filterMint', 'withUtxo', 'filterUtxo', 'withCIP67'],
withNftMetadata: ['withCIP67', 'withMint', 'filterMint'],
withStakeKeyRegistrations: ['withCertificates'],
withStakePools: ['withCertificates']
withStakePools: ['withCertificates'],
withValidByronAddresses: ['withUtxo']
};

const storeMapperDependencies: Partial<Record<StoreName, MapperName[]>> = {
storeAddresses: ['withAddresses'],
storeAssets: ['withMint'],
storeCredentials: ['withAddresses', 'withCertificates', 'withUtxo', 'withValidByronAddresses'],
storeHandleMetadata: ['withHandleMetadata'],
storeHandles: ['withHandles'],
storeNftMetadata: ['withNftMetadata'],
Expand All @@ -260,6 +280,7 @@ const storeInterDependencies: Partial<Record<StoreName, StoreName[]>> = {
storeStakePoolMetadataJob: ['storeBlock'],
storeStakePoolRewardsJob: ['storeBlock'],
storeStakePools: ['storeBlock'],
storeTransactions: ['storeCredentials', 'storeBlock', 'storeUtxo'],
storeUtxo: ['storeBlock', 'storeAssets']
};

Expand All @@ -273,6 +294,7 @@ const projectionStoreDependencies: Record<ProjectionName, StoreName[]> = {
'stake-pool-metadata-job': ['storeStakePoolMetadataJob'],
'stake-pool-metrics-job': ['storePoolMetricsUpdateJob'],
'stake-pool-rewards-job': ['storeStakePoolRewardsJob'],
transaction: ['storeCredentials', 'storeTransactions'],
utxo: ['storeUtxo']
};

Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/Cardano/Address/PointerAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,27 @@ const variableLengthEncode = (val: number): Buffer => {
};

/**
* Decodes a value previously encoded in a variable length array.
* Decodes a value previously encoded in a variable length array only
* up to Number.MAX_SAFE_INTEGER values before decoding to 'Infinity'.
*
* @param array The encoded value.
* @returns the decoded value.
*/
const variableLengthDecode = (array: Buffer): { value: number; bytesRead: number } => {
let more = true;
let value = 0;
let value = 0n;

let bytesRead = 0;
while (more && bytesRead < array.length) {
const b = array[bytesRead];
value <<= 7;
value |= b & 127;
value <<= 7n;
value |= BigInt(b & 127);

more = (b & 128) !== 0;
++bytesRead;
}

return { bytesRead, value };
return { bytesRead, value: value <= Number.MAX_SAFE_INTEGER ? Number(value) : Number.POSITIVE_INFINITY };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a test for round-tripping a Pointer address that uses a slot>MAX_SAFE_INTEGER. In order for that to work, we'll need to change this Pointer type to store a bigint, and save the full value when packing in order to reuse when unpacking

};

/** A transaction index (within a slot). */
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/Cardano/types/Block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,13 @@ VrfVkBech32.fromHex = (value: string) => {
return VrfVkBech32(BaseEncoding.bech32.encode('vrf_vk', words, 1023));
};

export type BlockType = 'bft' | 'praos';

/** Minimal Block type meant as a base for the more complete version `Block` */
// TODO: optionals (except previousBlock) are there because they are not calculated for Byron yet.
// Remove them once calculation is done and remove the Required<BlockMinimal> from interface Block
export interface BlockInfo {
type: BlockType;
header: PartialBlockHeader;
/** Byron blocks fee not calculated yet */
fees?: Lovelace;
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/Cardano/types/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { PlutusData } from './PlutusData';
import { ProposalProcedure, VotingProcedures } from './Governance';
import { RewardAccount } from '../Address';
import { Script } from './Script';
import { Serialization } from '../..';

/** transaction hash as hex string */
export type TransactionId = OpaqueString<'TransactionId'>;
Expand Down Expand Up @@ -151,6 +152,7 @@ export interface OnChainTx<TBody extends TxBody = TxBody>
extends Omit<TxWithInputSource<TBody>, 'witness' | 'auxiliaryData'> {
witness: Omit<Witness, 'scripts'>;
auxiliaryData?: Omit<AuxiliaryData, 'scripts'>;
cbor?: Serialization.TxCBOR;
}

export interface HydratedTx extends TxWithInputSource<HydratedTxBody> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const legacyOutputNoDatumCbor = HexBlob(
'82583900537ba48a023f0a3c65e54977ffc2d78c143fb418ef6db058e006d78a7c16240714ea0e12b41a914f2945784ac494bb19573f0ca61a08afa8821a000f4240a2581c00000000000000000000000000000000000000000000000000000000a3443031323218644433343536186344404142420a581c11111111111111111111111111111111111111111111111111111111a3443031323218644433343536186344404142420a'
);

const maryOutputPointerCbor = HexBlob(
'825826412813b99a80cfb4024374bd0f502959485aa56e0648564ff805f2e51bbcd9819561bddc66141a02faf080'
);

const babbageAllFieldsCbor = HexBlob(
'a400583900537ba48a023f0a3c65e54977ffc2d78c143fb418ef6db058e006d78a7c16240714ea0e12b41a914f2945784ac494bb19573f0ca61a08afa801821a000f4240a2581c00000000000000000000000000000000000000000000000000000000a3443031323218644433343536186344404142420a581c11111111111111111111111111111111111111111111111111111111a3443031323218644433343536186344404142420a028201d81849d8799f0102030405ff03d8185182014e4d01000033222220051200120011'
);
Expand Down Expand Up @@ -225,6 +229,18 @@ describe('TransactionOutput', () => {
});
});

describe('Pointer Address Output', () => {
it('can decode PointerAddressOutput from CBOR', () => {
const output = TransactionOutput.fromCbor(maryOutputPointerCbor);
const hash = output.address().asPointer()?.getPaymentCredential().hash;
expect(hash).toEqual('2813b99a80cfb4024374bd0f502959485aa56e0648564ff805f2e51b');
const pointer = output.address().asPointer()?.getStakePointer();
expect(pointer?.slot).toEqual(16_292_793_057);
expect(pointer?.certIndex).toEqual(20);
expect(pointer?.txIndex).toEqual(1_011_302);
});
});

describe('Inline Datum', () => {
it('can decode TransactionOutput from CBOR', () => {
const output = TransactionOutput.fromCbor(babbageInlineDatumCbor);
Expand Down
2 changes: 2 additions & 0 deletions packages/ogmios/src/ogmiosToCore/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const mapByronBlock = (block: Schema.BlockBFT): Cardano.Block => ({
size: mapBlockSize(block),
totalOutput: mapTotalOutputs(block),
txCount: mapTxCount(block),
type: block.type,
vrf: undefined // no vrf key for byron. DbSync doesn't have one either
});

Expand All @@ -86,6 +87,7 @@ const mapCommonBlock = (block: CommonBlock): Cardano.Block => ({
size: mapBlockSize(block),
totalOutput: mapTotalOutputs(block),
txCount: mapTxCount(block),
type: block.type,
vrf: mapCommonVrf(block)
});

Expand Down
10 changes: 7 additions & 3 deletions packages/ogmios/src/ogmiosToCore/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ const mapCommonTx = (tx: Schema.Transaction): Cardano.OnChainTx => {
withdrawals: mapWithdrawals(tx.withdrawals)
})
},
cbor: tx.cbor ? Serialization.TxCBOR(tx.cbor) : undefined,
id: Cardano.TransactionId(tx.id),
// At the time of writing Byron transactions didn't set this property
inputSource: mapInputSource(tx.spends),
Expand All @@ -448,19 +449,22 @@ const mapCommonTx = (tx: Schema.Transaction): Cardano.OnChainTx => {
// ...(tx.scripts && { scripts: [...Object.values(tx.scripts).map(mapScript)] }),
signatures: new Map(
tx.signatories
.filter((signatory) => !signatory.addressAttributes && !signatory.chainCode)
.filter((signatory) => !signatory.addressAttributes && !signatory.chainCode && signatory.key.length === 64)
.map(({ key, signature }) => [Crypto.Ed25519PublicKeyHex(key), Crypto.Ed25519SignatureHex(signature)])
)
}
};
};

const isByronEraBlock = ({ type }: CommonBlock | Schema.BlockBFT) => type === 'bft';

export const mapBlockBody = (block: CommonBlock | Schema.BlockBFT): Cardano.Block['body'] => {
const { transactions, type } = block;
const { transactions } = block;
return (transactions || []).map((transaction) =>
type !== 'bft' && transaction.cbor
!isByronEraBlock(block) && transaction.cbor
? {
...Serialization.Transaction.fromCbor(transaction.cbor as Serialization.TxCBOR).toCore(),
cbor: transaction.cbor as Serialization.TxCBOR,
inputSource: mapInputSource(transaction.spends)
}
: mapCommonTx(transaction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ Array [
"size": 1880,
"totalOutput": 29999998493561943n,
"txCount": 1,
"type": "praos",
"vrf": "vrf_vk1ny8dyz3pa9u7v7h8l5evsmxxjq07dk6j5uda60lxe3zsya5ea20s2c6jph",
},
"eventType": 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ Object {
"size": 8511,
"totalOutput": 29698651346n,
"txCount": 6,
"type": "praos",
"vrf": "vrf_vk1afy7gefvgc9eaek64lhunxw2velmuh4467n6a2aalah7r8q68j0s4f2sa9",
}
`;
Expand Down Expand Up @@ -711,6 +712,7 @@ Object {
"size": 1193,
"totalOutput": 29699998493147869n,
"txCount": 1,
"type": "praos",
"vrf": "vrf_vk1wpa9axwwassnadt8drdrzptxm285latvhhvsgv0t6zhp0akgej9sfgecvl",
}
`;
Expand Down Expand Up @@ -790,6 +792,7 @@ Object {
"size": 1152,
"totalOutput": 29699998492735907n,
"txCount": 1,
"type": "praos",
"vrf": "vrf_vk1aw6s04lqkquell8drg6jjusrzd8c5259kctvxkgug5kta7nphz9qfqtr4w",
}
`;
Expand Down Expand Up @@ -825,6 +828,7 @@ Object {
],
"requiredExtraSignatures": undefined,
},
"cbor": "82839f8200d8185824825820a12a839c25a01fa5d118167db5acdbd9e38172ae8f00e5ac0a4997ef792a200700ff9f8282d818584283581c6c9982e7f2b6dcc5eaa880e8014568913c8868d9f0f86eb687b2633ca101581e581c010d876783fb2b4d0d17c86df29af8d35356ed3d1827bf4744f06700001a8dc672c11a000f4240ffa0818202d81858658258208c0bdedfbbab26a1308300512ffb1b220f068ee13f7612afb076c22de3fb764158406cc41635a9794234966629ccfa2a5b089a20ae392f0e92154ff97eda30ff7a082a65fc4b362c24cf58c27f30103b1f1345e15479cf4b80cd4134c0f9dca83109",
"id": "6497b33b10fa2619c6efbd9f874ecd1c91badb10bf70850732aab45b90524d9e",
"inputSource": undefined,
"witness": Object {
Expand All @@ -846,6 +850,7 @@ Object {
"size": 908,
"totalOutput": 1000000n,
"txCount": 1,
"type": "bft",
"vrf": undefined,
}
`;
Expand Down Expand Up @@ -925,6 +930,7 @@ Object {
"size": 1151,
"totalOutput": 29699998492941888n,
"txCount": 1,
"type": "praos",
"vrf": "vrf_vk1aw6s04lqkquell8drg6jjusrzd8c5259kctvxkgug5kta7nphz9qfqtr4w",
}
`;
Expand Down Expand Up @@ -1157,6 +1163,7 @@ Object {
"size": 1880,
"totalOutput": 29999998493561943n,
"txCount": 1,
"type": "praos",
"vrf": "vrf_vk1ny8dyz3pa9u7v7h8l5evsmxxjq07dk6j5uda60lxe3zsya5ea20s2c6jph",
}
`;
Loading
Loading