Skip to content

Commit 6d7132b

Browse files
committed
epoch 416 contractstate tree
1 parent 747290e commit 6d7132b

16 files changed

Lines changed: 336 additions & 224 deletions

File tree

ex/lib/api/api_proof.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ defmodule API.Proof do
33
entry_hash = if byte_size(entry_hash) != 32, do: Base58.decode(entry_hash), else: entry_hash
44
proof = Entry.proof_validators(entry_hash)
55
%{
6-
value: Base58.encode(proof.value),
76
key: proof.key,
7+
value: Base58.encode(proof.value),
88
validators: Enum.map(proof.validators, & Base58.encode(&1)),
99
proof: %{
1010
root: Base58.encode(proof.proof.root),
@@ -17,6 +17,9 @@ defmodule API.Proof do
1717

1818
def proof_contractstate(key) do
1919
%{db: db, cf: cf} = :persistent_term.get({:rocksdb, Fabric})
20-
RDB.bintree_contractstate_root_prove(db, key)
20+
proof = RDB.bintree_contractstate_root_prove(db, key)
21+
#RDB.bintree_root_verify(proof, "bic:epoch:segment_vr_hash", "7")
22+
#RDB.bintree_
23+
#
2124
end
2225
end

ex/lib/api/db_api.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule DB.API do
3434
"entry", "entry_meta",
3535
"attestation",
3636
"tx", "tx_account_nonce", "tx_receiver_nonce",
37-
"contractstate"
37+
"contractstate", "contractstate_tree"
3838
]
3939
try do
4040
{:ok, db_ref, cf_ref_list} = RDB.open_transaction_db(path, cfs)
@@ -44,15 +44,15 @@ defmodule DB.API do
4444
entry_cf, entry_meta_cf,
4545
attestation_cf,
4646
tx_cf, tx_account_nonce_cf, tx_receiver_nonce_cf,
47-
contractstate_cf
47+
contractstate_cf, contractstate_tree_cf,
4848
] = cf_ref_list
4949
cf = %{
5050
default: default_cf,
5151
sysconf: sysconf_cf,
5252
entry: entry_cf, entry_meta: entry_meta_cf,
5353
attestation: attestation_cf,
5454
tx: tx_cf, tx_account_nonce: tx_account_nonce_cf, tx_receiver_nonce: tx_receiver_nonce_cf,
55-
contractstate: contractstate_cf
55+
contractstate: contractstate_cf, contractstate_tree: contractstate_tree_cf
5656
}
5757
:persistent_term.put({:rocksdb, Fabric}, %{db: db_ref, cf_list: cf_ref_list, cf: cf, path: path})
5858
catch

ex/lib/api/db_chain.ex

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ defmodule DB.Chain do
114114
validator_for_height(height(db_opts) + 1, db_opts)
115115
end
116116

117+
def validators_removed(epoch, db_opts \\ %{}) do
118+
vstart = validators_for_height(epoch * 100_000, db_opts)
119+
vend = validators_for_height(epoch * 100_000 + 99_999, db_opts)
120+
vstart -- vend
121+
end
117122

118123
#Rewind
119124
def rewind(target_hash) do
@@ -158,16 +163,20 @@ defmodule DB.Chain do
158163
Enum.reverse(m_rev)
159164
|> Enum.each(fn(mut)->
160165
op = :"#{mut.op}"
166+
cf_table = case mut.table do
167+
"contractstate" -> cf.contractstate
168+
"contractstate_tree" -> cf.contractstate_tree
169+
end
161170
case op do
162171
:put ->
163-
RocksDB.put(mut.key, mut.value, %{rtx: db_opts.rtx, cf: cf.contractstate})
172+
RocksDB.put(mut.key, mut.value, %{rtx: db_opts.rtx, cf: cf_table})
164173
:delete ->
165-
RocksDB.delete(mut.key, %{rtx: db_opts.rtx, cf: cf.contractstate})
174+
RocksDB.delete(mut.key, %{rtx: db_opts.rtx, cf: cf_table})
166175
:clear_bit ->
167-
old_value = RocksDB.get(mut.key, %{rtx: db_opts.rtx, cf: cf.contractstate})
176+
old_value = RocksDB.get(mut.key, %{rtx: db_opts.rtx, cf: cf_table})
168177
<< left::size(mut.value), _old_bit::size(1), right::bitstring >> = old_value
169178
new_value = << left::size(mut.value), 0::size(1), right::bitstring >>
170-
RocksDB.put(mut.key, new_value, %{rtx: db_opts.rtx, cf: cf.contractstate})
179+
RocksDB.put(mut.key, new_value, %{rtx: db_opts.rtx, cf: cf_table})
171180
end
172181
end)
173182
end

ex/lib/consensus/consensus_kv.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,15 @@ defmodule ConsensusKV do
207207
end
208208
end
209209

210-
def hash_mutations(m) do
210+
def hash_mutations(height, m) do
211+
if height >= 416_00000 do
212+
RDB.vecpak_encode(m)
213+
|> Blake3.hash()
214+
else
215+
m = Enum.map(m, & Map.drop(&1, [:table]))
211216
RDB.vecpak_encode(m)
212217
|> Blake3.hash()
218+
end
213219
end
214220

215221
def merge_nested(left, right) do

ex/lib/consensus/fabric_gen.ex

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,22 +314,26 @@ defmodule FabricGen do
314314
txus = Enum.map(entry.txs, & Map.put(&1, :tx_cost, TX.exec_cost(0, &1)))
315315
{rtx, m, m_rev, l} = RDB.apply_entry(db, next_entry_trimmed_map,
316316
Application.fetch_env!(:ama, :trainer_pk), Application.fetch_env!(:ama, :trainer_sk), txus,
317-
Application.fetch_env!(:ama, :testnet), Map.keys(Application.fetch_env!(:ama, :keys_by_pk))
317+
!!Application.fetch_env!(:ama, :testnet), Map.keys(Application.fetch_env!(:ama, :keys_by_pk))
318318
)
319319
rebuild_m_fn = fn(m)->
320320
Enum.map(m, fn(inner)->
321321
op = :"#{IO.iodata_to_binary(inner[~c"op"])}"
322322
case op do
323-
:set_bit -> %{op: op, key: IO.iodata_to_binary(inner[~c"key"]), value: :erlang.binary_to_integer("#{inner[~c"value"]}"), bloomsize: :erlang.binary_to_integer("#{inner[~c"bloomsize"]}")}
324-
:clear_bit -> %{op: op, key: IO.iodata_to_binary(inner[~c"key"]), value: :erlang.binary_to_integer("#{inner[~c"value"]}")}
325-
:delete -> %{op: op, key: IO.iodata_to_binary(inner[~c"key"])}
326-
:put -> %{op: op, key: IO.iodata_to_binary(inner[~c"key"]), value: IO.iodata_to_binary(inner[~c"value"])}
323+
:set_bit -> %{op: op, table: IO.iodata_to_binary(inner[~c"table"]), key: IO.iodata_to_binary(inner[~c"key"]), value: :erlang.binary_to_integer("#{inner[~c"value"]}"), bloomsize: :erlang.binary_to_integer("#{inner[~c"bloomsize"]}")}
324+
:clear_bit -> %{op: op, table: IO.iodata_to_binary(inner[~c"table"]), key: IO.iodata_to_binary(inner[~c"key"]), value: :erlang.binary_to_integer("#{inner[~c"value"]}")}
325+
:delete -> %{op: op, table: IO.iodata_to_binary(inner[~c"table"]), key: IO.iodata_to_binary(inner[~c"key"])}
326+
:put -> %{op: op, table: IO.iodata_to_binary(inner[~c"table"]), key: IO.iodata_to_binary(inner[~c"key"]), value: IO.iodata_to_binary(inner[~c"value"])}
327327
end
328328
end)
329329
end
330330
rebuild_l_fn = fn(m)->
331331
Enum.map(m, fn(inner)->
332+
if entry.header.height >= 416_00000 do
333+
%{error: IO.iodata_to_binary(inner["error"]), gas_used: IO.iodata_to_binary(inner["gas_used"])}
334+
else
332335
%{error: :"#{IO.iodata_to_binary(inner["error"])}"}
336+
end
333337
end)
334338
end
335339
m = rebuild_m_fn.(m)
@@ -345,7 +349,7 @@ defmodule FabricGen do
345349
#m = m ++ m_exit
346350
#m_rev = m_rev ++ m_exit_rev
347351

348-
mutations_hash = ConsensusKV.hash_mutations(l ++ m)
352+
mutations_hash = ConsensusKV.hash_mutations(next_entry.header.height, l ++ m)
349353

350354
RocksDB.put("temporal_tip", next_entry.hash, %{rtx: rtx, cf: cf.sysconf})
351355

