Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Improve Interoperability LIPs #187

Merged
merged 44 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d1689f5
init
ricott1 Nov 17, 2022
e0bbcca
updates to LIP 0043
ricott1 Nov 17, 2022
8f28ccd
LIP0049: remove islive from sidechain terminated message
ricott1 Nov 17, 2022
edd40bd
LIP0054: fix typo
ricott1 Nov 17, 2022
9fd27f0
LIP0053: update call to verifyAggregateCertificateSignature, add chec…
ricott1 Nov 21, 2022
795f96c
LIP0043: fix header levels
ricott1 Nov 23, 2022
02ae7dd
LIP0045: remove unused mainchain constants and fix calculateNewActive…
ricott1 Nov 23, 2022
184adb7
LIP0049: Stop forwarded messages if direct channel exists in apply fu…
ricott1 Nov 23, 2022
6ffd88b
LIP0053: make validators update smaller by including newBLSKeys and n…
ricott1 Nov 23, 2022
18370dc
LIP0053: implement validators update with bitmap
ricott1 Nov 24, 2022
3e0843d
LIP0045: remove unused constant
ricott1 Nov 29, 2022
35ad371
LIP0053: add description for bftUpdateBitmap in rationale
ricott1 Nov 29, 2022
232a456
LIP0045: emit event after defining ccm
ricott1 Dec 5, 2022
852ec73
rename schemas to match substore names
ricott1 Dec 6, 2022
afd731c
LIP0043: address Greg's review
ricott1 Dec 6, 2022
f9bfbf2
LIP0053: fix small typos from Greg's review
ricott1 Dec 6, 2022
659b30f
LIP0045: remove usage of floor function
ricott1 Dec 6, 2022
4aeb468
Add full ccm to ccmSent and ccmProcessed events data
ricott1 Dec 8, 2022
cc686aa
LIP0045 and LIP0053: emit event with empty ccm when event code is CCM…
ricott1 Dec 8, 2022
5196e35
LIP0043: change delegate to validator and remove dead link
ricott1 Dec 9, 2022
8930233
LIP0045: fix notation of sha256 in function
ricott1 Dec 9, 2022
75560bb
LIP0045: update description of calculateNewActiveValidators
ricott1 Dec 12, 2022
e50b888
LIP0053: reintroduce single object activeValidatorsUpdate in CCU. Fix…
ricott1 Dec 12, 2022
43a6002
address Greg's review
ricott1 Dec 13, 2022
e1c299f
address Greg's review
ricott1 Dec 14, 2022
800c951
LIP0043: small cosmetic improvement
ricott1 Dec 14, 2022
091ef34
rename REGISTRATION_FEE to CHAIN_REGISTRATION_FEE
ricott1 Dec 20, 2022
78628b3
Address Andreas' review
ricott1 Dec 20, 2022
b456083
LIP0045: fix mainchain name
ricott1 Dec 20, 2022
37fec44
LIP53 and LIP45: add more granularity to ccm validation
ricott1 Jan 4, 2023
fd06135
LIP0043: remove check about length of mainchainValidators array
ricott1 Jan 4, 2023
db66985
LIP0043: check that mainchain account has not been registered yet
ricott1 Jan 4, 2023
3626723
LIP0043: check length of validators array
ricott1 Jan 4, 2023
03f98ac
LIP0045: fix sendInternal function
ricott1 Jan 4, 2023
138f78a
LIP0043: remove redundant check
ricott1 Jan 4, 2023
cdcb637
LIP0043 and LIP0045: add constant NUMBER_ACTIVE_VALIDATORS_MAINCHAIN …
ricott1 Jan 4, 2023
c55edbb
LIP0053: update partnerChainOutboxRoot after appending all ccms; upda…
ricott1 Jan 9, 2023
9bb4bbb
Address Andreas' review
ricott1 Jan 9, 2023
dabcd01
LIP0053: address Greg's review
ricott1 Jan 10, 2023
a5e7ec1
Greg's review
ricott1 Jan 10, 2023
43d7a1a
LIP0053: improve exception text
ricott1 Jan 10, 2023
9c0cdc1
LIP0043: remove two broken links
ricott1 Jan 13, 2023
5e1ed57
:nail_care: Apply standards
Jan 13, 2023
ceb70eb
:pencil: Update header
Jan 13, 2023
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
194 changes: 117 additions & 77 deletions proposals/lip-0043.md

Large diffs are not rendered by default.

