-
Notifications
You must be signed in to change notification settings - Fork 25
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
chore(domain): adds domain model, based on APIs, and various inputs #154
base: main
Are you sure you want to change the base?
Conversation
Would it be good to include the |
docs/domain/domain-model.gql
Outdated
enum ChainwebNetwork { | ||
mainnet01 | ||
testnet04 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to be able to interact with test versions including devnet versions, this may be best kept as a string.
docs/domain/domain-model.gql
Outdated
type Cut { | ||
height: BigInt | ||
weight: Hash | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cuts have some more information, a cut in general is a mapping from chain IDs to block header hashes. The other properties are derived from those block headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference: the following command get a cut
in JSON representation:
curl -sk https://api.chainweb.com/chainweb/0.0/mainnet01/cut | jq
Here is an example:
{
"hashes": {
"12": {
"height": 3512387,
"hash": "qoZL-lcmcixKM6DsMlGIzq4coULTjqx3Y5hfdCudJS0"
},
"13": {
"height": 3512387,
"hash": "XqnmwgX5waN3o9gWZbnsUElLNX5z1NIXLNmQtii85fc"
},
"14": {
"height": 3512387,
"hash": "XjqNxZZKGBkLVAyIofj4WsqkBaPsj_nX3HAcP9mhCSU"
},
"15": {
"height": 3512387,
"hash": "OLtNO3eaQo-0fymKsgLS9k_YCaJz9q0Tusb2m0PbDg4"
},
"8": {
"height": 3512387,
"hash": "wdMmjmYc1ykJwcSO4hahRpNsHZPFP6lyIpRcg21tMxk"
},
"9": {
"height": 3512387,
"hash": "yMPa6aYlXIDk2HGLWEv8PH1fdNwPIrbHl36r-E7YU_o"
},
"10": {
"height": 3512388,
"hash": "TC6S0S9xYoKRj6imiTfO_a3yigMFQSbcJpcHirXbmgQ"
},
"11": {
"height": 3512388,
"hash": "sbZa24LIDqeBOEYnnqRsfafd0A-JclttD9sti7mocHM"
},
"4": {
"height": 3512387,
"hash": "qfwKlsNJxPTys8MwgyXW09ynP6SXvSolrNBSRWCTW5Q"
},
"5": {
"height": 3512387,
"hash": "W88AnXR8gRfq9fLDxzmX86ixrXqkgA7dYFV4SCdAuic"
},
"6": {
"height": 3512387,
"hash": "_XYqx572X9ucwLYP5l3dDKC0IKJ9m_-2PFK0ymFtdd8"
},
"7": {
"height": 3512387,
"hash": "s4zKVxxKu0nOjoTtqZaLkaE-RV8RsV6aszdDMLHXE3g"
},
"0": {
"height": 3512387,
"hash": "HdYVc0VGaH7Su2cEDmfJuyM4Sc1Cv2S_9Jg9VKRiMOw"
},
"16": {
"height": 3512386,
"hash": "a2uzoLkEuFfsWWoPOuurvt8QeGnusnEXt0-KsnDmGMU"
},
"1": {
"height": 3512387,
"hash": "8-iv8kMTI8pC920rgnqSFlzlcEclWETR-Bfwq6tQiFI"
},
"17": {
"height": 3512387,
"hash": "uD8QPH6jWglmWp6ne6AgFNKVcPooONJgCCzMQuSlEc4"
},
"2": {
"height": 3512387,
"hash": "Um-2ceGXomt8gLFSQlIniIHDZB2_fw0Dbx5b7hE6MkA"
},
"18": {
"height": 3512388,
"hash": "SHhZ4R8f3RUfQPVPWm20P26eKgG_-UBpH9GZ_PZSXVY"
},
"3": {
"height": 3512387,
"hash": "FjirHdHhO3hOLUnkAH5f28yc7A3YjExX-ZirxDcCPfw"
},
"19": {
"height": 3512387,
"hash": "31CpGbw3ABsUxVW41SuHpIYot6eixcUB4vABk_YVwgU"
}
},
"origin": null,
"weight": "qJrdqrUWrTh-8QQAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"height": 70247742,
"instance": "mainnet01",
"id": "TSVbbu10brCcuZ_DxKbJtzYRN-UBGUndyQbgLwLYwro"
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that the GraphQL does not support dictionaries. So there has to be a key for each chain:
type Cut { | |
height: BigInt | |
weight: Hash | |
} | |
type CutChain { | |
height: BlockHeight! | |
hash: BlockHash! | |
} | |
type CutHashes { | |
0: CutChain! | |
1: CutChain! | |
2: CutChain! | |
3: CutChain! | |
4: CutChain! | |
5: CutChain! | |
6: CutChain! | |
7: CutChain! | |
8: CutChain! | |
9: CutChain! | |
10: CutChain! | |
11: CutChain! | |
12: CutChain! | |
13: CutChain! | |
14: CutChain! | |
15: CutChain! | |
16: CutChain! | |
17: CutChain! | |
18: CutChain! | |
19: CutChain! | |
} | |
type Cut { | |
hashes: CutHashes! | |
origin: String | |
weight: BlockWeight! | |
height: BlockHeight! | |
instance: ChainwebNetwork! | |
id: CutHash! | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that the use of numbers as keys (either directly or as string) isn't supported in GraphQL. So, the current JSON wouldn't work.
So, maybe we would have to use
type CutChain {
chain: ChainId!
height: BlockHeight!
hash: BlockHash!
}
type Cut {
hashes: [CutChain!]!
origin: String
weight: BlockWeight!
height: BlockHeight!
instance: ChainwebNetwork!
id: CutHash!
}
This would break the existing JSON encoding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The review proposes quite a few new custom scalars. Not sure if we want that. However, the chainweb data types (Block and BlockPayload) are part of the Merkle tree and thus have pretty git types and semantics. In particular hashes are just opaque identifiers.
Recursively specified types seem to be a potential source of DOS vectors. But I don't know how queries on recursively specified types are implemented in GraphQL and whether there is a build in solution for this. Also, references to adjacent blocks form a DAG (a huge one) and if GraphQL queries aren't careful about sharing, this would result in exponential blowup in the response. So, I propose to avoid recursive types.
Also almost (but not all fields) are non-nullable
.
The appropriate GraphQL representation for adjacents
of a Block
is an open question.
docs/domain/domain-model.gql
Outdated
weight: Base64Url | ||
featureFlags: Int | ||
epochStart: MsFromPosixEpoch | ||
adjacents: [Block] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of Block
makes the type recursive. Not sure if we want support this. It would probably rarely be useful and would also constitute a potential DOS vector.
Technically adjacents
are a (partial) mapping from a ChainId
to BlockHash
. Here is an example of the JSON encoding:
"adjacents": {
"5": "dTLm0UrocvMNjjz_TMUbWqpZhuBBht_JoNqZpCliaS8",
"2": "fJB-vS9h7ByxNHY19WqM8icji9CcATiXn48uouHAMzs",
"3": "UsNRCUkMKQBRDVIv0JLDfDllYNg2QO0EXaWcRfMQ6g0"
}
The problem is that the keys depend on the chain id of the block (they are the adjacent chains in the chain graph). A representation as list would assume knowledge of the graph. I don't think GraphQL's type language has support expressing this.
In GraphQL we could express this as
adjacents: [(ChainId, BlockHash)]
But this representation would break the existing JSON APIs of chainweb-node and api.chainweb.com.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what would be a good solution. Maybe simply Object
?
Or maybe using a union type for adjacents:
type Adjacents0 {
2: BlockHash!
3: BlockHash!
5: BlockHash!
}
type Adjacents1 {
# ...
}
# ...
union Adjacents = Adjacents0 | Adjacents1 | ... | Adjacents19
Or event creating one Block type per chain? But that would be pretty verbose and would make queries more complicated.
interface Block {
# ...
}
type Block0 implements Block {
adjacents: Adjacents0!
}
type Block1 {
adjacents: Adjacents1!
}
# ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another problem is that the use of numbers as field keys (either directly or quoted as strings) is not supported by GraphQL. So, it is not clear how to best encode our chains. (Unfortunately, enums aren't supported as keys neither.)
target: Base64Url | ||
nonce: Int64 | ||
|
||
payload: BlockPayload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is should be fine, because BlockPayload
is not mutually recursive with Block
. Still it could allow for pretty big query results (unless restricted by other means), possibly providing a DOS vector. It is also currently not supported by chainweb-node and api.chainweb.com.
I guess, since it is not marked as nullable
the server would always be free to just return null
.
sig: String | ||
} | ||
|
||
type Block { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference. This returns a JSON representation of a Block:
curl -sk https://api.chainweb.com/chainweb/0.0/mainnet01/chain/0/header?limit=1 -H 'accept: application/json;blockheader-encoding=object' | jq '.items[0]'
Here is an example:
{
"nonce": "0",
"creationTime": 1572393660000000,
"parent": "wJ6fVF6_vrzfemqQsWB6nCzfrMwznbZscn53-0DpAcI",
"adjacents": {
"5": "dTLm0UrocvMNjjz_TMUbWqpZhuBBht_JoNqZpCliaS8",
"2": "fJB-vS9h7ByxNHY19WqM8icji9CcATiXn48uouHAMzs",
"3": "UsNRCUkMKQBRDVIv0JLDfDllYNg2QO0EXaWcRfMQ6g0"
},
"target": "__________________________________________8",
"payloadHash": "k1H3DsInAPvJ0W_zPxnrpkeSNdPUT0S9U8bqDLG739o",
"chainId": 0,
"weight": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"height": 0,
"chainwebVersion": "mainnet01",
"epochStart": 1572393660000000,
"featureFlags": 0,
"hash": "SNAMXHBvZtAbeS19x12bZV2p5d1E4BaxrggceNdUxbw"
}
docs/domain/domain-model.gql
Outdated
type Cut { | ||
height: BigInt | ||
weight: Hash | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference: the following command get a cut
in JSON representation:
curl -sk https://api.chainweb.com/chainweb/0.0/mainnet01/cut | jq
Here is an example:
{
"hashes": {
"12": {
"height": 3512387,
"hash": "qoZL-lcmcixKM6DsMlGIzq4coULTjqx3Y5hfdCudJS0"
},
"13": {
"height": 3512387,
"hash": "XqnmwgX5waN3o9gWZbnsUElLNX5z1NIXLNmQtii85fc"
},
"14": {
"height": 3512387,
"hash": "XjqNxZZKGBkLVAyIofj4WsqkBaPsj_nX3HAcP9mhCSU"
},
"15": {
"height": 3512387,
"hash": "OLtNO3eaQo-0fymKsgLS9k_YCaJz9q0Tusb2m0PbDg4"
},
"8": {
"height": 3512387,
"hash": "wdMmjmYc1ykJwcSO4hahRpNsHZPFP6lyIpRcg21tMxk"
},
"9": {
"height": 3512387,
"hash": "yMPa6aYlXIDk2HGLWEv8PH1fdNwPIrbHl36r-E7YU_o"
},
"10": {
"height": 3512388,
"hash": "TC6S0S9xYoKRj6imiTfO_a3yigMFQSbcJpcHirXbmgQ"
},
"11": {
"height": 3512388,
"hash": "sbZa24LIDqeBOEYnnqRsfafd0A-JclttD9sti7mocHM"
},
"4": {
"height": 3512387,
"hash": "qfwKlsNJxPTys8MwgyXW09ynP6SXvSolrNBSRWCTW5Q"
},
"5": {
"height": 3512387,
"hash": "W88AnXR8gRfq9fLDxzmX86ixrXqkgA7dYFV4SCdAuic"
},
"6": {
"height": 3512387,
"hash": "_XYqx572X9ucwLYP5l3dDKC0IKJ9m_-2PFK0ymFtdd8"
},
"7": {
"height": 3512387,
"hash": "s4zKVxxKu0nOjoTtqZaLkaE-RV8RsV6aszdDMLHXE3g"
},
"0": {
"height": 3512387,
"hash": "HdYVc0VGaH7Su2cEDmfJuyM4Sc1Cv2S_9Jg9VKRiMOw"
},
"16": {
"height": 3512386,
"hash": "a2uzoLkEuFfsWWoPOuurvt8QeGnusnEXt0-KsnDmGMU"
},
"1": {
"height": 3512387,
"hash": "8-iv8kMTI8pC920rgnqSFlzlcEclWETR-Bfwq6tQiFI"
},
"17": {
"height": 3512387,
"hash": "uD8QPH6jWglmWp6ne6AgFNKVcPooONJgCCzMQuSlEc4"
},
"2": {
"height": 3512387,
"hash": "Um-2ceGXomt8gLFSQlIniIHDZB2_fw0Dbx5b7hE6MkA"
},
"18": {
"height": 3512388,
"hash": "SHhZ4R8f3RUfQPVPWm20P26eKgG_-UBpH9GZ_PZSXVY"
},
"3": {
"height": 3512387,
"hash": "FjirHdHhO3hOLUnkAH5f28yc7A3YjExX-ZirxDcCPfw"
},
"19": {
"height": 3512387,
"hash": "31CpGbw3ABsUxVW41SuHpIYot6eixcUB4vABk_YVwgU"
}
},
"origin": null,
"weight": "qJrdqrUWrTh-8QQAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"height": 70247742,
"instance": "mainnet01",
"id": "TSVbbu10brCcuZ_DxKbJtzYRN-UBGUndyQbgLwLYwro"
}
docs/domain/domain-model.gql
Outdated
@@ -0,0 +1,165 @@ | |||
scalar Hash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the purpose of this model hashes are most likely just unique identifiers (and possibly cryptographic fingerprints). So, it may make sense to consider them just as opaque IDs.
In any case I propose to also include the type that is referenced/identified with that hash:
scalar Hash | |
# chainweb | |
scalar BlockHash | |
scalar PayloadHash | |
scalar CutHash | |
scalar PayloadTransactionsHash | |
scalar PayloadOutputsHash | |
# pact | |
scalar TransactionHash |
docs/domain/domain-model.gql
Outdated
chainId: Int | ||
weight: Base64Url | ||
featureFlags: Int | ||
epochStart: MsFromPosixEpoch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
epochStart: MsFromPosixEpoch | |
epochStart(format: DateFormat = ISO8601): Date! |
docs/domain/domain-model.gql
Outdated
epochStart: MsFromPosixEpoch | ||
adjacents: [Block] | ||
payloadHash: Base64Url # fk BlockPayload | ||
chainwebVersion: ChainwebNetwork |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chainwebVersion: ChainwebNetwork | |
chainwebVersion: ChainwebNetwork! |
docs/domain/domain-model.gql
Outdated
transactions: [Transaction] # pact realm | ||
minerData: Account |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transactions: [Transaction] # pact realm | |
minerData: Account | |
transactions: [Transaction!]! # pact realm | |
minerData: Account! |
docs/domain/domain-model.gql
Outdated
transactionsHash: Base64Url | ||
outputsHash: Base64Url | ||
payloadHash: Base64Url | ||
coinbase: CoinbaseTransaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coinbase: CoinbaseTransaction | |
coinbase: CoinbaseTransaction! |
docs/domain/domain-model.gql
Outdated
command: TransactionCommand | ||
commandResult: TransactionCommandResult |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some services may not have the results available (e.g. they are not needed for validation and in the future we decide to make storage of results in nodes optional). So, it probably makes sense to keep results nullable
.
command: TransactionCommand | |
commandResult: TransactionCommandResult | |
command: TransactionCommand! | |
commandResult: TransactionCommandResult |
This PR is stale because it is open for 60 days with no activity |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
2 Skipped Deployments
|
This PR is stale because it is open for 60 days with no activity |
7ba84ec
to
b848df0
Compare
|
b848df0
to
e37a4a1
Compare
No description provided.