Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

feat: Get balance. #28

Merged
merged 1 commit into from
Oct 24, 2019
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
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 44 additions & 13 deletions core/api/src/adapter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
use std::marker::PhantomData;
use std::sync::Arc;

use async_trait::async_trait;

use protocol::traits::executor::{ExecutorFactory, TrieDB};
use protocol::traits::{APIAdapter, Context, MemPool, Storage};
use protocol::types::{Address, Balance, Epoch, Hash, Receipt, SignedTransaction};
use protocol::types::{Address, AssetID, Balance, Epoch, Hash, Receipt, SignedTransaction};
use protocol::ProtocolResult;

pub struct DefaultAPIAdapter<M, S> {
pub struct DefaultAPIAdapter<EF, M, S, DB> {
mempool: Arc<M>,
storage: Arc<S>,
trie_db: Arc<DB>,

pin_ef: PhantomData<EF>,
}

impl<M: MemPool, S: Storage> DefaultAPIAdapter<M, S> {
pub fn new(mempool: Arc<M>, storage: Arc<S>) -> Self {
Self { mempool, storage }
impl<EF: ExecutorFactory<DB>, M: MemPool, S: Storage, DB: TrieDB> DefaultAPIAdapter<EF, M, S, DB> {
pub fn new(mempool: Arc<M>, storage: Arc<S>, trie_db: Arc<DB>) -> Self {
Self {
mempool,
storage,
trie_db,

pin_ef: PhantomData,
}
}
}

#[async_trait]
impl<M: MemPool, S: Storage> APIAdapter for DefaultAPIAdapter<M, S> {
impl<EF: ExecutorFactory<DB>, M: MemPool, S: Storage, DB: TrieDB> APIAdapter
for DefaultAPIAdapter<EF, M, S, DB>
{
async fn insert_signed_txs(
&self,
ctx: Context,
Expand All @@ -27,12 +40,13 @@ impl<M: MemPool, S: Storage> APIAdapter for DefaultAPIAdapter<M, S> {
self.mempool.insert(ctx, signed_tx).await
}

async fn get_latest_epoch(&self, _ctx: Context) -> ProtocolResult<Epoch> {
self.storage.get_latest_epoch().await
}
async fn get_epoch_by_id(&self, _ctx: Context, epoch_id: Option<u64>) -> ProtocolResult<Epoch> {
let epoch = match epoch_id {
Some(id) => self.storage.get_epoch_by_epoch_id(id).await?,
None => self.storage.get_latest_epoch().await?,
};

async fn get_epoch_by_id(&self, _ctx: Context, epoch_id: u64) -> ProtocolResult<Epoch> {
self.storage.get_epoch_by_epoch_id(epoch_id).await
Ok(epoch)
}

async fn get_receipt_by_tx_hash(
Expand All @@ -43,7 +57,24 @@ impl<M: MemPool, S: Storage> APIAdapter for DefaultAPIAdapter<M, S> {
self.storage.get_receipt(tx_hash).await
}

async fn get_balance(&self, _ctx: Context, _address: &Address) -> ProtocolResult<Balance> {
Ok(Balance::from(0u64))
async fn get_balance(
&self,
ctx: Context,
address: &Address,
id: &AssetID,
epoch_id: Option<u64>,
) -> ProtocolResult<Balance> {
let epoch: Epoch = self.get_epoch_by_id(ctx.clone(), epoch_id).await?;

let executor = EF::from_root(
epoch.header.chain_id,
epoch.header.state_root.clone(),
Arc::clone(&self.trie_db),
epoch.header.epoch_id,
0,
Address::User(epoch.header.proposer.clone()),
)?;

executor.get_balance(address, id)
}
}
43 changes: 38 additions & 5 deletions core/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use protocol::traits::{APIAdapter, Context};

use crate::config::GraphQLConfig;
use crate::schema::{
Bytes, ContractType, Epoch, Hash, InputDeployAction, InputRawTransaction,
InputTransactionEncryption, InputTransferAction,
Address, AssetID, Balance, Bytes, ContractType, Epoch, Hash, InputDeployAction,
InputRawTransaction, InputTransactionEncryption, InputTransferAction, Uint64,
};

pub async fn start_graphql<Adapter: APIAdapter + 'static>(cfg: GraphQLConfig, adapter: Adapter) {
Expand Down Expand Up @@ -51,12 +51,35 @@ struct Query;
// Switch to async/await fn https://github.com/graphql-rust/juniper/issues/2
#[juniper::object(Context = State)]
impl Query {
#[graphql(name = "getLatestEpoch", description = "get latest epoch")]
fn get_latest_epoch(state_ctx: &State) -> FieldResult<Epoch> {
let epoch = block_on(state_ctx.adapter.get_latest_epoch(Context::new()))
#[graphql(name = "getLatestEpoch", description = "get epoch")]
fn get_latest_epoch(state_ctx: &State, epoch_id: Option<Uint64>) -> FieldResult<Epoch> {
let epoch_id = opt_hex_to_u64(epoch_id.map(|id| id.as_hex()))?;

let epoch = block_on(state_ctx.adapter.get_epoch_by_id(Context::new(), epoch_id))
.map_err(FieldError::from)?;
Ok(Epoch::from(epoch))
}

#[graphql(name = "getBalance", description = "get balance")]
fn get_balance(
state_ctx: &State,
address: Address,
id: AssetID,
epoch_id: Option<Uint64>,
) -> FieldResult<Balance> {
let epoch_id = opt_hex_to_u64(epoch_id.map(|id| id.as_hex()))?;
let address = protocol::types::Address::from_hex(&address.as_hex())?;
let id = protocol::types::AssetID::from_hex(&id.as_hex())?;

let balance = block_on(state_ctx.adapter.get_balance(
Context::new(),
&address,
&id,
epoch_id,
))
.map_err(FieldError::from)?;
Ok(Balance::from(balance))
}
}

struct Mutation;
Expand Down Expand Up @@ -204,6 +227,16 @@ fn hex_to_u64(s: &str) -> FieldResult<u64> {
Ok(n)
}

fn opt_hex_to_u64(s: Option<String>) -> FieldResult<Option<u64>> {
match s {
Some(s) => match hex_to_u64(&s) {
Ok(num) => Ok(Some(num)),
Err(e) => Err(e),
},
None => Ok(None),
}
}

fn gen_input_tx_encryption(
input_privkey: Bytes,
tx_hash: Hash,
Expand Down
2 changes: 1 addition & 1 deletion core/consensus/src/fixed_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Codec for FixedSignedTxs {
}
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FixedPill {
pub inner: Pill,
}
Expand Down
16 changes: 6 additions & 10 deletions core/executor/src/cycles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::error::Error;
use derive_more::{Display, From};
use lazy_static::lazy_static;

use protocol::types::Fee;
use protocol::{ProtocolError, ProtocolErrorKind, ProtocolResult};

const NATIVE_BASE_CYCLES: u64 = 10;
Expand All @@ -26,22 +25,19 @@ pub enum CyclesAction {

pub fn consume_cycles(
action: CyclesAction,
cycles_price: u64,
fee: &mut Fee,
limit: &Fee,
) -> ProtocolResult<()> {
let cycles_used = fee.cycle
cycles_used: u64,
cycles_limit: u64,
) -> ProtocolResult<u64> {
let cycles_used = cycles_used
+ CYCLES_TABLE
.get(&action)
.unwrap_or_else(|| panic!("cycles action {:?} uninitialized", action));
let cycles_used = cycles_used * cycles_price;

if cycles_used > limit.cycle {
if cycles_used > cycles_limit {
return Err(CyclesError::OutOfCycles.into());
}

fee.cycle = cycles_used;
Ok(())
Ok(cycles_used)
}

#[derive(Debug, Display, From)]
Expand Down
58 changes: 31 additions & 27 deletions core/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use protocol::traits::executor::{
Executor, ExecutorExecResp, ExecutorFactory, InvokeContext, RcInvokeContext, TrieDB,
};
use protocol::types::{
Address, Balance, Bloom, ContractAddress, ContractType, Fee, Genesis, Hash, MerkleRoot,
Receipt, ReceiptResult, SignedTransaction, TransactionAction, UserAddress,
Address, AssetID, Balance, Bloom, ContractAddress, ContractType, Fee, Genesis, Hash,
MerkleRoot, Receipt, ReceiptResult, SignedTransaction, TransactionAction, UserAddress,
};
use protocol::{ProtocolError, ProtocolErrorKind, ProtocolResult};

Expand Down Expand Up @@ -53,14 +53,9 @@ impl<DB: TrieDB> Executor for TransactionExecutor<DB> {
epoch_id: 0,
coinbase: self.coinbase.clone(),
caller: self.coinbase.clone(),
cycles_used: Fee {
asset_id: Hash::from_empty(),
cycle: 0,
},
cycles_limit: Fee {
asset_id: Hash::from_empty(),
cycle: 999_999_999_999,
},
cycles_used: 0,
cycles_limit: 999_999_999_999,
fee_asset_id: Hash::from_empty(),
carrying_asset: None,
};
let ictx = Rc::new(RefCell::new(ictx));
Expand Down Expand Up @@ -134,7 +129,10 @@ impl<DB: TrieDB> Executor for TransactionExecutor<DB> {
let receipt = Receipt {
state_root: Hash::from_empty(),
epoch_id: ictx.borrow().epoch_id,
cycles_used: ictx.borrow().cycles_used.clone(),
cycles_used: Fee {
asset_id: ictx.borrow().fee_asset_id.clone(),
cycle: ictx.borrow().cycles_used * self.cycles_price,
},
result: res,
tx_hash,
};
Expand Down Expand Up @@ -167,6 +165,10 @@ impl<DB: TrieDB> Executor for TransactionExecutor<DB> {
state_root: state_root.clone(),
})
}

fn get_balance(&self, address: &Address, id: &AssetID) -> ProtocolResult<Balance> {
self.account_contract.get_balance(id, address)
}
}

impl<DB: TrieDB> TransactionExecutor<DB> {
Expand Down Expand Up @@ -197,9 +199,10 @@ impl<DB: TrieDB> TransactionExecutor<DB> {
ictx: RcInvokeContext,
to: &Address,
) -> ProtocolResult<ReceiptResult> {
let from = &ictx.borrow().caller;
let carrying_asset = ictx
.borrow()
let cloned_ictx = { ictx.borrow().clone() };

let from = &cloned_ictx.caller;
let carrying_asset = cloned_ictx
.carrying_asset
.clone()
.expect("in transfer, `carrying_asset` cannot be empty");
Expand Down Expand Up @@ -375,24 +378,25 @@ fn gen_invoke_ctx(
coinbase: &Address,
signed_tx: &SignedTransaction,
) -> ProtocolResult<RcInvokeContext> {
let carrying_asset = match &signed_tx.raw.action {
TransactionAction::Transfer { carrying_asset, .. } => Some(carrying_asset.clone()),
TransactionAction::Call { carrying_asset, .. } => carrying_asset.clone(),
_ => None,
};

let ctx = InvokeContext {
let mut ctx = InvokeContext {
chain_id: chain_id.clone(),
cycles_used: Fee {
asset_id: signed_tx.raw.fee.asset_id.clone(),
cycle: 0,
},
cycles_limit: signed_tx.raw.fee.clone(),
cycles_used: 0,
cycles_limit: signed_tx.raw.fee.cycle,
fee_asset_id: signed_tx.raw.fee.asset_id.clone(),
caller: Address::User(UserAddress::from_pubkey_bytes(signed_tx.pubkey.clone())?),
coinbase: coinbase.clone(),
epoch_id,
cycles_price,
carrying_asset,
carrying_asset: None,
};
match &signed_tx.raw.action {
TransactionAction::Transfer { carrying_asset, .. } => {
ctx.carrying_asset = Some(carrying_asset.clone());
}
TransactionAction::Call { carrying_asset, .. } => {
ctx.carrying_asset = carrying_asset.clone();
}
_ => {}
};
Ok(Rc::new(RefCell::new(ctx)))
}
Expand Down
13 changes: 7 additions & 6 deletions core/executor/src/native_contract/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ impl<StateAdapter: ContractStateAdapter> AccountContract<StateAdapter>
for NativeAccountContract<StateAdapter>
{
fn transfer(&mut self, ictx: RcInvokeContext, to: &Address) -> ProtocolResult<()> {
let cloned_ictx = { ictx.borrow().clone() };

let carrying_asset = ictx
.borrow()
.carrying_asset
Expand All @@ -42,14 +44,13 @@ impl<StateAdapter: ContractStateAdapter> AccountContract<StateAdapter>
)?;
self.add_balance(&carrying_asset.asset_id, to, carrying_asset.amount.clone())?;

let mut fee = ictx.borrow().cycles_used.clone();
consume_cycles(
let cycles_used = consume_cycles(
CyclesAction::AccountTransfer,
ictx.borrow().cycles_price,
&mut fee,
&ictx.borrow().cycles_limit,
cloned_ictx.cycles_used,
cloned_ictx.cycles_limit,
)?;
ictx.borrow_mut().cycles_used = fee;

ictx.borrow_mut().cycles_used = cycles_used;
Ok(())
}

Expand Down
10 changes: 4 additions & 6 deletions core/executor/src/native_contract/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,12 @@ impl<StateAdapter: ContractStateAdapter> BankContract<StateAdapter>
FixedAsset::new(asset.clone()),
)?;

let mut fee = ictx.borrow().cycles_used.clone();
consume_cycles(
let cycles_used = consume_cycles(
CyclesAction::BankRegister,
ictx.borrow().cycles_price,
&mut fee,
&ictx.borrow().cycles_limit,
ictx.borrow().cycles_used,
ictx.borrow().cycles_limit,
)?;
ictx.borrow_mut().cycles_used = fee;
ictx.borrow_mut().cycles_used = cycles_used;
Ok(asset)
}

Expand Down
Loading