package octez-libs
A package that contains multiple base libraries used by the Octez suite
Install
Dune Dependency
Authors
Maintainers
Sources
tezos-octez-v20.1.tag.bz2
sha256=ddfb5076eeb0b32ac21c1eed44e8fc86a6743ef18ab23fff02d36e365bb73d61
sha512=d22a827df5146e0aa274df48bc2150b098177ff7e5eab52c6109e867eb0a1f0ec63e6bfbb0e3645a6c2112de3877c91a17df32ccbff301891ce4ba630c997a65
doc/src/octez-libs.tezos-sapling/forge.ml.html
Source file forge.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2019-2020 Nomadic Labs <contact@nomadic-labs.com> *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) (* to deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) (* and/or sell copies of the Software, and to permit persons to whom the *) (* Software is furnished to do so, subject to the following conditions: *) (* *) (* The above copyright notice and this permission notice shall be included *) (* in all copies or substantial portions of the Software. *) (* *) (* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) (* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) (* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) (* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) (* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) (* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) module Core = Core.Client module S = Storage module Input = struct include Core.Forge.Input let pos i = i.pos let amount i = i.amount let address i = i.address let is_spent forge_input state xfvk = let nf = Core.Nullifier.compute forge_input.address xfvk ~amount:forge_input.amount forge_input.rcm ~position:forge_input.pos in S.mem_nullifier state nf let get state pos vk = let existing_cm, cipher = S.get state pos in match of_ciphertext ~pos cipher vk with | None -> None | Some (memo, forge_input) -> if check_cm forge_input existing_cm then Some (memo, forge_input) else None let get_out state pos ovk = let existing_cm, cipher = S.get state pos in match of_ciphertext_out ~pos cipher ovk existing_cm with | None -> None | Some (memo, forge_input) -> if check_cm forge_input existing_cm then Some (memo, forge_input) else None let mem state pos = S.mem state pos end type output = Core.Forge.Output.t let make_output address amount memo = Core.Forge.Output.{address; amount; memo} let dummy_input anti_replay ctx dummy_witness root = let rcm = Core.Rcm.random () in let seed = Tezos_crypto.Hacl.Rand.gen 32 in let sk = Core.Spending_key.of_seed seed in let vk = Core.Viewing_key.of_sk sk in let addr = Core.Viewing_key.dummy_address () in let nf = Core.Nullifier.compute addr vk ~amount:0L rcm ~position:0L in let ar = Core.Proving.ar_random () in (* The proof is considered valid even with a dummy witness if the amount given is 0. *) let cv, rk, proof_i = Core.Proving.spend_proof ctx vk sk addr rcm ar ~amount:0L ~root ~witness:dummy_witness in let signature = Core.Proving.spend_sig sk ar cv nf rk proof_i anti_replay in Core.UTXO.{cv; nf; rk; proof_i; signature} let create_dummy_inputs n state anti_replay ctx = (* assertion already checked by callers *) assert (n >= 0) ; (* In order to get a valid witness we simply use the one of the first element *) let not_empty = S.mem state 0L in if not_empty then (* Doesn't make sense to create dummy_inputs with an empty storage *) let dummy_witness = S.get_witness state 0L in let root = S.get_root state in WithExceptions.Result.get_ok ~loc:__LOC__ @@ (* n is checked above *) List.init ~when_negative_length:() n (fun _ -> dummy_input anti_replay ctx dummy_witness root) else [] let dummy_output pctx ~memo_size = let addr = Core.Viewing_key.dummy_address () in let amount = 0L in let o = make_output addr amount (Tezos_crypto.Hacl.Rand.gen memo_size) in let rcm = Core.Rcm.random () in let esk = Core.DH.esk_random () in let cv_o, proof_o = Core.Proving.output_proof pctx esk addr rcm ~amount in let ciphertext, cm = Core.Forge.Output.to_ciphertext_without_ovk o rcm esk cv_o in Core.UTXO.{cm; proof_o; ciphertext} let forge_transaction ?(number_dummy_inputs = 0) ?(number_dummy_outputs = 0) (forge_inputs : Input.t list) (forge_outputs : output list) (sp : Core.Spending_key.t) (anti_replay : string) ~(bound_data : string) (state : S.state) = if number_dummy_inputs < 0 then raise (Invalid_argument "Tezos_sapling.Forge.forge_transaction: number_dummy_inputs is \ negative") ; if number_dummy_outputs < 0 then raise (Invalid_argument "Tezos_sapling.Forge.forge_transaction: number_dummy_outputs is \ negative") ; let memo_size = S.get_memo_size state in List.iter (fun forge_output -> assert (Bytes.length Core.Forge.Output.(forge_output.memo) = memo_size)) forge_outputs ; Core.Proving.with_proving_ctx (fun ctx -> let vk = Core.Viewing_key.of_sk sp in let root = S.get_root state in (* Forge the inputs *) let real_inputs = List.map (fun i -> let open Input in let ar = Core.Proving.ar_random () in let witness = S.get_witness state i.pos in let cv, rk, proof_i = Core.Proving.spend_proof ctx vk sp i.address i.rcm ar ~amount:i.amount ~root ~witness in let nf = Core.Nullifier.compute i.address vk ~amount:i.amount i.rcm ~position:i.pos in let signature = Core.Proving.spend_sig sp ar cv nf rk proof_i anti_replay in Core.UTXO.{cv; nf; rk; proof_i; signature}) forge_inputs in let real_outputs = List.map (fun forge_output -> let rcm = Core.Rcm.random () in (* encryption of the ciphertext containing diversifier, amount, commitment randomness, natural language memo *) (* the encoding of the amount to string is done by default in decimal. We fill the bigstring with 0s to get it at a length of 22 which is enough to hold 2^64 *) let open Core.Forge.Output in let esk = Core.DH.esk_random () in let cv_o, proof_o = Core.Proving.output_proof ctx esk forge_output.address rcm ~amount:forge_output.amount in let ciphertext, cm = to_ciphertext forge_output cv_o vk rcm esk in Core.UTXO.{cm; proof_o; ciphertext}) forge_outputs in let balance = let balance_inputs = List.fold_left (fun res forge_input -> Int64.add res Input.(forge_input.amount)) 0L forge_inputs in List.fold_left (fun res forge_output -> Int64.sub res Core.Forge.Output.(forge_output.amount)) balance_inputs forge_outputs in let dummy_inputs = create_dummy_inputs number_dummy_inputs state anti_replay ctx in let inputs = real_inputs @ dummy_inputs in let dummy_outputs = WithExceptions.Result.get_ok ~loc:__LOC__ @@ (* checked at entrance of function *) List.init ~when_negative_length:() number_dummy_outputs (fun _ -> dummy_output ctx ~memo_size) in let outputs = real_outputs @ dummy_outputs in let binding_sig = Core.Proving.make_binding_sig ctx inputs outputs ~balance ~bound_data anti_replay in Core.UTXO.{inputs; outputs; binding_sig; bound_data; balance; root}) (* Forge a transaction without sapling key (t to z). Add an optional amount of dummy inputs and outputs, set to 0 by default. The ovk encryption cannot be done without key and is therefore replaced by a dummy one *) let forge_shield_transaction ?(number_dummy_inputs = 0) ?(number_dummy_outputs = 0) (forge_outputs : output list) (balance : int64) (anti_replay : string) ~(bound_data : string) (state : S.state) = if number_dummy_inputs < 0 then raise (Invalid_argument "Tezos_sapling.Forge.forge_shield_transaction: number_dummy_inputs is \ negative") ; if number_dummy_outputs < 0 then raise (Invalid_argument "Tezos_sapling.Forge.forge_shield_transaction: number_dummy_outputs \ is negative") ; let memo_size = S.get_memo_size state in List.iter (fun forge_output -> assert (Bytes.length Core.Forge.Output.(forge_output.memo) = memo_size)) forge_outputs ; Core.Proving.with_proving_ctx (fun ctx -> (* Compute the root of the current tree *) let root = S.get_root state in let real_outputs = List.map (fun forge_output -> let rcm = Core.Rcm.random () in (* encryption of the ciphertext containing diversifier, amount, commitment randomness, natural language memo *) (* the encoding of the amount to string is done by default in decimal. We fill the bigstring with 0s to get it at a length of 22 which is enough to hold 2^64 *) let open Core.Forge.Output in let esk = Core.DH.esk_random () in let cv_o, proof_o = Core.Proving.output_proof ctx esk forge_output.address rcm ~amount:forge_output.amount in let ciphertext, cm = to_ciphertext_without_ovk forge_output rcm esk cv_o in Core.UTXO.{cm; proof_o; ciphertext}) forge_outputs in let balance_outputs = List.fold_left (fun res forge_output -> Int64.sub res Core.Forge.Output.(forge_output.amount)) 0L forge_outputs in let dummy_inputs = create_dummy_inputs number_dummy_inputs state anti_replay ctx in let dummy_outputs = WithExceptions.Result.get_ok ~loc:__LOC__ @@ (* checked at entrance of function *) List.init ~when_negative_length:() number_dummy_outputs (fun _ -> dummy_output ctx ~memo_size) in let outputs = real_outputs @ dummy_outputs in let binding_sig = Core.Proving.make_binding_sig ctx [] outputs ~balance:balance_outputs ~bound_data anti_replay in Core.UTXO. {inputs = dummy_inputs; outputs; binding_sig; bound_data; balance; root}) let forge_shield_transaction_legacy ?(number_dummy_inputs = 0) ?(number_dummy_outputs = 0) (forge_outputs : output list) (balance : int64) (anti_replay : string) (state : S.state) = let Core.UTXO.{inputs; outputs; binding_sig; balance; root; bound_data = _} = forge_shield_transaction ~number_dummy_inputs ~number_dummy_outputs forge_outputs balance anti_replay ~bound_data:"" state in Core.UTXO.Legacy.{inputs; outputs; binding_sig; balance; root} let forge_transaction_legacy ?number_dummy_inputs ?number_dummy_outputs (forge_inputs : Input.t list) (forge_outputs : output list) (sp : Core.Spending_key.t) (anti_replay : string) (state : S.state) = let Core.UTXO.{inputs; outputs; binding_sig; balance; root; _} = forge_transaction ?number_dummy_inputs ?number_dummy_outputs forge_inputs forge_outputs sp anti_replay ~bound_data:"" state in Core.UTXO.Legacy.{inputs; outputs; binding_sig; balance; root}
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>