diff --git a/cosmwasm/enclaves/execute/Enclave.edl b/cosmwasm/enclaves/execute/Enclave.edl index 646e531b9..522733457 100644 --- a/cosmwasm/enclaves/execute/Enclave.edl +++ b/cosmwasm/enclaves/execute/Enclave.edl @@ -193,11 +193,8 @@ enclave { uintptr_t in_txs_len, [in, count=in_encrypted_random_len] const uint8_t* in_encrypted_random, uintptr_t in_encrypted_random_len, - [out, count=32] uint8_t* decrypted - // [in, count=in_validator_set_len] const uint8_t* in_validator_set, - // uintptr_t in_validator_set_len, - // [in, count=in_next_validator_set_len] const uint8_t* in_next_validator_set, -// uintptr_t in_next_validator_set_len + [out, count=32] uint8_t* decrypted, + [out, count=32] uint8_t* next_validator_set_evidence ); }; diff --git a/cosmwasm/enclaves/execute/src/ecalls.rs b/cosmwasm/enclaves/execute/src/ecalls.rs index 40db781d6..be2b33ec2 100644 --- a/cosmwasm/enclaves/execute/src/ecalls.rs +++ b/cosmwasm/enclaves/execute/src/ecalls.rs @@ -16,6 +16,7 @@ pub unsafe extern "C" fn ecall_submit_block_signatures( in_encrypted_random: *const u8, in_encrypted_random_len: u32, decrypted_random: &mut [u8; 32], + next_validator_set_evidence: &mut [u8; 32], ) -> sgx_status_t { #[cfg(feature = "light-client-validation")] { @@ -29,6 +30,7 @@ pub unsafe extern "C" fn ecall_submit_block_signatures( in_encrypted_random, in_encrypted_random_len, decrypted_random, + next_validator_set_evidence, ) } diff --git a/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs b/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs index 31f635409..67480c0d1 100644 --- a/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs +++ b/cosmwasm/enclaves/shared/block-verifier/src/submit_block_signatures.rs @@ -4,7 +4,7 @@ use tendermint_proto::Protobuf; use sgx_types::sgx_status_t; -use enclave_utils::{validate_const_ptr, validate_input_length, validate_mut_ptr, Keychain}; +use enclave_utils::{validate_const_ptr, validate_input_length, validate_mut_ptr, Keychain, KEY_MANAGER}; use log::error; use log::debug; @@ -43,6 +43,7 @@ pub unsafe fn submit_block_signatures_impl( in_encrypted_random: *const u8, in_encrypted_random_len: u32, decrypted_random: &mut [u8; 32], + next_validator_set_evidence: &mut [u8; 32], ) -> sgx_status_t { if let Err(e) = validate_inputs( in_header, @@ -127,6 +128,19 @@ pub unsafe fn submit_block_signatures_impl( decrypted_random.copy_from_slice(&decrypted); } + // store this in the storage: header.header.next_validators_hash + if let tendermint::Hash::Sha256(val) = header.header.next_validators_hash { + let validator_set_evidence = KEY_MANAGER.encrypt_hash(val); + + println!( + "next validator set evidence: {:?}", + hex::encode(validator_set_evidence) + ); + + next_validator_set_evidence.copy_from_slice(validator_set_evidence.as_slice()); + + } + debug!( "Done verifying block height: {:?}", header.header.height.value() diff --git a/cosmwasm/enclaves/shared/block-verifier/src/wasm_messages.rs b/cosmwasm/enclaves/shared/block-verifier/src/wasm_messages.rs index ecd59c08f..910f153cb 100644 --- a/cosmwasm/enclaves/shared/block-verifier/src/wasm_messages.rs +++ b/cosmwasm/enclaves/shared/block-verifier/src/wasm_messages.rs @@ -16,6 +16,7 @@ pub struct VerifiedBlockMessages { messages: VecDeque>, height: u64, time: i128, + pub next_validators_evidence: tendermint::Hash, } impl VerifiedBlockMessages { diff --git a/cosmwasm/packages/sgx-vm/src/random.rs b/cosmwasm/packages/sgx-vm/src/random.rs index 957619319..0d667eb15 100644 --- a/cosmwasm/packages/sgx-vm/src/random.rs +++ b/cosmwasm/packages/sgx-vm/src/random.rs @@ -17,10 +17,7 @@ extern "C" { in_encrypted_random: *const u8, in_encrypted_random_len: u32, decrypted_random: &mut [u8; 32], - // in_validator_set: *const u8, - // in_validator_set_len: u32, - // in_next_validator_set: *const u8, - // in_next_validator_set_len: u32, + next_validator_set_evidence: &mut [u8; 32], ) -> sgx_status_t; } @@ -29,7 +26,7 @@ pub fn untrusted_submit_block_signatures( commit: &[u8], txs: &[u8], encrypted_random: &[u8], -) -> SgxResult<[u8; 32]> { +) -> SgxResult<([u8; 32], [u8; 32])>{ debug!("Hello from just before - untrusted_submit_block_signatures"); const RETRY_LIMIT: i32 = 3; @@ -38,7 +35,7 @@ pub fn untrusted_submit_block_signatures( // this is here so we can loop { - let (retval, decrypted, status) = + let (retval, decrypted, next_validator_set_evidence, status) = submit_block_signature_impl(header, commit, txs, encrypted_random)?; if status != sgx_status_t::SGX_SUCCESS { return Err(status); @@ -59,7 +56,7 @@ pub fn untrusted_submit_block_signatures( return Err(retval); } } else { - return Ok(decrypted); + return Ok((decrypted, next_validator_set_evidence)); } } } @@ -69,7 +66,7 @@ fn submit_block_signature_impl( commit: &[u8], txs: &[u8], encrypted_random: &[u8], -) -> SgxResult<(sgx_status_t, [u8; 32], sgx_status_t)> { +) -> SgxResult<(sgx_status_t, [u8; 32], [u8; 32], sgx_status_t)>{ // Bind the token to a local variable to ensure its // destructor runs in the end of the function let enclave_access_token = ENCLAVE_DOORBELL @@ -84,6 +81,7 @@ fn submit_block_signature_impl( // unused if random feature is not turned on let mut random_decrypted = [0u8; 32]; + let mut next_validator_set_evidence = [0u8; 32]; // let status = unsafe { ecall_get_encrypted_seed(eid, &mut retval, cert, cert_len, & mut seed) }; let status = unsafe { @@ -98,9 +96,10 @@ fn submit_block_signature_impl( txs.len() as u32, encrypted_random.as_ptr(), encrypted_random.len() as u32, - &mut random_decrypted + &mut random_decrypted, + &mut next_validator_set_evidence ) }; - Ok((retval, random_decrypted, status)) + Ok((retval, random_decrypted, next_validator_set_evidence, status)) } diff --git a/go-cosmwasm/api/bindings.h b/go-cosmwasm/api/bindings.h index 5c6b498ea..e3740f029 100644 --- a/go-cosmwasm/api/bindings.h +++ b/go-cosmwasm/api/bindings.h @@ -143,6 +143,11 @@ typedef struct GoQuerier { Querier_vtable vtable; } GoQuerier; +typedef struct TwoBuffers { + Buffer buf1; + Buffer buf2; +} TwoBuffers; + Buffer allocate_rust(const uint8_t *ptr, uintptr_t length); AnalysisReport analyze_code(cache_t *cache, Buffer checksum, Buffer *error_msg); @@ -238,11 +243,11 @@ Buffer query(cache_t *cache, */ void release_cache(cache_t *cache); -Buffer submit_block_signatures(Buffer header, - Buffer commit, - Buffer txs, - Buffer random, - Buffer *err); +TwoBuffers submit_block_signatures(Buffer header, + Buffer commit, + Buffer txs, + Buffer random, + Buffer *err); Buffer update_admin(cache_t *cache, Buffer contract_id, diff --git a/go-cosmwasm/api/lib.go b/go-cosmwasm/api/lib.go index 64ca4d464..d7a2eadac 100644 --- a/go-cosmwasm/api/lib.go +++ b/go-cosmwasm/api/lib.go @@ -46,7 +46,7 @@ func HealthCheck() ([]byte, error) { return receiveVector(res), nil } -func SubmitBlockSignatures(header []byte, commit []byte, txs []byte, encRandom []byte /* valSet []byte, nextValSet []byte */) ([]byte, error) { +func SubmitBlockSignatures(header []byte, commit []byte, txs []byte, encRandom []byte /* valSet []byte, nextValSet []byte */) ([]byte, []byte, error) { errmsg := C.Buffer{} spidSlice := sendSlice(header) defer freeAfterSend(spidSlice) @@ -59,9 +59,9 @@ func SubmitBlockSignatures(header []byte, commit []byte, txs []byte, encRandom [ res, err := C.submit_block_signatures(spidSlice, apiKeySlice, txsSlice, encRandomSlice /* valSetSlice, nextValSetSlice,*/, &errmsg) if err != nil { - return nil, errorWithMessage(err, errmsg) + return nil, nil, errorWithMessage(err, errmsg) } - return receiveVector(res), nil + return receiveVector(res.buf1), receiveVector(res.buf2), nil } func InitBootstrap(spid []byte, apiKey []byte) ([]byte, error) { diff --git a/go-cosmwasm/api/lib_mock.go b/go-cosmwasm/api/lib_mock.go index 643ce14d3..23d56fee3 100644 --- a/go-cosmwasm/api/lib_mock.go +++ b/go-cosmwasm/api/lib_mock.go @@ -39,8 +39,8 @@ func InitBootstrap(spid []byte, apiKey []byte) ([]byte, error) { return nil, nil } -func SubmitBlockSignatures(header []byte, commit []byte, txs []byte, random []byte /* valSet []byte, nextValSet []byte*/) ([]byte, error) { - return nil, nil +func SubmitBlockSignatures(header []byte, commit []byte, txs []byte, random []byte /* valSet []byte, nextValSet []byte*/) ([]byte, []byte, error) { + return nil, nil, nil } func LoadSeedToEnclave(masterKey []byte, seed []byte, apiKey []byte) (bool, error) { diff --git a/go-cosmwasm/src/lib.rs b/go-cosmwasm/src/lib.rs index 87a5ebba3..6edda4584 100644 --- a/go-cosmwasm/src/lib.rs +++ b/go-cosmwasm/src/lib.rs @@ -26,6 +26,7 @@ use ed25519_dalek::{Keypair, Signature, Signer}; use hex; use log::*; use logger::get_log_level; +use memory::TwoBuffers; pub use memory::{free_rust, Buffer}; pub use querier::GoQuerier; use serde::Deserialize; @@ -259,13 +260,13 @@ pub extern "C" fn submit_block_signatures( // val_set: Buffer, // next_val_set: Buffer, err: Option<&mut Buffer>, -) -> Buffer { +) -> TwoBuffers { trace!("Hello from right before init_bootstrap"); let header_slice = match unsafe { header.read() } { None => { set_error(Error::empty_arg("header"), err); - return Buffer::default(); + return TwoBuffers::default(); } Some(r) => r, }; @@ -273,7 +274,7 @@ pub extern "C" fn submit_block_signatures( let commit_slice = match unsafe { commit.read() } { None => { set_error(Error::empty_arg("api_key"), err); - return Buffer::default(); + return TwoBuffers::default(); } Some(r) => r, }; @@ -281,7 +282,7 @@ pub extern "C" fn submit_block_signatures( let txs_slice = match unsafe { txs.read() } { None => { set_error(Error::empty_arg("txs"), err); - return Buffer::default(); + return TwoBuffers::default(); } Some(r) => r, }; @@ -289,14 +290,14 @@ pub extern "C" fn submit_block_signatures( let random_slice = match unsafe { random.read() } { None => { set_error(Error::empty_arg("random"), err); - return Buffer::default(); + return TwoBuffers::default(); } Some(r) => r, }; // let val_set_slice = match unsafe { val_set.read() } { // None => { // set_error(Error::empty_arg("api_key"), err); - // return Buffer::default(); + // return TwoBuffers::default(); // } // Some(r) => r, // }; @@ -304,7 +305,7 @@ pub extern "C" fn submit_block_signatures( // let next_val_set_slice = match unsafe { next_val_set.read() } { // None => { // set_error(Error::empty_arg("api_key"), err); - // return Buffer::default(); + // return TwoBuffers::default(); // } // Some(r) => r, // }; @@ -319,11 +320,14 @@ pub extern "C" fn submit_block_signatures( ) { Err(e) => { set_error(Error::enclave_err(e.to_string()), err); - Buffer::default() + return TwoBuffers::default(); } - Ok(r) => { + Ok((r1, r2)) => { clear_error(); - Buffer::from_vec(r.to_vec()) + TwoBuffers { + buf1: Buffer::from_vec(r1.to_vec()), + buf2: Buffer::from_vec(r2.to_vec()), + } } } } diff --git a/go-cosmwasm/src/memory.rs b/go-cosmwasm/src/memory.rs index 58095a0bd..225dd36e2 100644 --- a/go-cosmwasm/src/memory.rs +++ b/go-cosmwasm/src/memory.rs @@ -85,6 +85,22 @@ impl Default for Buffer { } } +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(C)] +pub struct TwoBuffers { + pub buf1: Buffer, + pub buf2: Buffer, +} + +impl Default for TwoBuffers { + fn default() -> Self { + TwoBuffers { + buf1: Buffer::default(), + buf2: Buffer::default(), + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/x/compute/internal/keeper/keeper.go b/x/compute/internal/keeper/keeper.go index d3d1b16b9..4e71befc0 100644 --- a/x/compute/internal/keeper/keeper.go +++ b/x/compute/internal/keeper/keeper.go @@ -924,7 +924,7 @@ func (k Keeper) GetRandomSeed(ctx sdk.Context, height int64) []byte { return random } -func (k Keeper) SetRandomSeed(ctx sdk.Context, random []byte) { +func (k Keeper) SetRandomSeed(ctx sdk.Context, random []byte, validator_set_evidence []byte) { store := k.storeService.OpenKVStore(ctx) ctx.Logger().Info(fmt.Sprintf("Setting random: %s", hex.EncodeToString(random))) @@ -933,6 +933,11 @@ func (k Keeper) SetRandomSeed(ctx sdk.Context, random []byte) { if err != nil { ctx.Logger().Error("SetRandomSeed:", err.Error()) } + + err = store.Set(types.ValidatorSetEvidencePrefix, validator_set_evidence) + if err != nil { + ctx.Logger().Error("SetRandomSeed:", err.Error()) + } } func (k Keeper) GetContractAddress(ctx sdk.Context, label string) sdk.AccAddress { diff --git a/x/compute/internal/keeper/test_common.go b/x/compute/internal/keeper/test_common.go index 8fe27f15e..b95def0c2 100644 --- a/x/compute/internal/keeper/test_common.go +++ b/x/compute/internal/keeper/test_common.go @@ -605,7 +605,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, enc random := make([]byte, 32) _, _ = rand.Read(random) - keeper.SetRandomSeed(ctx, random) + keeper.SetRandomSeed(ctx, random, random) govSubSp, _ := paramsKeeper.GetSubspace(govtypes.ModuleName) @@ -1108,7 +1108,7 @@ func updateLightClientHelper(t *testing.T, ctx sdk.Context) { randomAndProofBz := append(random, proof...) //nolint:all - _, err = api.SubmitBlockSignatures(headerBz, commitBz, dataBz, randomAndProofBz) + _, _, err = api.SubmitBlockSignatures(headerBz, commitBz, dataBz, randomAndProofBz) require.NoError(t, err) } diff --git a/x/compute/internal/types/keys.go b/x/compute/internal/types/keys.go index 2218c5a01..b8c792aa4 100644 --- a/x/compute/internal/types/keys.go +++ b/x/compute/internal/types/keys.go @@ -34,6 +34,7 @@ var ( ContractCodeHistoryElementPrefix = []byte{0x09} ContractByCodeIDAndCreatedSecondaryIndexPrefix = []byte{0x0A} RandomPrefix = []byte{0xFF} + ValidatorSetEvidencePrefix = []byte{0xFE} KeyLastCodeID = append(SequenceKeyPrefix, []byte("lastCodeId")...) KeyLastInstanceID = append(SequenceKeyPrefix, []byte("lastContractId")...) diff --git a/x/compute/module.go b/x/compute/module.go index 021fdfacd..598e42ed4 100644 --- a/x/compute/module.go +++ b/x/compute/module.go @@ -164,13 +164,13 @@ func (am AppModule) BeginBlock(c context.Context) error { } if block_header.EncryptedRandom != nil { randomAndProof := append(block_header.EncryptedRandom.Random, block_header.EncryptedRandom.Proof...) //nolint:all - random, err := api.SubmitBlockSignatures(header, b_commit, data, randomAndProof) + random, validator_set_evidence, err := api.SubmitBlockSignatures(header, b_commit, data, randomAndProof) if err != nil { ctx.Logger().Error("Failed to submit block signatures") return err } - am.keeper.SetRandomSeed(ctx, random) + am.keeper.SetRandomSeed(ctx, random, validator_set_evidence) } else { ctx.Logger().Debug("Non-encrypted block", "Block_hash", block_header.LastBlockId.Hash, "Height", ctx.BlockHeight(), "Txs", len(x2_data)) }