Skip to content

Commit

Permalink
Merge pull request #1 from Prom3th3us/memory-management
Browse files Browse the repository at this point in the history
Added register & unregister endpoints.
  • Loading branch information
ffakenz authored May 10, 2024
2 parents d53999e + c60e185 commit 75a95f7
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 30 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
- .github/workflows/provision-darwin.sh
- .github/workflows/provision-linux.sh
- .github/workflows/backend.yaml
- .ic-commit

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
23 changes: 18 additions & 5 deletions .github/workflows/provision-darwin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,34 @@ bash install-brew.sh
rm install-brew.sh

# Install Node.
version=${NODE_VERSION:=14.15.4}
version=${NODE_VERSION:=20.12.2}
curl --location --output node.pkg "https://nodejs.org/dist/v$version/node-v$version.pkg"
sudo installer -pkg node.pkg -store -target /
rm node.pkg

# Install DFINITY SDK.
curl --location --output install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/dfxvm-install-script/install.sh"
DFX_VERSION=${DFX_VERSION:=0.19.0} DFXVM_INIT_YES=true bash install-dfx.sh
curl --location --output install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/master/public/install-dfxvm.sh"
DFX_VERSION=${DFX_VERSION:=0.20.0} DFXVM_INIT_YES=true bash install-dfx.sh
rm install-dfx.sh
echo "$HOME/Library/Application Support/org.dfinity.dfx/bin" >> $GITHUB_PATH
source "$HOME/Library/Application Support/org.dfinity.dfx/env"
dfx cache install

