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

feat: add number input for finality window #711

Merged
merged 7 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,4 @@ HEURISTAIAPIKEY = '<add_your_heuristai_api_key_here>'
VALIDATORS_CONFIG_JSON = ''

# Consensus mechanism
FINALITY_WINDOW = 1800 # in seconds
VITE_FINALITY_WINDOW = 1800 # in seconds
9 changes: 6 additions & 3 deletions backend/consensus/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __init__(
self.get_session = get_session
self.msg_handler = msg_handler
self.queues: dict[str, asyncio.Queue] = {}
self.finality_window_time = int(os.getenv("VITE_FINALITY_WINDOW"))

def run_crawl_snapshot_loop(self):
loop = asyncio.new_event_loop()
Expand Down Expand Up @@ -570,8 +571,7 @@ def run_appeal_window_loop(self):
print(" ~ ~ ~ ~ ~ ENDING APPEAL WINDOW LOOP")

async def _appeal_window(self):
FINALITY_WINDOW = int(os.getenv("FINALITY_WINDOW"))
print(" ~ ~ ~ ~ ~ FINALITY WINDOW: ", FINALITY_WINDOW)
print(" ~ ~ ~ ~ ~ FINALITY WINDOW: ", self.finality_window_time)
while True:
try:
with self.get_session() as session:
Expand All @@ -583,7 +583,7 @@ async def _appeal_window(self):
if not transaction.appealed:
if (
int(time.time()) - transaction.timestamp_accepted
) > FINALITY_WINDOW:
) > self.finality_window_time:
self.finalize_transaction(
transaction,
transactions_processor,
Expand All @@ -608,6 +608,9 @@ async def _appeal_window(self):

await asyncio.sleep(1)

def set_finality_window_time(self, time: int):
self.finality_window_time = time


def rotate(nodes: list) -> Iterator[list]:
nodes = deque(nodes)
Expand Down
10 changes: 10 additions & 0 deletions backend/protocol_rpc/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
)
from backend.node.base import Node
from backend.node.types import ExecutionMode, ExecutionResultStatus
from backend.consensus.base import ConsensusAlgorithm

from flask import request
from flask_jsonrpc.exceptions import JSONRPCError
Expand Down Expand Up @@ -523,6 +524,10 @@ def set_transaction_appeal(
transactions_processor.set_transaction_appeal(transaction_hash, True)


def set_finality_window_time(consensus: ConsensusAlgorithm, time: int) -> None:
consensus.set_finality_window_time(time)


def register_all_rpc_endpoints(
jsonrpc: JSONRPC,
msg_handler: MessageHandler,
Expand All @@ -531,6 +536,7 @@ def register_all_rpc_endpoints(
transactions_processor: TransactionsProcessor,
validators_registry: ValidatorsRegistry,
llm_provider_registry: LLMProviderRegistry,
consensus: ConsensusAlgorithm,
):
register_rpc_endpoint = partial(generate_rpc_endpoint, jsonrpc, msg_handler)

Expand Down Expand Up @@ -645,3 +651,7 @@ def register_all_rpc_endpoints(
partial(set_transaction_appeal, transactions_processor),
method_name="sim_appealTransaction",
)
register_rpc_endpoint(
partial(set_finality_window_time, consensus),
method_name="sim_setFinalityWindowTime",
)
1 change: 1 addition & 0 deletions backend/protocol_rpc/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def create_app():
transactions_processor,
validators_registry,
llm_provider_registry,
consensus,
)


Expand Down
2 changes: 2 additions & 0 deletions frontend/src/hooks/useConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ export const useConfig = () => {
const isHostedEnvironment = import.meta.env.VITE_IS_HOSTED === 'true';
const canUpdateValidators = !isHostedEnvironment;
const canUpdateProviders = !isHostedEnvironment;
const canUpdateFinalityWindow = !isHostedEnvironment;

return {
canUpdateValidators,
canUpdateProviders,
canUpdateFinalityWindow,
};
};
1 change: 1 addition & 0 deletions frontend/src/services/IJsonRpcService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ export interface IJsonRpcService {
getTransactionByHash(hash: string): Promise<any>;
getTransactionCount(address: GetTransactionCountRequest): Promise<number>;
setTransactionAppeal(tx_address: string): Promise<any>;
setFinalityWindowTime(time: number): Promise<any>;
}
9 changes: 9 additions & 0 deletions frontend/src/services/JsonRpcService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,13 @@ export class JsonRpcService implements IJsonRpcService {
'Error setting transaction appeal flag',
);
}

