runtime.rs 76 KiB
Newer Older
	// # Errors
	//
	// `ReturnCode::EcdsaRecoverFailed`
	[__unstable__] seal_ecdsa_recover(ctx, signature_ptr: u32, message_hash_ptr: u32, output_ptr: u32) -> ReturnCode => {
		ctx.charge_gas(RuntimeCosts::EcdsaRecovery)?;

		let mut signature: [u8; 65] = [0; 65];
		ctx.read_sandbox_memory_into_buf(signature_ptr, &mut signature)?;
		let mut message_hash: [u8; 32] = [0; 32];
		ctx.read_sandbox_memory_into_buf(message_hash_ptr, &mut message_hash)?;

		let result = ctx.ext.ecdsa_recover(&signature, &message_hash);

		match result {
			Ok(pub_key) => {
				// Write the recovered compressed ecdsa public key back into the sandboxed output
				// buffer.
				ctx.write_sandbox_memory(output_ptr, pub_key.as_ref())?;

				Ok(ReturnCode::Success)
			},
			Err(_) => Ok(ReturnCode::EcdsaRecoverFailed),
		}
	},

	// Replace the contract code at the specified address with new code.
	//
	// # Note
	//
	// There are a couple of important considerations which must be taken into account when
	// using this API:
	//
	// 1. The storage at the code address will remain untouched. This means that contract developers
	// must ensure that the storage layout of the new code is compatible with that of the old code.
	//
	// 2. Contracts using this API can't be assumed as having deterministic addresses. Said another way,
	// when using this API you lose the guarantee that an address always identifies a specific code hash.
	//
	// 3. If a contract calls into itself after changing its code the new call would use
	// the new code. However, if the original caller panics after returning from the sub call it
	// would revert the changes made by `seal_set_code_hash` and the next caller would use
	// the old code.
	//
	// # Parameters
	//
	// - `code_hash_ptr`: A pointer to the buffer that contains the new code hash.
	//
	// # Errors
	//
	// `ReturnCode::CodeNotFound`
	[__unstable__] seal_set_code_hash(ctx, code_hash_ptr: u32) -> ReturnCode => {
		ctx.charge_gas(RuntimeCosts::SetCodeHash)?;
		let code_hash: CodeHash<<E as Ext>::T> = ctx.read_sandbox_memory_as(code_hash_ptr)?;
		match ctx.ext.set_code_hash(code_hash) {
			Err(err) =>	{
				let code = Runtime::<E>::err_into_return_code(err)?;
				Ok(code)
			},
			Ok(()) => Ok(ReturnCode::Success)
		}
	},

	// Calculates Ethereum address from the ECDSA compressed public key and stores
	// it into the supplied buffer.
	//
	// # Parameters
	//
	// - `key_ptr`: a pointer to the ECDSA compressed public key. Should be decodable as a 33 bytes value.
	//		Traps otherwise.
	// - `out_ptr`: the pointer into the linear memory where the output
	//                 data is placed. The function will write the result
	//                 directly into this buffer.
	//
	// The value is stored to linear memory at the address pointed to by `out_ptr`.
	// If the available space at `out_ptr` is less than the size of the value a trap is triggered.
	//
	// # Errors
	//
	// `ReturnCode::EcdsaRecoverFailed`
	[__unstable__] seal_ecdsa_to_eth_address(ctx, key_ptr: u32, out_ptr: u32) -> ReturnCode => {
		ctx.charge_gas(RuntimeCosts::EcdsaToEthAddress)?;
		let mut compressed_key: [u8; 33] = [0;33];
		ctx.read_sandbox_memory_into_buf(key_ptr, &mut compressed_key)?;
		let result = ctx.ext.ecdsa_to_eth_address(&compressed_key);
		match result {
			Ok(eth_address) => {
				ctx.write_sandbox_memory(out_ptr, eth_address.as_ref())?;
				Ok(ReturnCode::Success)
			},
			Err(_) => Ok(ReturnCode::EcdsaRecoverFailed),
		}
	},