wicc合约

CReceipt:  //收据信息
        receipt.from_uid    = CUserID(CNickID(from));
        receipt.to_uid      = CUserID(CNickID(to));
        receipt.coin_symbol = quantity.sym.code().to_string();
        receipt.coin_amount = quantity.amount;
		receipt.code = TRANSFER_ACTUAL_COINS; ///202,

tx.inline_transactions.push_back({contract_name.value, action.value, std::vector<permission>{{authorizer_name.value, wasmio_owner}}, action_data});


struct inline_transaction {
        uint64_t                 contract;
        uint64_t                 action;
        std::vector <permission> authorization;
        std::vector<char>        data;

        IMPLEMENT_SERIALIZE (
            READWRITE(VARINT(contract ));
            READWRITE(VARINT(action ));
            READWRITE(authorization);
            READWRITE(data);
            )
        WASM_REFLECT( inline_transaction, (contract)(action)(authorization)(data) )
    }

/提交WASM的api
Value submitwasmcontractcalltx( const Array &params, bool fHelp ) {
        wasm::name        contract_name = wasm::name(params[1].get_str());
        if(!get_native_contract_abi(contract_name.value, abi)){
          	**//非系统合约,获取合约信息**
            get_contract(database_account, database_contract, contract_name, contract, contract_store );
        
        }

            tx.nTxType      = WASM_CONTRACT_TX;
            tx.txUid        = authorizer.regid;
            tx.valid_height = chainActive.Height();
            tx.fee_symbol   = fee.symbol;
            tx.llFees       = fee.GetSawiAmount();

        	///一会执行这个交易
            tx.inline_transactions.push_back({contract_name.value, action.value, std::vector<permission>{{authorizer_name.value, wasmio_owner}}, action_data});

		/执行交易
           std::tuple<bool, string> ret = wallet->CommitTx((CBaseTx * ) & tx);
  		...
}

到内存池里进行check