async setFinalityWindowTime(time: number): Promise<any> {
console.log('Setting finality window time:', time, 'Type:', typeof time);
return this.callRpcMethod<any>(
'sim_setFinalityWindowTime',
[time],
'Error setting finality window duration',
);
}
}
6 changes: 6 additions & 0 deletions frontend/src/stores/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ export const useNodeStore = defineStore('nodeStore', () => {
],
);

async function setFinalityWindowTime(time: number) {
rpcClient.setFinalityWindowTime(time);
}

return {
logs,
validators,
Expand All @@ -232,5 +236,7 @@ export const useNodeStore = defineStore('nodeStore', () => {
availableModelsForProvider,
validatorsOrderedById,
hasAtLeastOneValidator,

setFinalityWindowTime,
};
});
43 changes: 41 additions & 2 deletions frontend/src/views/Simulator/RunDebugView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ import ConstructorParameters from '@/components/Simulator/ConstructorParameters.
import ContractReadMethods from '@/components/Simulator/ContractReadMethods.vue';
import ContractWriteMethods from '@/components/Simulator/ContractWriteMethods.vue';
import TransactionsList from '@/components/Simulator/TransactionsList.vue';
import { useContractQueries } from '@/hooks';
import { useContractQueries, useConfig } from '@/hooks';
import MainTitle from '@/components/Simulator/MainTitle.vue';
import { ref, watch } from 'vue';
import { ref, watch, computed } from 'vue';
import { useContractsStore, useNodeStore } from '@/stores';
import ContractInfo from '@/components/Simulator/ContractInfo.vue';
import BooleanField from '@/components/global/fields/BooleanField.vue';
import FieldError from '@/components/global/fields/FieldError.vue';
import NumberInput from '@/components/global/inputs/NumberInput.vue';
const contractsStore = useContractsStore();
const { isDeployed, address, contract } = useContractQueries();
const nodeStore = useNodeStore();
const leaderOnly = ref(false);

const isDeploymentOpen = ref(!isDeployed.value);
const finalityWindow = ref(Number(import.meta.env.VITE_FINALITY_WINDOW));
const { canUpdateFinalityWindow } = useConfig();

// Hide constructors by default when contract is already deployed
const setConstructorVisibility = () => {
Expand All @@ -25,6 +29,16 @@ watch(
[() => contract.value?.id, () => isDeployed.value, () => address.value],
setConstructorVisibility,
);

watch(finalityWindow, (newTime) => {
if (isFinalityWindowValid.value) {
nodeStore.setFinalityWindowTime(newTime);
}
});

const isFinalityWindowValid = computed(() => {
return Number.isInteger(finalityWindow.value) && finalityWindow.value >= 0;
});
</script>

<template>
Expand All @@ -40,6 +54,31 @@ watch(
label="Leader Only (Fast Execution)"
class="p-2"
/>

<div v-if="canUpdateFinalityWindow" class="p-2">
<div class="flex flex-wrap items-center gap-2">
<label for="finalityWindow" class="text-xs"
>Finality Window (seconds)</label
>
<NumberInput
id="finalityWindow"
name="finalityWindow"
:min="1"
:step="1"
:invalid="!isFinalityWindowValid"
v-model.number="finalityWindow"
required
testId="input-finalityWindow"
:disabled="false"
class="w-20"
/>
</div>

<FieldError v-if="!isFinalityWindowValid"
>Please enter a positive integer.</FieldError
>
</div>

<ContractInfo
:showNewDeploymentButton="!isDeploymentOpen"
@openDeployment="isDeploymentOpen = true"
Expand Down
Loading