Unverified Commit e22a0feb authored by Hero Bird's avatar Hero Bird Committed by GitHub
Browse files

Use BLAKE2b 256-bit hashes for selectors (#680)

* use BLAKE2b 256-bit hashes for selectors

Before this PR we accidentally used BLAKE2b 512-bit hashing.
Using 256-bit versions is important for smart contracts so that smart contracts can compute selector hashes on their own through the built-in contracts-pallet hash support which includes BLAKE2b 256-bit but not 512-bit.

* apply rustfmt
parent a50bf6d3
Pipeline #123070 canceled with stages
in 6 minutes and 3 seconds
......@@ -789,7 +789,7 @@ impl TryFrom<syn::NestedMeta> for AttributeFrag {
];
return Ok(AttributeFrag {
ast: meta,
arg: AttributeArg::Selector(Selector::new(
arg: AttributeArg::Selector(Selector::from_bytes(
selector_bytes,
)),
})
......@@ -1069,7 +1069,7 @@ mod tests {
#[ink(selector = "0xDEADBEEF")]
},
Ok(test::Attribute::Ink(vec![AttributeArg::Selector(
Selector::new([0xDE, 0xAD, 0xBE, 0xEF]),
Selector::from_bytes([0xDE, 0xAD, 0xBE, 0xEF]),
)])),
);
}
......
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Computes the BLAKE2b 256-bit hash for the given input and stores it in output.
pub fn blake2b_256(input: &[u8], output: &mut [u8]) {
use ::blake2::digest::{
Update as _,
VariableOutput as _,
};
let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32);
blake2.update(input);
blake2.finalize_variable(|result| output.copy_from_slice(result));
}
......@@ -343,8 +343,7 @@ where
}
}
};
let hash = <blake2::Blake2b as blake2::Digest>::digest(&joined);
ir::Selector::new([hash[0], hash[1], hash[2], hash[3]])
ir::Selector::new(&joined)
}
/// Ensures that common invariants of externally callable ink! entities are met.
......@@ -521,11 +520,8 @@ mod tests {
impl ExpectedSelector {
pub fn expected_selector(self) -> ir::Selector {
match self {
Self::Raw(raw_selector) => ir::Selector::new(raw_selector),
Self::Blake2(blake2_input) => {
let hash = <blake2::Blake2b as blake2::Digest>::digest(&blake2_input);
ir::Selector::new([hash[0], hash[1], hash[2], hash[3]])
}
Self::Raw(raw_selector) => ir::Selector::from_bytes(raw_selector),
Self::Blake2(blake2_input) => ir::Selector::new(&blake2_input),
}
}
}
......
......@@ -781,7 +781,7 @@ mod tests {
}
}
},
"encountered ink! messages with overlapping selectors (= [EA, 48, 09, 33])\n\
"encountered ink! messages with overlapping selectors (= [04, C4, 94, 46])\n\
hint: use #[ink(selector = \"0x...\")] on the callable or \
#[ink(namespace = \"...\")] on the implementation block to \
disambiguate overlapping selectors.",
......
......@@ -15,6 +15,7 @@
#![allow(dead_code)]
mod attrs;
mod blake2;
mod chain_extension;
mod config;
mod contract;
......
......@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use super::blake2::blake2b_256;
/// A function selector.
///
/// # Note
......@@ -23,11 +25,18 @@ pub struct Selector {
}
impl Selector {
/// Creates a new selector from the given bytes.
pub fn new(bytes: [u8; 4]) -> Self {
/// Creates a new selector from the given raw bytes.
pub fn from_bytes(bytes: [u8; 4]) -> Self {
Self { bytes }
}
/// Computes the BLAKE-2 256-bit based selector from the given input bytes.
pub fn new(input: &[u8]) -> Self {
let mut output = [0; 32];
blake2b_256(input, &mut output);
Self::from_bytes([output[0], output[1], output[2], output[3]])
}
/// Returns the underlying four bytes.
pub fn as_bytes(&self) -> &[u8; 4] {
&self.bytes
......@@ -41,6 +50,6 @@ impl Selector {
impl From<[u8; 4]> for Selector {
fn from(bytes: [u8; 4]) -> Self {
Self::new(bytes)
Self::from_bytes(bytes)
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment