Skip to content

Commit

Permalink
add governance (ontio#107)
Browse files Browse the repository at this point in the history
* add governance

* add gov example

* add test

* replace String with str

* fix

fix
  • Loading branch information
lucas7788 authored Nov 11, 2021
1 parent 2e6dfda commit bb8d531
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"examples/notify-test",
"examples/call_native",
"examples/oracle",
"examples/gov",
"examples/bridge"
]

Expand Down
17 changes: 17 additions & 0 deletions examples/gov/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "gov"
version = "0.1.0"
authors = ["lucas7788 <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]
path = "src/lib.rs"

[dependencies]
ontio-std = {path="../../ontio-std", features=["bump-alloc"]}

[features]
mock = ["ontio-std/mock"]
67 changes: 67 additions & 0 deletions examples/gov/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#![no_std]
#![feature(proc_macro_hygiene)]
extern crate ontio_std as ostd;
use ostd::abi::{Sink, Source};
use ostd::contract::governance::un_authorize_for_peer;
use ostd::contract::{governance, ont};
use ostd::prelude::*;
use ostd::runtime;
use ostd::runtime::address;

fn authorize_for_peer_transfer_from(user: &Address, amt: U128, peer_pub_key: &str) -> bool {
let this = address();
ont::transfer(user, &this, amt);
governance::authorize_for_peer_transfer_from(&this, amt, peer_pub_key)
}

fn authorize_for_peer(user: &Address, amt: U128, peer_pub_key: &str) -> bool {
governance::authorize_for_peer(user, amt, peer_pub_key)
}

fn withdraw(user: &Address, amt: U128, peer_pub_key: &str) -> bool {
governance::withdraw(user, amt, peer_pub_key)
}

fn withdraw_ong(user: &Address) -> bool {
governance::withdraw_ong(user)
}

#[no_mangle]
pub fn invoke() {
let input = runtime::input();
let mut source = Source::new(&input);
let action = source.read().unwrap();
let mut sink = Sink::new(12);
match action {
"authorize_for_peer_transfer_from" => {
let (user, amt, peer_pub_key) = source.read().unwrap();
sink.write(authorize_for_peer_transfer_from(user, amt, peer_pub_key));
}
"authorize_for_peer" => {
let (user, amt, peer_pub_key) = source.read().unwrap();
sink.write(authorize_for_peer(user, amt, peer_pub_key))
}
"un_authorize_for_peer" => {
let (user, amt, peer_pub_key) = source.read().unwrap();
sink.write(un_authorize_for_peer(user, amt, peer_pub_key))
}
"withdraw" => {
let (user, amt, peer_pub_key) = source.read().unwrap();
sink.write(withdraw(user, amt, peer_pub_key));
}
"withdraw_ong" => {
let user = source.read().unwrap();
sink.write(withdraw_ong(user));
}
_ => panic!("unsupported action!"),
}
runtime::ret(sink.bytes())
}

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
1 change: 1 addition & 0 deletions ontio-std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ uint = {version = "0.8.5", default-features=false}

[dev-dependencies]
rand = "0.7.0"
etcommon-hexutil = { version = "0.2.4", default-features = false }

[features]
std = []
Expand Down
181 changes: 181 additions & 0 deletions ontio-std/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,186 @@
use crate::prelude::*;

pub mod governance {
use crate::abi::{Encoder, Sink, Source};
use crate::macros::base58;
use crate::prelude::*;
use crate::runtime::call_contract;
use crate::types::u128_to_neo_bytes;

const VERSION: u8 = 0;
pub const GOV_CONTRACT_ADDRESS: Address = base58!("AFmseVrdL9f9oyCzZefL9tG6UbviEH9ugK");

pub struct AuthorizeForPeerParam<'a> {
addr: &'a Address,
peer_pubkey_list: &'a [&'a str],
pos_list: &'a [u32],
}

impl<'a> AuthorizeForPeerParam<'a> {
pub fn new(addr: &'a Address, pos_list: &'a [u32], peer_pub_key: &'a [&str]) -> Self {
AuthorizeForPeerParam { addr, peer_pubkey_list: peer_pub_key, pos_list }
}
}

impl<'a> Encoder for AuthorizeForPeerParam<'a> {
fn encode(&self, sink: &mut Sink) {
sink.write_var_bytes(self.addr.as_bytes());
sink.write_native_varuint(self.peer_pubkey_list.len() as u64);
for &pk in self.peer_pubkey_list.iter() {
sink.write(pk);
}
sink.write_native_varuint(self.pos_list.len() as u64);
for pos in self.pos_list.iter() {
sink.write(u128_to_neo_bytes(U128::new(*pos as u128)));
}
}
}

pub fn authorize_for_peer(addr: &Address, amt: U128, peer_pub_key: &str) -> bool {
let mut sink = Sink::new(64);
let pos_list = vec![amt.raw() as u32];
let peer_pub_key = &[peer_pub_key];
let a = AuthorizeForPeerParam::new(addr, pos_list.as_slice(), peer_pub_key);
sink.write(a);

let mut sink_param = Sink::new(64);
sink_param.write(VERSION);
sink_param.write("authorizeForPeer");
sink_param.write(sink.bytes());

let output = call_contract(&GOV_CONTRACT_ADDRESS, sink_param.bytes());
let mut source = Source::new(output.as_slice());
source.read_bool().unwrap_or_default()
}

