-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #89 from paseo-network/feat/runtime_patch
feat: runtime patching scripts
- Loading branch information
Showing
6 changed files
with
480 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,4 +38,5 @@ runtime/wasm/target/ | |
substrate.code-workspace | ||
target/ | ||
**/tmp_runtime | ||
**/tmp_hub | ||
**/tmp_hub | ||
*.log |
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,77 @@ | ||
# Runtime Patch Scripts | ||
|
||
This directory contains scripts for managing runtime patches: | ||
|
||
1. `create_runtime_patch.sh`: Creates patch files with the new code from the Polkadot repo. | ||
2. `apply_runtime_patch.py`: Applies patches while preserving specific content. | ||
3. `revert_unwanted_changes.py`: Reverts specific changes in files. | ||
|
||
## Creating the runtime patch files | ||
|
||
Creates patch files for Paseo-specific modifications based on the differences between Polkadot runtime versions. | ||
|
||
Usage: | ||
|
||
```bash | ||
./scripts/create_runtime_patch.sh <current_version> <new_version> [process_parachains] | ||
``` | ||
|
||
Parameters: | ||
|
||
- `current_version`: The current Paseo runtime version | ||
- `new_version`: The new Polkadot runtime version to update to | ||
- `process_parachains`: Optional. Set to 'true' to process parachains. Defaults to 'false'. | ||
|
||
Example: | ||
|
||
```bash | ||
# Without processing parachains | ||
./scripts/create_runtime_patch.sh 1.2.3 1.2.4 | ||
|
||
# With processing parachains | ||
./scripts/create_runtime_patch.sh 1.2.3 1.2.4 true | ||
``` | ||
|
||
This script will create the following patch files in the `patches` directory: | ||
|
||
- `relay_polkadot.patch`: Contains changes for the relay chain and Cargo.toml | ||
- `parachain_<name>.patch`: Created for each specified parachain if `process_parachains` is set to true | ||
- `system_parachains_common.patch`: Contains changes for the `system-parachains/constants` directory and `system-parachains/Cargo.toml` file | ||
|
||
## Apply the patch | ||
|
||
Usage: | ||
|
||
```bash | ||
python apply_runtime_patch.py [--check] <patch_file> | ||
|
||
The --check option performs a dry run of the patch application process | ||
``` | ||
|
||
Examples: | ||
|
||
```bash | ||
# Apply a patch | ||
python apply_runtime_patch.py ../patches/relay_polkadot.patch | ||
|
||
# Check if a patch can be applied | ||
python apply_runtime_patch.py --check ../patches/relay_polkadot.patch | ||
``` | ||
|
||
## Revert unwanted changes | ||
|
||
Reverts specific changes in files based on predefined rules. | ||
|
||
Usage: | ||
|
||
```bash | ||
python revert_unwanted_changes.py <config.json> | ||
``` | ||
|
||
Example: | ||
|
||
```bash | ||
python revert_unwanted_changes.py replacement_config.json | ||
``` | ||
|
||
Both `apply_runtime_patch.py` and `revert_unwanted_changes.py` scripts log their actions to `apply_patch.log` and `revert_unwanted_changes.log` respectively in the current directory. |
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,131 @@ | ||
import sys | ||
import os | ||
import subprocess | ||
import tempfile | ||
import re | ||
from unidiff import PatchSet | ||
|
||
# Global variable for the log file name | ||
LOG_FILE = "apply_patch.log" | ||
|
||
def keep_sudo_filter(file_path, hunk): | ||
""" | ||
Filter to keep files and lines related to sudo. | ||
- Ignores deletion of files with 'sudo' in their name. | ||
- Prevents deletion of lines containing 'sudo'. | ||
""" | ||
if hunk.source_start == 0 and hunk.source_length == 0 and 'sudo' in file_path.lower(): | ||
log(f" Keeping file {file_path}: Contains 'sudo' in filename") | ||
return False | ||
|
||
for line in hunk: | ||
if line.is_removed and 'sudo' in line.value.lower(): | ||
log(f" Keeping line in {file_path}: Contains 'sudo'") | ||
return False | ||
|
||
return True | ||
|
||
def log(message): | ||
"""Log a message to both console and the log file.""" | ||
print(message) | ||
with open(LOG_FILE, "a") as log_file: | ||
log_file.write(message + "\n") | ||
|
||
def filter_hunk(file_path, hunk): | ||
"""Main filter function that applies all individual filters.""" | ||
filters = [ | ||
keep_sudo_filter | ||
] | ||
|
||
for filter_func in filters: | ||
if not filter_func(file_path, hunk): | ||
return False | ||
return True | ||
|
||
def apply_hunk_with_git(file_path, hunk_content): | ||
"""Apply a single hunk using git apply.""" | ||
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.patch') as temp_file: | ||
# Format the hunk content as a proper patch file | ||
patch_content = f"diff --git a/{file_path} b/{file_path}\n" | ||
patch_content += "--- a/{}\n+++ b/{}\n".format(file_path, file_path) | ||
patch_content += hunk_content | ||
temp_file.write(patch_content) | ||
temp_file_path = temp_file.name | ||
|
||
try: | ||
result = subprocess.run(['git', 'apply', '--3way', temp_file_path], | ||
capture_output=True, text=True, check=True) | ||
log(f"Successfully applied hunk to {file_path}") | ||
return True | ||
except subprocess.CalledProcessError as e: | ||
log(f"Failed to apply hunk to {file_path}: {e.stderr}") | ||
return False | ||
finally: | ||
os.unlink(temp_file_path) | ||
|
||
def apply_patch_line_by_line(patch_file, check_only=False, hunk_filter=filter_hunk): | ||
try: | ||
with open(patch_file, 'r') as pf: | ||
patch = PatchSet(pf) | ||
|
||
modified_files = set() | ||
|
||
for patched_file in patch: | ||
file_path = patched_file.path | ||
for hunk in patched_file: | ||
if not hunk_filter(file_path, hunk): | ||
log(f"Skipping hunk in {file_path} due to filter") | ||
continue | ||
|
||
hunk_content = str(hunk) | ||
if not check_only: | ||
success = apply_hunk_with_git(file_path, hunk_content) | ||
if not success: | ||
log(f"Failed to apply hunk to {file_path}") | ||
return False | ||
modified_files.add(file_path) | ||
else: | ||
log(f"Hunk for {file_path} can be applied") | ||
|
||
if not check_only: | ||
# Reset all modified files | ||
for file_path in modified_files: | ||
try: | ||
reset_result = subprocess.run(['git', 'reset', file_path], | ||
capture_output=True, text=True, check=True) | ||
log(f"Reset {file_path} to unstage changes") | ||
except subprocess.CalledProcessError as e: | ||
log(f"Failed to reset {file_path}: {e.stderr}") | ||
return False | ||
|
||
log("Patch applied successfully!") | ||
else: | ||
log("Patch can be applied successfully.") | ||
return True | ||
except Exception as e: | ||
log(f"Failed to apply patch: {e}") | ||
return False | ||
|
||
def main(): | ||
if len(sys.argv) < 2 or len(sys.argv) > 3: | ||
log("Usage: python apply_runtime_patch.py [--check] <patch_file>") | ||
sys.exit(1) | ||
|
||
check_flag = False | ||
if len(sys.argv) == 3: | ||
if sys.argv[1] != "--check": | ||
log("Invalid argument. Use --check for check mode.") | ||
sys.exit(1) | ||
check_flag = True | ||
patch_file = sys.argv[2] | ||
else: | ||
patch_file = sys.argv[1] | ||
|
||
# Clear the log file before starting | ||
open(LOG_FILE, "w").close() | ||
|
||
success = apply_patch_line_by_line(patch_file, check_flag, hunk_filter=filter_hunk) | ||
sys.exit(0 if success else 1) | ||
|
||
if __name__ == "__main__": | ||
main() |
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,137 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
# Define colors | ||
RED=$(tput setaf 1) | ||
WHITE=$(tput setaf 7) | ||
BLUE=$(tput setaf 4) | ||
RESET=$(tput sgr0) | ||
|
||
# Function to print messages with colors | ||
print_message() { | ||
local message=$1 | ||
local color=$2 | ||
echo "${color}${message}${RESET}" | ||
} | ||
|
||
# Check if the correct number of arguments is provided | ||
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then | ||
echo "Usage: $0 <current_paseo_runtime_version> <new_polkadot_runtime_version> [process_parachains]" | ||
echo "process_parachains: Optional. Set to 'true' to process parachains. Defaults to 'false'." | ||
exit 1 | ||
fi | ||
|
||
# Define list of parachains to copy | ||
# Format: "parachain_name origin_dir dest_dir" | ||
# parachain_name: name of the parachain | ||
# origin_dir: relative path in polkadot_runtime_next/system-parachains/ | ||
# dest_dir: relative path in paseo_runtime/system-parachains/ | ||
PARACHAINS=( | ||
"asset_hub asset-hubs/asset-hub-polkadot asset-hub-paseo" | ||
) | ||
|
||
|
||
CURRENT_TAG=$1 | ||
NEXT_TAG=$2 | ||
PROCESS_PARACHAINS=${3:-false} | ||
POLKADOT_CURRENT_TAG=v${CURRENT_TAG} | ||
POLKADOT_NEXT_TAG=v${NEXT_TAG} | ||
|
||
|
||
print_message "========================================" "${GREEN}" | ||
print_message "Creating patches from tag ${POLKADOT_CURRENT_TAG} to ${POLKADOT_NEXT_TAG}" "${GREEN}" | ||
print_message "Parachains processing: ${PROCESS_PARACHAINS}" "${GREEN}" | ||
print_message "========================================" "${GREEN}" | ||
|
||
rm -rf tmp_runtime | ||
mkdir tmp_runtime | ||
cd tmp_runtime | ||
|
||
print_message "----- Cloning repositories -----" "${BLUE}" | ||
git clone --depth 1 https://github.com/paseo-network/runtimes.git paseo_runtime | ||
git clone --depth 1 --branch ${POLKADOT_CURRENT_TAG} https://github.com/polkadot-fellows/runtimes.git polkadot_runtime_current | ||
git clone --depth 1 --branch ${POLKADOT_NEXT_TAG} https://github.com/polkadot-fellows/runtimes.git polkadot_runtime_next | ||
|
||
print_message "----- Copying current Polkadot runtime to Paseo -----" "${BLUE}" | ||
cp -fr polkadot_runtime_current/relay/polkadot/* paseo_runtime/relay/paseo/. | ||
|
||
print_message "----- Creating temporary branch in Paseo repo -----" "${BLUE}" | ||
cd paseo_runtime | ||
git switch -c tmp/${CURRENT_TAG}-runtime | ||
git add . | ||
git commit -m "Revert to Polkadot ${CURRENT_TAG} runtime" | ||
|
||
print_message "----- Reverting changes to keep Paseo-specific modifications -----" "${RED}" | ||
git revert --no-edit HEAD | ||
LATEST_COMMIT=$(git rev-parse HEAD) | ||
|
||
print_message "----- Creating new branch for updated runtime -----" "${BLUE}" | ||
git switch main | ||
git switch -c release/${NEXT_TAG}-runtime | ||
|
||
print_message "----- Copying new Polkadot runtime to Paseo -----" "${BLUE}" | ||
rm -rf relay/paseo/* | ||
cp -rf ../polkadot_runtime_next/relay/polkadot/* relay/paseo/. | ||
cp -f ../polkadot_runtime_next/Cargo.toml ./ | ||
|
||
if [ "$PROCESS_PARACHAINS" = "true" ]; then | ||
print_message "----- Copying system-parachains files -----" "${BLUE}" | ||
cp ../polkadot_runtime_next/system-parachains/constants/Cargo.toml system-parachains/constants | ||
cp ../polkadot_runtime_next/system-parachains/constants/src/polkadot.rs system-parachains/constants/src/paseo.rs | ||
cp ../polkadot_runtime_next/system-parachains/constants/src/lib.rs system-parachains/constants/src/ | ||
|
||
print_message "Copied system-parachains files:" "${WHITE}" | ||
print_message "- Cargo.toml" "${WHITE}" | ||
print_message "- constants/src/paseo.rs (renamed from polkadot.rs)" "${WHITE}" | ||
print_message "- constants/src/lib.rs" "${WHITE}" | ||
|
||
|
||
print_message "----- Copying specified parachains -----" "${BLUE}" | ||
for parachain in "${PARACHAINS[@]}"; do | ||
read -r parachain_name source_dir dest_dir <<< "$parachain" | ||
source_dir="../polkadot_runtime_next/system-parachains/${source_dir}" | ||
dest_dir="system-parachains/${dest_dir}" | ||
if [ -d "$source_dir" ]; then | ||
mkdir -p "$dest_dir" | ||
cp -rf "$source_dir"/* "$dest_dir/" | ||
print_message "Copied ${parachain_name} from ${source_dir} to ${dest_dir}" "${WHITE}" | ||
else | ||
print_message "Warning: ${source_dir} not found for ${parachain_name}" "${RED}" | ||
fi | ||
done | ||
fi | ||
|
||
git add . | ||
git commit -m "Update to Polkadot ${NEXT_TAG} runtime" | ||
if [ "$PROCESS_PARACHAINS" = "true" ]; then | ||
git commit --amend -m "Update to Polkadot ${NEXT_TAG} runtime and copy specified parachains" | ||
fi | ||
|
||
print_message "----- Creating patch files for Paseo-specific modifications -----" "${WHITE}" | ||
mkdir -p ../../patches | ||
|
||
# Create patch for relay/paseo and Cargo.toml | ||
git diff ${LATEST_COMMIT} HEAD -- relay/paseo Cargo.toml > ../../patches/relay_polkadot.patch | ||
|
||
if [ "$PROCESS_PARACHAINS" = "true" ]; then | ||
# Create patches for each parachain | ||
for parachain in "${PARACHAINS[@]}"; do | ||
read -r parachain_name _ dest_dir <<< "$parachain" | ||
parachain_dir="system-parachains/${dest_dir}" | ||
if [ -d "$parachain_dir" ]; then | ||
git diff ${LATEST_COMMIT} HEAD -- "$parachain_dir" > "../../patches/parachain_${parachain_name}.patch" | ||
print_message "Created patch for ${parachain_name}" "${WHITE}" | ||
else | ||
print_message "Warning: ${dest_dir} not found for ${parachain_name}, skipping patch creation" "${RED}" | ||
fi | ||
done | ||
|
||
# Create patch for system-parachains/constants and system-parachains/Cargo.toml | ||
git diff ${LATEST_COMMIT} HEAD -- system-parachains/constants system-parachains/constants/Cargo.toml > "../../patches/system_parachains_common.patch" | ||
print_message "Created patch for system-parachains/constants" | ||
fi | ||
|
||
print_message "--------------------" "${BLUE}" | ||
print_message "----- Patch files created in patches/ directory -----" "${WHITE}" | ||
print_message "----- Apply these patch files to integrate Paseo-specific changes -----" "${WHITE}" | ||
print_message "--------------------" "${BLUE}" |
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,20 @@ | ||
{ | ||
"replacements": { | ||
"[\"Polkadot Fellowship\"]": "[\"Paseo Core Team\"]", | ||
"https://github.com/polkadot-fellows/runtimes.git": "https://github.com/paseo-network/runtimes.git", | ||
"polkadot_runtime_constants": "paseo_runtime_constants", | ||
"polkadot-runtime-constants": "paseo-runtime-constants", | ||
"runtime::polkadot": "runtime::paseo", | ||
"polkadot-runtime\"":"paseo-runtime\"", | ||
"spec_name: create_runtime_str!(\"polkadot\"),": "spec_name: create_runtime_str!(\"paseo\"),", | ||
"impl_name: create_runtime_str!(\"parity-polkadot\"),": "impl_name: create_runtime_str!(\"paseo-testnet\"),", | ||
"type LeaseOffset = LeaseOffset;": "type LeaseOffset = ();", | ||
"// Polkadot version identifier;": "// Portico version identifier;", | ||
"/// Runtime version (Polkadot).": "/// Runtime version (Paseo).", | ||
"//! XCM configuration for Polkadot.": "//! XCM configuration for Paseo.", | ||
"pub const EPOCH_DURATION_IN_SLOTS: BlockNumber = prod_or_fast!(4 * HOURS, 1 * MINUTES);":"pub const EPOCH_DURATION_IN_SLOTS: BlockNumber = prod_or_fast!(1 * HOURS, 1 * MINUTES);", | ||
"Polkadot": "Paseo", | ||
"polkadot": "paseo" | ||
}, | ||
"remove_block_pattern": "\\s*// Polkadot Genesis was on May 26, 2020\\..*?DOT_LEASE_OFFSET\\\"\\);" | ||
} |
Oops, something went wrong.