ex/lib/consensus/models/consensus.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ defmodule Consensus do
1919
mask_set_size: 99
2020
}
2121
}
22+
23+
entry_hash
24+
root_blocks
25+
root_contractstate
26+
root_receipts
2227
"""
2328

2429
def validate_vs_chain(c) do

ex/lib/consensus/models/tx.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ defmodule TX do
8080
if !is_binary(action[:contract]), do: throw %{error: :contract_must_be_binary}
8181
if !is_binary(action[:function]), do: throw %{error: :function_must_be_binary}
8282
if !is_list(action[:args]), do: throw %{error: :args_must_be_list}
83+
if length(action.args) > 16, do: throw %{error: :args_length_cannot_exceed_16}
8384
Enum.each(action.args, fn(arg)->
8485
if !is_binary(arg), do: throw(%{error: :arg_must_be_binary})
8586
end)

ex/lib/misc/rocksdb.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ defmodule RocksDB do
214214
d = RocksDB.dump(cf.contractstate)
215215
dd = inspect d, limit: 1111111111111111111, pretty: true
216216
File.write! "/tmp/amastate", dd
217+
d = RocksDB.dump(cf.contractstate_tree)
218+
dd = inspect d, limit: 1111111111111111111, pretty: true
219+
File.write! "/tmp/amastate_tree", dd
217220
end
218221

219222
def dump(cf) do

ex/lib/native/rdb.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ defmodule RDB do
5252

5353
def bintree_root(_propslist), do: :erlang.nif_error(:nif_not_loaded)
5454
def bintree_root_prove(_propslist, _key), do: :erlang.nif_error(:nif_not_loaded)
55-
def bintree_root_verify(_proof, _key, _value), do: :erlang.nif_error(:nif_not_loaded)
55+
def bintree_root_verify(_proof, _ns, _key, _value), do: :erlang.nif_error(:nif_not_loaded)
5656
def bintree_contractstate_root_prove(_db, _key), do: :erlang.nif_error(:nif_not_loaded)
5757
end

ex/native/rdb/src/consensus/bintree.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@ const ZERO_HASH: Hash = [0u8; 32];
1111
// STRUCTS
1212
// ============================================================================
1313

14+
/// The Universal Proof Struct.
15+
///
16+
/// - If `path` == sha256(key) and `hash` == sha256(key, value): It's an Inclusion Proof.
17+
/// - If `path` == sha256(key) and `hash` != sha256(key, value): It's a Mismatch Proof.
18+
/// - If `path` != sha256(key): It's a Non-Existence Proof (pointing to the closest ancestor).
19+
#[derive(Debug, Clone)]
20+
pub struct Proof {
21+
pub root: Hash,
22+
pub nodes: Vec<ProofNode>,
23+
pub path: Path, // The path of the leaf node actually found in the tree
24+
pub hash: Hash, // The hash of the leaf node actually found in the tree
25+
}
26+
27+
/// A simplified proof node without length.
28+
#[derive(Debug, Clone)]
29+
pub struct ProofNode {
30+
pub hash: Hash,
31+
pub direction: u8
32+
}
33+
1434
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
1535
pub struct NodeKey {
1636
pub path: Path,
@@ -39,26 +59,6 @@ pub enum Op {
3959
Delete(Vec<u8>),
4060
}
4161

42-
/// A simplified proof node without length.
43-
#[derive(Debug, Clone)]
44-
pub struct ProofNode {
45-
pub hash: Hash,
46-
pub direction: u8
47-
}
48-
49-
/// The Universal Proof Struct.
50-
///
51-
/// - If `path` == sha256(key) and `hash` == sha256(key, value): It's an Inclusion Proof.
52-
/// - If `path` == sha256(key) and `hash` != sha256(key, value): It's a Mismatch Proof.
53-
/// - If `path` != sha256(key): It's a Non-Existence Proof (pointing to the closest ancestor).
54-
#[derive(Debug, Clone)]
55-
pub struct Proof {
56-
pub root: Hash,
57-
pub nodes: Vec<ProofNode>,
58-
pub path: Path, // The path of the leaf node actually found in the tree
59-
pub hash: Hash, // The hash of the leaf node actually found in the tree
60-
}
61-
6262
#[derive(Debug, PartialEq)]
6363
pub enum VerifyStatus {
6464
Included, // Key exists and Value matches
@@ -387,8 +387,8 @@ impl Hubt {
387387
// ========================================================================
388388

389389
/// Verifies the proof and determines the relationship between the Key, Value, and the Tree.
390-
pub fn verify(proof: &Proof, k: Vec<u8>, v: Vec<u8>) -> VerifyStatus {
391-
let target_path = sha256(&k);
390+
pub fn verify(proof: &Proof, ns: Option<&[u8]>, k: Vec<u8>, v: Vec<u8>) -> VerifyStatus {
391+
let target_path = compute_namespace_path(ns, &k);
392392
let claimed_leaf_hash = concat_and_hash(&k, &v);
393393

394394
// 1. Basic Integrity Check: Does the proof path/hash actually hash up to the Root?

0 commit comments

Comments
 (0)