//Authorize for a node by depositing ONT in this governance contract, used by contracts
pub fn authorize_for_peer_transfer_from(addr: &Address, amt: U128, peer_pub_key: &str) -> bool {
let mut sink = Sink::new(64);
let pos_list = &[amt.raw() as u32];
let peer_pub_key = &[peer_pub_key];
let a = AuthorizeForPeerParam::new(addr, pos_list, peer_pub_key);
sink.write(a);
let mut sink_param = Sink::new(64);
sink_param.write(VERSION);
sink_param.write("authorizeForPeerTransferFrom");
sink_param.write(sink.bytes());

let output = call_contract(&GOV_CONTRACT_ADDRESS, sink_param.bytes());
let mut source = Source::new(output.as_slice());
source.read_bool().unwrap_or_default()
}

//UnAuthorize for a node by redeeming ONT from this governance contract
pub fn un_authorize_for_peer(addr: &Address, amt: U128, peer_pub_key: &str) -> bool {
let mut sink = Sink::new(64);
let pos_list = vec![amt.raw() as u32];
let peer_pub_key = &[peer_pub_key];
let a = AuthorizeForPeerParam::new(addr, pos_list.as_slice(), peer_pub_key);
sink.write(a);

let mut sink_param = Sink::new(64);
sink_param.write(VERSION);
sink_param.write("unAuthorizeForPeer");
sink_param.write(sink.bytes());

let output = call_contract(&GOV_CONTRACT_ADDRESS, sink_param.bytes());
let mut source = Source::new(output.as_slice());
source.read_bool().unwrap_or_default()
}

struct WithdrawParam<'a> {
addr: &'a Address,
peer_pubkey_list: &'a [&'a str],
withdraw_list: &'a [u32],
}
impl<'a> Encoder for WithdrawParam<'a> {
fn encode(&self, sink: &mut Sink) {
sink.write_var_bytes(self.addr.as_bytes());
sink.write_var_bytes(
u128_to_neo_bytes(U128::new(self.peer_pubkey_list.len() as u128)).as_slice(),
);
self.peer_pubkey_list.iter().for_each(|peer_pubkey| sink.write(peer_pubkey));
sink.write_var_bytes(
u128_to_neo_bytes(U128::new(self.withdraw_list.len() as u128)).as_slice(),
);
self.withdraw_list.iter().for_each(|withdraw| {
sink.write_var_bytes(u128_to_neo_bytes(U128::new(*withdraw as u128)).as_slice())
});
}
}

//Withdraw unfreezed ONT deposited in this governance contract.
pub fn withdraw(addr: &Address, amt: U128, peer_pub_key: &str) -> bool {
let mut sink = Sink::new(80);
sink.write(WithdrawParam {
addr,
peer_pubkey_list: &[peer_pub_key],
withdraw_list: &[amt.raw() as u32],
});
let mut sink_param = Sink::new(64);
sink_param.write(VERSION);
sink_param.write("withdraw");
sink_param.write(sink.bytes());

let output = call_contract(&GOV_CONTRACT_ADDRESS, sink_param.bytes());
let mut source = Source::new(output.as_slice());
source.read_bool().unwrap_or_default()
}

struct WithdrawOngParam<'a> {
addr: &'a Address,
}
impl<'a> Encoder for WithdrawOngParam<'a> {
fn encode(&self, sink: &mut Sink) {
sink.write_var_bytes(self.addr.as_bytes())
}
}

//Withdraw unbounded ONG according to deposit ONT in this governance contract
pub fn withdraw_ong(addr: &Address) -> bool {
let mut sink = Sink::new(64);
sink.write(WithdrawOngParam { addr });
let mut sink_param = Sink::new(64);
sink_param.write(VERSION);
sink_param.write("withdrawOng");
sink_param.write(sink.bytes());

let output = call_contract(&GOV_CONTRACT_ADDRESS, sink_param.bytes());
let mut source = Source::new(output.as_slice());
source.read_bool().unwrap_or_default()
}

#[test]
pub fn test_struct() {
let data = [
0x1b, 0x25, 0xfb, 0x79, 0xe6, 0x1d, 0x58, 0x60, 0x97, 0xef, 0xd9, 0xee, 0x89, 0xa5,
0xab, 0xbf, 0x22, 0x27, 0xa2, 0xba,
];
let ap = AuthorizeForPeerParam {
addr: &Address::new(data),
peer_pubkey_list: &[&"test".to_string()],
pos_list: &[128u32],
};
let mut sink = Sink::new(64);
sink.write(ap);
println!("AuthorizeForPeerParam:{}", hexutil::to_hex(sink.bytes()));

let wp = WithdrawParam {
addr: &Address::repeat_byte(2),
peer_pubkey_list: &["test"],
withdraw_list: &[128u32],
};
let mut sink = Sink::new(64);
sink.write(wp);
println!("WithdrawParam:{}", hexutil::to_hex(sink.bytes()));

let wp = WithdrawOngParam { addr: &Address::repeat_byte(2) };
let mut sink = Sink::new(64);
sink.write(wp);
println!("WithdrawOngParam:{}", hexutil::to_hex(sink.bytes()));
}
}

pub mod neo {
use crate::prelude::*;

Expand Down

0 comments on commit bb8d531

Please sign in to comment.