219 changes: 115 additions & 104 deletions proposals/lip-0045.md

Large diffs are not rendered by default.

75 changes: 51 additions & 24 deletions proposals/lip-0049.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Discussions-To: https://research.lisk.com/t/introduce-cross-chain-messages/299
Status: Draft
Type: Standards Track
Created: 2021-05-22
Updated: 2022-11-11
Updated: 2023-01-13
Requires: 0053
```

Expand Down Expand Up @@ -236,7 +236,7 @@ def validateFormat(ccm: CCM) -> None:
if not re.match("^[a-zA-Z0-9]*$", ccm.crossChainCommand):
raise Exception("Cross-chain message command name must be alphanumeric.")
# Check ccm size.
if ccmBytes > MAX_CCM_SIZE:
if len(ccmBytes) > MAX_CCM_SIZE:
raise Exception(f"Cross-chain message size is larger than {MAX_CCM_SIZE}.")
```

Expand All @@ -250,8 +250,6 @@ _Figure 1: A schematic of the steps executed in the `apply` function. Blue bored

```python
def apply(ccu: Transaction, ccm: CCM) -> None:
# Calculate CCM ID, used later in events.
ccmID = sha256(encode(crossChainMessageSchema, ccm))
try:
if not isLive(ccm.sendingChainID):
raise Exception(f"Sending chain {ccm.sendingChainID} is not live.")
Expand All @@ -266,7 +264,7 @@ def apply(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_CCM_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_CCM_EXCEPTION},
ricott1 marked this conversation as resolved.
Show resolved Hide resolved
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
return
Expand All @@ -286,7 +284,7 @@ def apply(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_EXCEPTION},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
return
Expand All @@ -304,19 +302,26 @@ def apply(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_BEFORE_CCC_EXECUTION_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_BEFORE_CCC_EXECUTION_EXCEPTION},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
return
# Create a state snapshot.
executionSnapshot = snapshot of the current state
try:
# This could happen during the execution of a mainchain CCU containing a CCM
# from a sidechain for which a direct channel has been registered.
# Then, ccu.params.sendingChainID == CHAIN_ID_MAINCHAIN.
# This is not necessarily a violation of the protocol, since the message
# could have been sent before the direct channel was opened.
if chainAccount(ccm.sendingChainID) exists and ccu.params.sendingChainID != ccm.sendingChainID:
raise Exception("Cannot receive forwarded messages for a direct channel.")
AndreasKendziorra marked this conversation as resolved.
Show resolved Hide resolved
# Execute the cross-chain command.
crossChainCommand.execute(ccu, ccm)
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_APPLIED, "code": CCM_PROCESSED_CODE_SUCCESS},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_APPLIED, "code": CCM_PROCESSED_CODE_SUCCESS},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
except:
Expand All @@ -333,7 +338,7 @@ def apply(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_AFTER_CCC_EXECUTION_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_AFTER_CCC_EXECUTION_EXCEPTION},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
```
Expand All @@ -348,8 +353,6 @@ _Figure 2: A schematic of the steps executed in the `forward` function. Blue bor

