/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
use darkfi_sdk::crypto::{PublicKey, CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
use darkfi_serial::serialize;
use log::info;
use crate::{
blockchain::BlockchainOverlayPtr, runtime::vm_runtime::Runtime, util::time::TimeKeeper, Result,
};
/// Deploy DarkFi native wasm contracts to provided blockchain overlay.
/// If overlay already contains the contracts, it will just open the
/// necessary db and trees, and give back what it has. This means that
/// on subsequent runs, our native contracts will already be in a deployed
/// state, so what we actually do here is a redeployment. This kind of
/// operation should only modify the contract's state in case it wasn't
/// deployed before (meaning the initial run). Otherwise, it shouldn't
/// touch anything, or just potentially update the db schemas or whatever
/// is necessary. This logic should be handled in the init function of
/// the actual contract, so make sure the native contracts handle this well.
pub fn deploy_native_contracts(
overlay: &BlockchainOverlayPtr,
time_keeper: &TimeKeeper,
faucet_pubkeys: &Vec,
) -> Result<()> {
info!(target: "validator::utils::deploy_native_contracts", "Deploying native WASM contracts");
// The faucet pubkeys are pubkeys which are allowed to create clear inputs
// in the Money contract.
let money_contract_deploy_payload = serialize(faucet_pubkeys);
// The DAO contract uses an empty payload to deploy itself.
let dao_contract_deploy_payload = vec![];
// The Consensus contract uses an empty payload to deploy itself.
let consensus_contract_deploy_payload = vec![];
let native_contracts = vec![
(
"Money Contract",
*MONEY_CONTRACT_ID,
include_bytes!("../contract/money/money_contract.wasm").to_vec(),
money_contract_deploy_payload,
),
(
"DAO Contract",
*DAO_CONTRACT_ID,
include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
dao_contract_deploy_payload,
),
(
"Consensus Contract",
*CONSENSUS_CONTRACT_ID,
include_bytes!("../contract/consensus/consensus_contract.wasm").to_vec(),
consensus_contract_deploy_payload,
),
];
for nc in native_contracts {
info!(target: "validator::utils::deploy_native_contracts", "Deploying {} with ContractID {}", nc.0, nc.1);
let mut runtime = Runtime::new(&nc.2[..], overlay.clone(), nc.1, time_keeper.clone())?;
runtime.deploy(&nc.3)?;
info!(target: "validator::utils::deploy_native_contracts", "Successfully deployed {}", nc.0);
}
info!(target: "validator::utils::deploy_native_contracts", "Finished deployment of native WASM contracts");
Ok(())
}