CWallet::CommitTx(CBaseTx *pTx) {
    LOCK2(cs_main, cs_wallet);
    LogPrint(BCLog::INFO, "CommitTx() : %s\n", pTx->ToString(*pCdMan->pAccountCache));
    {
        //到内存池
        if (!::AcceptToMemoryPool(mempool, state, pTx, true)) {
		//到未确认交易
    bool flag           = CWalletDB(strWalletFile).WriteUnconfirmedTx(txid, un
    
    ::RelayTransaction(pTx, txid);
    return std::make_tuple(flag, message);
}
bool AcceptToMemoryPool(CTxMemPool &pool, CValidationState &state, CBaseTx *pBaseTx,
                        bool fLimitFree, bool fRejectInsaneFee) {
                        
             pool.AddUnchecked(hash, entry, state); ->CheckTxInMemPool()
                        	 
  }

bool CTxMemPool::CheckTxInMemPool(const uint256 &txid, const CTxMemPoolEntry &memPoolEntry, CValidationState &state,
                                  bool bExecute) {
    // is it within valid height
 .....
 emPoolEntry.GetTransaction()->ExecuteTx(context)
 
}
///WASM contract excecute 
bool CWasmContractTx::ExecuteTx(CTxExecuteContext &context) {
......
		///< 扣取发起者的手续费
sub_balance(payer, wasm::asset(llFees, wasm::symbol(SYMB::WICC, 8)), database.accountCache);
  
        for (auto& trx: inline_transactions) {
            trx_current_for_exception = &trx;
            trx_trace.traces.emplace_back();
            //执行交易
            execute_inline_transaction(trx_trace.traces.back(), trx, trx.contract, database, receipts, 0);
            trx_current_for_exception = nullptr;
        }
        ....
        //save trx receipts
        trace_to_receipts(trx_trace, receipts);
        CHAIN_ASSERT( database.txReceiptCache.SetTxReceipts(GetHash(), receipts),
                      wasm_chain::account_access_exception,
                      "set tx '%s' receipts failed",
                      GetHash().ToString())

        //set runstep for block fuel sum
        nRunStep = run_cost;

    return true;
}

CWasmContractTx::execute_inline_transaction(wasm::inline_transaction_trace& trace,
                                                 wasm::inline_transaction&       trx,
                                                 uint64_t                        receiver,
                                                 CCacheWrapper&                  database,
                                                 vector <CReceipt>&              receipts,
                                                 uint32_t                        recurse_depth) {

    wasm_context wasm_execute_context(*this, trx, database, receipts, mining, recurse_depth);

    wasm_execute_context._receiver = receiver;
    wasm_execute_context.execute(trace);

}

//执行trace
//这个通过执行后bank的系统合约来增加notiy,来触发用户合约的transfer的接口
void wasm_context::execute(inline_transaction_trace &trace) {

        initialize();
		///notified 
        notified.push_back(_receiver);
        execute_one(trace);  ///如果是合约, 会把合约加入notify

        for (uint32_t i = 1; i < notified.size(); ++i) {
            _receiver = notified[i];

            trace.inline_traces.emplace_back();
            execute_one(trace.inline_traces.back());
        }

        CHAIN_ASSERT( recurse_depth < wasm::max_inline_transaction_depth,
                      wasm_chain::transaction_exception,
                      "max inline transaction depth per transaction reached");


		//执行合约内部交易的请求

        for (auto &inline_trx : inline_transactions) {
            trace.inline_traces.emplace_back();
            control_trx.execute_inline_transaction(trace.inline_traces.back(), inline_trx,
                                                   inline_trx.contract, database, receipts,
                                                   recurse_depth + 1);
        }

    }
 void wasm_context::execute_one(inline_transaction_trace &trace) {

        //auto start = system_clock::now();
        control_trx.recipients_size ++;
        trace.trx      = trx;
        trace.receiver = _receiver;
        auto native    = find_native_handle(_receiver, trx.action);
        if (native) {
        	  //执行内部的transfer
             (*native)(*this);
         } else {
             vector <uint8_t> code = get_code(_receiver);
             if (code.size() > 0) {
                 wasmif.execute(code, this);
             }
         }
        if (contracts_console()) {
            print_debug(_receiver, trace);
        }
    }
//系统合约交易函数
void wasmio_bank_native_transfer(wasm_context &context) {


        transfer_data_type transfer_data = wasm::unpack<std::tuple<uint64_t, uint64_t, wasm::asset, string>>(context.trx.data);
        auto from                        = std::get<0>(transfer_data);
        auto to                          = std::get<1>(transfer_data);
        auto quantity                    = std::get<2>(transfer_data);
        auto memo                        = std::get<3>(transfer_data);
        ....
        sub_balance( from_account, quantity, database ); //修改WICC金额
      	....
        add_balance( to_account, quantity, database );

        context.require_recipient(from); ///添加notify继续执行  sender
        context.require_recipient(to); ///< 当前这个合约
    }

}
void wasm_interface::execute(const vector <uint8_t> &code, wasm_context_interface *pWasmContext) {

        pWasmContext->pause_billing_timer();
        auto pInstantiated_module = get_instantiated_backend(code);
        pWasmContext->resume_billing_timer();

        //system_clock::time_point start = system_clock::now();
        pInstantiated_module->apply(pWasmContext); ///调用到用户的合约

    }


///json RPC的执行请求
json_spirit::Value CRPCTable::execute(const string& strMethod,
                                      const json_spirit::Array& params) const {

  Value result;
        {
            if (pcmd->threadSafe)
                result = pcmd->actor(params, false);
            else if (!pWalletMain) {
                LOCK(cs_main);
                result = pcmd->actor(params, false);
            } else {
                LOCK2(cs_main, pWalletMain->cs_wallet);
                result = pcmd->actor(params, false);
            }
        }
}

static void inline_trace_to_receipts(const wasm::inline_transaction_trace& trace,
                                     vector<CReceipt>&                     receipts,
                                     map<transfer_data_type,  uint64_t>&   receipts_duplicate_check) {

    if (trace.trx.contract == wasmio_bank && trace.trx.action == wasm::N(transfer)) {

        CReceipt receipt;
        receipt.code = TRANSFER_ACTUAL_COINS;

        transfer_data_type transfer_data = wasm::unpack < std::tuple < uint64_t, uint64_t, wasm::asset, string>> (trace.trx.data);
        auto from                        = std::get<0>(transfer_data);
        auto to                          = std::get<1>(transfer_data);
        auto quantity                    = std::get<2>(transfer_data);
        auto memo                        = std::get<3>(transfer_data);

        auto itr = receipts_duplicate_check.find(std::tuple(from, to ,quantity, memo));
        if (itr == receipts_duplicate_check.end()){
            receipts_duplicate_check[std::tuple(from, to ,quantity, memo)] = wasmio_bank;

            receipt.from_uid    = CUserID(CNickID(from));
            receipt.to_uid      = CUserID(CNickID(to));
            receipt.coin_symbol = quantity.sym.code().to_string();
            receipt.coin_amount = quantity.amount;

            receipts.push_back(receipt);
        }
    }
	///这个inline_traces 哪里来的
    for (auto t: trace.inline_traces) {
        inline_trace_to_receipts(t, receipts, receipts_duplicate_check);
    }

}

虚拟机是如何响应外部执行需求的,这个主要体现在对外接
层面虚拟机接口对外暴露虚拟机实例创建和合约执行入口,具体声明在如下路径文件中
//这个是合约执行的关键, 回调用用户合约请求
void apply(wasm::wasm_context_interface *pContext) override {
   .......
		//这个就是调用用户合约定义的apply接口
            auto fn = [&]() {
                const auto &res = _runtime->_bkend->call(
                        pContext, "env", "apply", pContext->receiver(),
                        pContext->contract(),
                        pContext->action());
		
  }
//收据的生成,递归生成
static void inline_trace_to_receipts(const wasm::inline_transaction_trace& trace,
                                     vector<CReceipt>&                     receipts,
                                     map<transfer_data_type,  uint64_t>&   receipts_duplicate_check) {

    if (trace.trx.contract == wasmio_bank && trace.trx.action == wasm::N(transfer)) {

        CReceipt receipt;
        receipt.code = TRANSFER_ACTUAL_COINS;

        transfer_data_type transfer_data = wasm::unpack < std::tuple < uint64_t, uint64_t, wasm::asset, string>> (trace.trx.data);
        auto from                        = std::get<0>(transfer_data);
        auto to                          = std::get<1>(transfer_data);
        auto quantity                    = std::get<2>(transfer_data);
        auto memo                        = std::get<3>(transfer_data);

        auto itr = receipts_duplicate_check.find(std::tuple(from, to ,quantity, memo));
        if (itr == receipts_duplicate_check.end()){
            receipts_duplicate_check[std::tuple(from, to ,quantity, memo)] = wasmio_bank;

            receipt.from_uid    = CUserID(CNickID(from));
            receipt.to_uid      = CUserID(CNickID(to));
            receipt.coin_symbol = quantity.sym.code().to_string();
            receipt.coin_amount = quantity.amount;

            receipts.push_back(receipt);
        }
    }

    for (auto t: trace.inline_traces) {
        inline_trace_to_receipts(t, receipts, receipts_duplicate_check);
    }

}

合约的接口是如何让主要程序调用

提供了api 底层调用
extern "C" {
void apply(uint64_t receiver, uint64_t code, uint64_t action) {
 wasm::execute_action( wasm::name(receiver), wasm::name(code), &eidos::close ); 

bool execute_action( name self, name code, void (T::*func)(Args...)  ) {
      size_t size = action_data_size();

      //using malloc/free here potentially is not exception-safe, although WASM doesn't support exceptions
      constexpr size_t max_stack_buffer_size = 512;
      void* buffer = nullptr;
      if( size > 0 ) {
         buffer = max_stack_buffer_size < size ? malloc(size) : alloca(size);
         read_action_data( buffer, size );
      }

      std::tuple<std::decay_t<Args>...> args;
      datastream<const char*> ds((char*)buffer, size);
      ds >> args;

      T inst(self, code, ds);

      auto f2 = [&]( auto... a ){
         ((&inst)->*func)( a... );
      };

      boost::mp11::tuple_apply( f2, args );
      if ( max_stack_buffer_size < size ) {
         free(buffer);
      }
      return true;
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值