```python
def forward(ccu: Transaction, ccm: CCM) -> None:
# Calculate CCM ID, used later in events.
ccmID = sha256(encode(crossChainMessageSchema, ccm))
try:
if not isLive(ccm.sendingChainID):
raise Exception(f"Sending chain {ccm.sendingChainID} is not live.")
Expand All @@ -364,7 +367,7 @@ def forward(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_CCM_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_VERIFY_CCM_EXCEPTION},
ricott1 marked this conversation as resolved.
Show resolved Hide resolved
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
return
Expand All @@ -386,7 +389,7 @@ def forward(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_CHANNEL_UNAVAILABLE},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_CHANNEL_UNAVAILABLE},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)

Expand All @@ -404,7 +407,7 @@ def forward(ccu: Transaction, ccm: CCM) -> None:
ccm.sendingChainID,
0,
CCM_STATUS_CODE_OK,
stmParams
encode(sidechainTerminatedCCMParamsSchema, stmParams)
)
return

Expand All @@ -421,7 +424,7 @@ def forward(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_BEFORE_CCC_FORWARDING_EXCEPTION},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_DISCARDED, "code": CCM_PROCESSED_CODE_INVALID_CCM_BEFORE_CCC_FORWARDING_EXCEPTION},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
return
Expand All @@ -431,7 +434,7 @@ def forward(ccu: Transaction, ccm: CCM) -> None:
emitEvent(
module = MODULE_NAME_INTEROPERABILITY,
name = EVENT_NAME_CCM_PROCESSED,
data = {"ccmID": ccmID, "result": CCM_PROCESSED_RESULT_FORWARDED, "code": CCM_PROCESSED_CODE_SUCCESS},
data = {"ccm": ccm, "result": CCM_PROCESSED_RESULT_FORWARDED, "code": CCM_PROCESSED_CODE_SUCCESS},
topics = [ccm.sendingChainID, ccm.receivingChainID]
)
```
Expand Down Expand Up @@ -461,8 +464,9 @@ A channel terminated message is created by the Interoperability module when [ter

```python
def execute(ccu: Transaction, ccm: CCM) -> None:
AndreasKendziorra marked this conversation as resolved.
Show resolved Hide resolved
if isLive(ccm.sendingChainID):
createTerminatedStateAccount(ccm.sendingChainID)
if terminatedStateAccount(ccm.sendingChainID) exists:
return
createTerminatedStateAccount(ccm.sendingChainID)
```

The function `createTerminatedStateAccount` is defined in [LIP 0045][lip-0045#createTerminatedStateAccount].
Expand All @@ -485,23 +489,32 @@ registrationCCMParamsSchema = {
"type": "object",
"required" : [
"name",
"chainID",
"messageFeeTokenID"
],
"properties": {
"name": {
"dataType": "string",
"minLength": MIN_CHAIN_NAME_LENGTH,
"maxLength": MAX_CHAIN_NAME_LENGTH,
"fieldNumber": 1
},
"chainID": {
"dataType": "bytes",
"length": CHAIN_ID_LENGTH,
"fieldNumber": 2
},
"messageFeeTokenID": {
"dataType": "bytes",
"length": TOKEN_ID_LENGTH,
"fieldNumber": 2
"fieldNumber": 3
}
}
}
```

* `name`: name registered on the mainchain.
* `chainID`: chain ID registered on the mainchain.
* `messageFeeTokenID`: ID of the token used for cross-chain message fees.

##### Creation
Expand All @@ -512,6 +525,15 @@ A registration message is created by the Interoperability module when registerin

```python
def verify(ccu: Transaction, ccm: CCM) -> None:
if chainAccount(ccm.sendingChainID) does not exist:
raise Exception("Registration message must be sent from a registered chain.")

if ccm.sendingChainID != ccu.sendingChainID:
raise Exception("Registration message must be sent from a direct channel.")

if chainAccount(ccm.sendingChainID).status != CHAIN_REGISTERED:
raise Exception("Registration message must be sent from a chain with status 'registered'.")

if channel(ccm.sendingChainID).inbox.size != 0:
raise Exception("Registration message must be the first message in the inbox.")

Expand All @@ -520,6 +542,9 @@ def verify(ccu: Transaction, ccm: CCM) -> None:

if ownChainAccount.chainID != ccm.receivingChainID:
raise Exception("Registration message must be sent to the chain account ID of the chain.")

if ownChainAccount.chainID != ccm.params.chainID:
raise Exception("Registration message must contain the chain ID of the receiving chain.")

if ownChainAccount.name != ccm.params.name:
raise Exception("Registration message must contain the name of the registered chain.")
Expand All @@ -531,10 +556,6 @@ def verify(ccu: Transaction, ccm: CCM) -> None:
if ownChainAccount.chainID == CHAIN_ID_MAINCHAIN:
if ccm.nonce != 0:
raise Exception("Registration message must have nonce 0.")
# Processing on a sidechain.
else:
if ccm.sendingChainID != CHAIN_ID_MAINCHAIN:
raise Exception("Registration message must be sent from the mainchain.")
```

##### Execution
Expand Down Expand Up @@ -607,7 +628,13 @@ def verify(ccu: Transaction, ccm: CCM) -> None:

```python
def execute(ccu: Transaction, ccm: CCM) -> None:
if isLive(ccm.params.chainID):
if terminatedStateAccount(ccm.chainID) exists:
if terminatedStateAccount(ccm.chainID).initialized == True:
return
terminatedStateAccount(trs.params.chainID).stateRoot = ccm.params.stateRoot
terminatedStateAccount(trs.params.chainID).mainchainStateRoot = EMPTY_HASH
terminatedStateAccount(trs.params.chainID).initialized = True
else:
createTerminatedStateAccount(ccm.params.chainID, ccm.params.stateRoot)
```

Expand Down
Loading