# check the current ic-commit found in the main branch, check if it differs from the one in this PR branch
# if so, update the dfx cache with the latest ic artifacts
if [ -f "${GITHUB_WORKSPACE}/.ic-commit" ]; then
stable_sha=$(curl https://raw.githubusercontent.com/dfinity/examples/master/.ic-commit)
current_sha=$(sed <"$GITHUB_WORKSPACE/.ic-commit" 's/#.*$//' | sed '/^$/d')
arch="x86_64-darwin"
if [ "$current_sha" != "$stable_sha" ]; then
export current_sha
export arch
sh "$GITHUB_WORKSPACE/.github/workflows/update-dfx-cache.sh"
fi
fi

# Install ic-repl
version=0.1.2
version=0.7.0
curl --location --output ic-repl "https://github.com/chenyan2002/ic-repl/releases/download/$version/ic-repl-macos"
mv ./ic-repl /usr/local/bin/ic-repl
chmod a+x /usr/local/bin/ic-repl
Expand Down Expand Up @@ -54,4 +67,4 @@ mv "${HOME}/bin/wasmtime-v${wasmtime_version}-x86_64-macos/wasmtime" "${HOME}/bi
rm "wasmtime-v${wasmtime_version}-x86_64-macos.tar.xz"

# Exit temporary directory.
popd
popd
22 changes: 17 additions & 5 deletions .github/workflows/provision-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,33 @@ set -ex
pushd /tmp

# Install Node.
wget --output-document install-node.sh "https://deb.nodesource.com/setup_14.x"
wget --output-document install-node.sh "https://deb.nodesource.com/setup_20.x"
sudo bash install-node.sh
sudo apt-get install --yes nodejs
rm install-node.sh

# Install DFINITY SDK.
wget --output-document install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/dfxvm-install-script/install.sh"
DFX_VERSION=${DFX_VERSION:=0.19.0} DFXVM_INIT_YES=true bash install-dfx.sh
wget --output-document install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/master/public/install-dfxvm.sh"
DFX_VERSION=${DFX_VERSION:=0.20.0} DFXVM_INIT_YES=true bash install-dfx.sh
rm install-dfx.sh
echo "$HOME/.local/share/dfx/bin" >> $GITHUB_PATH
source "$HOME/.local/share/dfx/env"
dfx cache install
# check the current ic-commit found in the main branch, check if it differs from the one in this PR branch
# if so, update the dfx cache with the latest ic artifacts
if [ -f "${GITHUB_WORKSPACE}/.ic-commit" ]; then
stable_sha=$(curl https://raw.githubusercontent.com/dfinity/examples/master/.ic-commit)
current_sha=$(sed <"$GITHUB_WORKSPACE/.ic-commit" 's/#.*$//' | sed '/^$/d')
arch="x86_64-linux"
if [ "$current_sha" != "$stable_sha" ]; then
export current_sha
export arch
sh "$GITHUB_WORKSPACE/.github/workflows/update-dfx-cache.sh"
fi
fi

# Install ic-repl
version=0.1.2
version=0.7.0
curl --location --output ic-repl "https://github.com/chenyan2002/ic-repl/releases/download/$version/ic-repl-linux64"
mv ./ic-repl /usr/local/bin/ic-repl
chmod a+x /usr/local/bin/ic-repl
Expand Down Expand Up @@ -53,4 +65,4 @@ echo "$HOME/bin" >> $GITHUB_PATH
echo "$HOME/.cargo/bin" >> $GITHUB_PATH

# Exit temporary directory.
popd
popd
1 change: 1 addition & 0 deletions .ic_commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
63acf4f88b20ec0c6384f4e18f0f6f69fc5d9b9f
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ test-4: # install
cat $$TMP_FILE; \
rm -f $$TMP_FILE

.PHONY: test-a
.SILENT: test-a
test-a: # install
.PHONY: test
.SILENT: test
test: install
# Call the backend canister for healthcheck and capture the output
@echo "Calling healthcheck on backend canister..."
@TMP_FILE=$$(mktemp); \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ dfx start --background

# Deploys your canisters to the replica and generates your candid interface
dfx deploy
```
```
27 changes: 21 additions & 6 deletions backend/backend.did
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ type User = record {

type GithubToken = text;

type GithubIssueId = text;

type GithubPullRequestId = text;

type BountyAmount = nat32;

// Bounty Service

type Contributor = record {
Expand All @@ -88,22 +94,31 @@ type DepositReceipt = variant {
};

type AcceptErr = variant {
IssueNotFound : record { github_issue_id : text };
CantAcceptedTwice;
IssueNotFound : record { GithubIssueId };
};

type AcceptReceipt = opt AcceptErr;

type RegisterIssueErr = null;

type RegisterIssueReceipt = opt RegisterIssueErr;

type UnRegisterIssueErr = null;

type UnRegisterIssueReceipt = opt UnRegisterIssueErr;

service : (authority: principal) -> {

// GitHub Service
"get_issue": (GithubToken) -> (IssueReceipt);
"get_fixed_by": (GithubToken) -> (FixedByReceipt);
"get_is_merged": (GithubToken) -> (IsMergedReceipt);
"get_merged_details": (GithubToken) -> (MergeDetailsReceipt);

// Bounty Service
"healthcheck": () -> (text);
"accept": (Contributor, github_issue_id: text, github_pr_id: text) -> (AcceptReceipt);
"accept": (Contributor, GithubIssueId, GithubPullRequestId) -> (AcceptReceipt);
"deposit": () -> (DepositReceipt);
}


"register_issue": (Contributor, GithubIssueId, BountyAmount) -> (RegisterIssueReceipt);
"unregister_issue": (GithubIssueId) -> (UnRegisterIssueReceipt);
}
2 changes: 1 addition & 1 deletion backend/src/bounty/api/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ fn extract_regex<T: std::str::FromStr>(regex: &str, str: &str) -> Option<T> {
let error_message = format!("Error (regex): {}", err);
print!("{}", error_message);
None
},
}
Ok(re) => {
if let Some(captures) = re.captures(str) {
if let Some(number) = captures.get(1) {
Expand Down
112 changes: 112 additions & 0 deletions backend/src/bounty/api/register_issue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use std::collections::HashMap;

use super::state::IssueId;
use super::state::{Bounty, Contributor, Issue, BOUNTY_STATE};

use candid::Nat;

pub type RegisterIssueError = ();

pub type RegisterIssueReceipt = Option<RegisterIssueError>;

pub fn register_issue_impl(
contributor: Contributor,
github_issue_id: IssueId,
amount: Nat,
) -> RegisterIssueReceipt {
return BOUNTY_STATE.with(|state| {
if let Some(ref mut bounty_canister) = *state.borrow_mut() {
let issue_exists = bounty_canister.github_issues.contains_key(&github_issue_id);
if !issue_exists {
let github_issue = Issue {
id: github_issue_id.clone(),
maintainer: contributor,
bounty: Bounty {
amount: amount,
winner: None,
accepted_prs: HashMap::new(),
},
};
// TODO: Check contributor it's registered and github_issue_id exists on github
bounty_canister
.github_issues
.insert(github_issue_id.clone(), github_issue);
}
None
} else {
panic!("Bounty canister state not initialized")
}
});
}

#[cfg(test)]
mod test_register_issue {
use super::*;
use crate::bounty::api::init::init_impl;
use candid::{Nat, Principal};
use num_bigint::BigUint;

#[test]
fn test_register_issue() {
let authority = Principal::anonymous();

init_impl(authority);

let github_issue_id = "input-output-hk/hydra/issues/1370".to_string();

let contributor = Contributor {
address: Principal::anonymous(),
crypto_address: "0x1234".to_string(),
};

let bounty_amount: Nat = Nat(BigUint::from(100u32));

let r: Option<RegisterIssueError> =
register_issue_impl(contributor, github_issue_id.clone(), bounty_amount);

assert!(r.is_none());

BOUNTY_STATE.with(|state| {
let bounty_canister = state.borrow();
if let Some(ref bounty_canister) = *bounty_canister {
assert!(bounty_canister
.github_issues
.get(&github_issue_id)
.is_some());
} else {
panic!("Bounty canister state not initialized");
}
});
}
#[test]
fn test_cant_register_issue_twice() {
let authority = Principal::anonymous();

init_impl(authority);

let github_issue_id = "input-output-hk/hydra/issues/1370".to_string();

let contributor = Contributor {
address: Principal::anonymous(),
crypto_address: "0x1234".to_string(),
};

let bounty_amount: Nat = Nat(BigUint::from(100u32));

let r: Option<RegisterIssueError> = register_issue_impl(
contributor.clone(),
github_issue_id.clone(),
bounty_amount.clone(),
);

assert!(r.is_none());

let r2: Option<RegisterIssueError> = register_issue_impl(
contributor.clone(),
github_issue_id.clone(),
bounty_amount.clone(),
);

assert!(r2.is_none());
}
}
8 changes: 4 additions & 4 deletions backend/src/bounty/api/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use candid::{CandidType, Principal};
use candid::{CandidType, Nat, Principal};
use serde::{Deserialize, Serialize};

pub type IssueId = String;
Expand All @@ -20,7 +20,7 @@ pub struct PullRequest {

#[derive(Debug, Serialize, Deserialize, CandidType, Clone, Builder)]
pub struct Bounty {
pub amount: i32,
pub amount: Nat,
pub winner: Option<PullRequestId>,
pub accepted_prs: HashMap<PullRequestId, PullRequest>,
}
Expand All @@ -35,7 +35,7 @@ pub struct Issue {
#[derive(Debug, Serialize, Deserialize, CandidType)]
pub struct BountyState {
pub authority: Principal,
pub github_issues: HashMap<IssueId, Issue>,
pub github_issues: HashMap<IssueId, Issue>,
}
// Define thread-local storage for the bounty canister state
// WASM is single-threaded by nature. [RefCell] and [thread_local!] are used despite being not totally safe primitives.
Expand All @@ -44,7 +44,7 @@ pub struct BountyState {
// Here we use [thread_local!] because it is simpler.
thread_local! {
// Currently, a single canister smart contract is limited to 4 GB of storage due to WebAssembly limitations.
// To ensure that our canister does not exceed this limit, we restrict memory usage to at most 2 GB because
// To ensure that our canister does not exceed this limit, we restrict memory usage to at most 2 GB because
// up to 2x memory may be needed for data serialization during canister upgrades.
pub static BOUNTY_STATE: std::cell::RefCell<Option<BountyState>> = std::cell::RefCell::new(None);
}
Loading

0 comments on commit 75a95f7

Please sign in to comment.