From 2b937ca76985afec2834e53736f575d626ca2119 Mon Sep 17 00:00:00 2001
From: David Turner <novalis@novalis.org>
Date: Mon, 18 Apr 2022 15:32:53 -0400
Subject: [PATCH] Proto: Allow implicit accounts to delegate at bootstrap time

This is already allowed for smart contracts.
---
 src/lib_store/test/alpha_utils.ml             |  7 +-
 src/proto_alpha/lib_client/mockup.ml          | 48 ++++++++++---
 .../lib_parameters/default_parameters.ml      |  5 +-
 .../lib_parameters/default_parameters.mli     |  5 +-
 .../lib_protocol/alpha_context.mli            |  1 +
 .../lib_protocol/bootstrap_storage.ml         | 10 ++-
 .../lib_protocol/parameters_repr.ml           | 67 +++++++++++++++++--
 .../lib_protocol/parameters_repr.mli          |  1 +
 .../lib_protocol/test/helpers/account.ml      | 14 +++-
 .../lib_protocol/test/helpers/account.mli     |  4 +-
 .../lib_protocol/test/helpers/block.ml        | 18 +++--
 .../lib_protocol/test/helpers/block.mli       |  6 +-
 .../lib_protocol/test/helpers/context.ml      | 31 +++++----
 .../lib_protocol/test/helpers/context.mli     |  2 +
 .../test/integration/consensus/test_baking.ml |  6 +-
 .../integration/consensus/test_delegation.ml  | 32 +++++++++
 .../integration/michelson/test_sapling.ml     |  2 +-
 .../test/integration/test_frozen_bonds.ml     |  2 +-
 .../test/integration/test_token.ml            |  2 +-
 19 files changed, 208 insertions(+), 55 deletions(-)

diff --git a/src/lib_store/test/alpha_utils.ml b/src/lib_store/test/alpha_utils.ml
index cfa2f23ffea2..62d69dc936f2 100644
--- a/src/lib_store/test/alpha_utils.ml
+++ b/src/lib_store/test/alpha_utils.ml
@@ -108,9 +108,10 @@ module Account = struct
 
   let dummy_account = new_account ()
 
-  let account_to_bootstrap ({pkh; pk; _}, amount) =
+  let account_to_bootstrap ({pkh; pk; _}, amount, delegate_to) =
     let open Parameters in
-    ({public_key_hash = pkh; public_key = Some pk; amount} : bootstrap_account)
+    ({public_key_hash = pkh; public_key = Some pk; amount; delegate_to}
+      : bootstrap_account)
 
   let commitment_secret =
     Blinded_public_key_hash.activation_code_of_hex
@@ -409,7 +410,7 @@ let default_accounts =
   let accounts = List.map to_account initial_accounts in
   List.iter Account.add_account accounts ;
   List.map
-    (fun acc -> Account.account_to_bootstrap (acc, default_amount))
+    (fun acc -> Account.account_to_bootstrap (acc, default_amount, None))
     accounts
 
 let default_genesis_parameters =
diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml
index 08c087d272e6..4b50846cb4db 100644
--- a/src/proto_alpha/lib_client/mockup.ml
+++ b/src/proto_alpha/lib_client/mockup.ml
@@ -1080,7 +1080,12 @@ module Parsed_account = struct
     let public_key_hash = Signature.Public_key.hash public_key in
     return
       Parameters.
-        {public_key_hash; public_key = Some public_key; amount = repr.amount}
+        {
+          public_key_hash;
+          public_key = Some public_key;
+          amount = repr.amount;
+          delegate_to = None;
+        }
 
   let default_to_json (cctxt : Tezos_client_base.Client_context.full) :
       string tzresult Lwt.t =
@@ -1131,15 +1136,37 @@ module Bootstrap_account = struct
   let encoding : Parameters.bootstrap_account Data_encoding.t =
     let open Data_encoding in
     let open Parameters in
-    conv
-      (fun {public_key_hash; public_key; amount} ->
-        (public_key_hash, public_key, amount))
-      (fun (public_key_hash, public_key, amount) ->
-        {public_key_hash; public_key; amount})
-      (obj3
-         (req "public_key_hash" Signature.Public_key_hash.encoding)
-         (opt "public_key" Signature.Public_key.encoding)
-         (req "amount" Tez.encoding))
+    union
+      [
+        case
+          ~title:"No delegate"
+          (Tag 0)
+          (obj3
+             (req "public_key_hash" Signature.Public_key_hash.encoding)
+             (opt "public_key" Signature.Public_key.encoding)
+             (req "amount" Tez.encoding))
+          (function
+            | {public_key_hash; public_key; amount; delegate_to = None} ->
+                Some (public_key_hash, public_key, amount)
+            | _ -> None)
+          (fun (public_key_hash, public_key, amount) ->
+            {public_key_hash; public_key; amount; delegate_to = None});
+        case
+          ~title:"With delegate"
+          (Tag 1)
+          (obj4
+             (req "public_key_hash" Signature.Public_key_hash.encoding)
+             (opt "public_key" Signature.Public_key.encoding)
+             (req "amount" Tez.encoding)
+             (req "delegate_to" Signature.Public_key_hash.encoding))
+          (function
+            | {public_key_hash; public_key; amount; delegate_to = Some delegate}
+              ->
+                Some (public_key_hash, public_key, amount, delegate)
+            | _ -> None)
+          (fun (public_key_hash, public_key, amount, delegate) ->
+            {public_key_hash; public_key; amount; delegate_to = Some delegate});
+      ]
 end
 
 module Bootstrap_contract = struct
@@ -1213,6 +1240,7 @@ let lib_parameters_json_encoding =
           Parameters.public_key = Some pk;
           public_key_hash = Signature.Public_key.hash pk;
           amount;
+          delegate_to = None;
         })
       (tup2 Signature.Public_key.encoding Tez.encoding)
   in
diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml
index 5efefbf1e523..d22d07ac466a 100644
--- a/src/proto_alpha/lib_parameters/default_parameters.ml
+++ b/src/proto_alpha/lib_parameters/default_parameters.ml
@@ -275,12 +275,13 @@ let compute_accounts =
           public_key_hash;
           public_key = Some public_key;
           amount = bootstrap_balance;
+          delegate_to = None;
         })
 
 let bootstrap_accounts = compute_accounts bootstrap_accounts_strings
 
-let make_bootstrap_account (pkh, pk, amount) =
-  Parameters.{public_key_hash = pkh; public_key = Some pk; amount}
+let make_bootstrap_account (pkh, pk, amount, delegate_to) =
+  Parameters.{public_key_hash = pkh; public_key = Some pk; amount; delegate_to}
 
 let parameters_of_constants ?(bootstrap_accounts = bootstrap_accounts)
     ?(bootstrap_contracts = []) ?(commitments = []) constants =
diff --git a/src/proto_alpha/lib_parameters/default_parameters.mli b/src/proto_alpha/lib_parameters/default_parameters.mli
index def1fe37347b..8aeb40866526 100644
--- a/src/proto_alpha/lib_parameters/default_parameters.mli
+++ b/src/proto_alpha/lib_parameters/default_parameters.mli
@@ -35,7 +35,10 @@ val constants_test : Constants.Parametric.t
 val test_commitments : Commitment.t list lazy_t
 
 val make_bootstrap_account :
-  Signature.public_key_hash * Signature.public_key * Tez.t ->
+  Signature.public_key_hash
+  * Signature.public_key
+  * Tez.t
+  * Signature.public_key_hash option ->
   Parameters.bootstrap_account
 
 val parameters_of_constants :
diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli
index b74aa51513cf..69671f95b943 100644
--- a/src/proto_alpha/lib_protocol/alpha_context.mli
+++ b/src/proto_alpha/lib_protocol/alpha_context.mli
@@ -3475,6 +3475,7 @@ module Parameters : sig
     public_key_hash : public_key_hash;
     public_key : public_key option;
     amount : Tez.t;
+    delegate_to : public_key_hash option;
   }
 
   type bootstrap_contract = {
diff --git a/src/proto_alpha/lib_protocol/bootstrap_storage.ml b/src/proto_alpha/lib_protocol/bootstrap_storage.ml
index a5f9715e5a6b..62a38dae7711 100644
--- a/src/proto_alpha/lib_protocol/bootstrap_storage.ml
+++ b/src/proto_alpha/lib_protocol/bootstrap_storage.ml
@@ -24,8 +24,8 @@
 (*****************************************************************************)
 
 let init_account (ctxt, balance_updates)
-    ({public_key_hash; public_key; amount} : Parameters_repr.bootstrap_account)
-    =
+    ({public_key_hash; public_key; amount; delegate_to} :
+      Parameters_repr.bootstrap_account) =
   let contract = Contract_repr.Implicit public_key_hash in
   Token.transfer
     ~origin:Protocol_migration
@@ -40,7 +40,11 @@ let init_account (ctxt, balance_updates)
         ctxt
         public_key_hash
         public_key
-      >>=? fun ctxt -> Delegate_storage.set ctxt contract (Some public_key_hash)
+      >>=? fun ctxt ->
+      Delegate_storage.set
+        ctxt
+        contract
+        (Some (Option.value ~default:public_key_hash delegate_to))
   | None -> return ctxt)
   >|=? fun ctxt -> (ctxt, new_balance_updates @ balance_updates)
 
diff --git a/src/proto_alpha/lib_protocol/parameters_repr.ml b/src/proto_alpha/lib_protocol/parameters_repr.ml
index 5fc7d3bd9fb3..3ab238b23d48 100644
--- a/src/proto_alpha/lib_protocol/parameters_repr.ml
+++ b/src/proto_alpha/lib_protocol/parameters_repr.ml
@@ -28,6 +28,7 @@ type bootstrap_account = {
   public_key_hash : Signature.Public_key_hash.t;
   public_key : Signature.Public_key.t option;
   amount : Tez_repr.t;
+  delegate_to : Signature.Public_key_hash.t option;
 }
 
 type bootstrap_contract = {
@@ -54,29 +55,85 @@ let bootstrap_account_encoding =
         ~title:"Public_key_known"
         (tup2 Signature.Public_key.encoding Tez_repr.encoding)
         (function
-          | {public_key_hash; public_key = Some public_key; amount} ->
+          | {
+              public_key_hash;
+              public_key = Some public_key;
+              amount;
+              delegate_to = None;
+            } ->
               assert (
                 Signature.Public_key_hash.equal
                   (Signature.Public_key.hash public_key)
                   public_key_hash) ;
               Some (public_key, amount)
-          | {public_key = None; _} -> None)
+          | {public_key = None; _} | {delegate_to = Some _; _} -> None)
         (fun (public_key, amount) ->
           {
             public_key = Some public_key;
             public_key_hash = Signature.Public_key.hash public_key;
             amount;
+            delegate_to = None;
           });
       case
         (Tag 1)
         ~title:"Public_key_unknown"
         (tup2 Signature.Public_key_hash.encoding Tez_repr.encoding)
         (function
-          | {public_key_hash; public_key = None; amount} ->
+          | {public_key_hash; public_key = None; amount; delegate_to = None} ->
               Some (public_key_hash, amount)
-          | {public_key = Some _; _} -> None)
+          | {public_key = Some _; _} | {delegate_to = Some _; _} -> None)
         (fun (public_key_hash, amount) ->
-          {public_key = None; public_key_hash; amount});
+          {public_key = None; public_key_hash; amount; delegate_to = None});
+      case
+        (Tag 2)
+        ~title:"Public_key_known_with_delegate"
+        (tup3
+           Signature.Public_key.encoding
+           Tez_repr.encoding
+           Signature.Public_key_hash.encoding)
+        (function
+          | {
+              public_key_hash;
+              public_key = Some public_key;
+              amount;
+              delegate_to = Some delegate;
+            } ->
+              assert (
+                Signature.Public_key_hash.equal
+                  (Signature.Public_key.hash public_key)
+                  public_key_hash) ;
+              Some (public_key, amount, delegate)
+          | {public_key = None; _} | {delegate_to = None; _} -> None)
+        (fun (public_key, amount, delegate) ->
+          {
+            public_key = Some public_key;
+            public_key_hash = Signature.Public_key.hash public_key;
+            amount;
+            delegate_to = Some delegate;
+          });
+      case
+        (Tag 3)
+        ~title:"Public_key_unknown_with_delegate"
+        (tup3
+           Signature.Public_key_hash.encoding
+           Tez_repr.encoding
+           Signature.Public_key_hash.encoding)
+        (function
+          | {
+              public_key_hash;
+              public_key = None;
+              amount;
+              delegate_to = Some delegate;
+            } ->
+              Some (public_key_hash, amount, delegate)
+          | {public_key = Some _; _} | {delegate_to = None; _} -> None)
+        (fun (public_key_hash, amount, delegate) ->
+          {
+            public_key = None;
+            public_key_hash;
+            amount;
+            delegate_to = Some delegate;
+          });
     ]
 
 let bootstrap_contract_encoding =
diff --git a/src/proto_alpha/lib_protocol/parameters_repr.mli b/src/proto_alpha/lib_protocol/parameters_repr.mli
index d31bab91a86c..844e54ba3753 100644
--- a/src/proto_alpha/lib_protocol/parameters_repr.mli
+++ b/src/proto_alpha/lib_protocol/parameters_repr.mli
@@ -32,6 +32,7 @@ type bootstrap_account = {
   public_key_hash : Signature.Public_key_hash.t;
   public_key : Signature.Public_key.t option;
   amount : Tez_repr.t;
+  delegate_to : Signature.Public_key_hash.t option;
 }
 
 (** An originated contract initially existing on a chain since genesis. *)
diff --git a/src/proto_alpha/lib_protocol/test/helpers/account.ml b/src/proto_alpha/lib_protocol/test/helpers/account.ml
index 76047a436749..df85819387f6 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/account.ml
+++ b/src/proto_alpha/lib_protocol/test/helpers/account.ml
@@ -77,7 +77,8 @@ let dummy_account =
 
 let default_initial_balance = Tez.of_mutez_exn 4_000_000_000_000L
 
-let generate_accounts ?rng_state ?(initial_balances = []) n : (t * Tez.t) list =
+let generate_accounts ?rng_state ?(initial_balances = []) ?bootstrap_delegations
+    n : (t * Tez.t * Signature.Public_key_hash.t option) list =
   Signature.Public_key_hash.Table.clear known_accounts ;
   let amount i =
     match List.nth_opt initial_balances i with
@@ -89,6 +90,15 @@ let generate_accounts ?rng_state ?(initial_balances = []) n : (t * Tez.t) list =
     | None -> Random.State.make_self_init ()
     | Some state -> state
   in
+  let delegate_to account =
+    Option.filter_map
+      (fun bootstrap_delegations ->
+        List.find_map
+          (fun (from_pkh, to_pkh) ->
+            if from_pkh = account then Some to_pkh else None)
+          bootstrap_delegations)
+      bootstrap_delegations
+  in
   List.map
     (fun i ->
       let pkh, pk, sk =
@@ -96,7 +106,7 @@ let generate_accounts ?rng_state ?(initial_balances = []) n : (t * Tez.t) list =
       in
       let account = {pkh; pk; sk} in
       Signature.Public_key_hash.Table.add known_accounts pkh account ;
-      (account, amount i))
+      (account, amount i, delegate_to pkh))
     (0 -- (n - 1))
 
 let commitment_secret =
diff --git a/src/proto_alpha/lib_protocol/test/helpers/account.mli b/src/proto_alpha/lib_protocol/test/helpers/account.mli
index f327344fcfbb..d7064b862fcf 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/account.mli
+++ b/src/proto_alpha/lib_protocol/test/helpers/account.mli
@@ -59,8 +59,10 @@ val default_initial_balance : Tez.t
 val generate_accounts :
   ?rng_state:Random.State.t ->
   ?initial_balances:int64 list ->
+  ?bootstrap_delegations:
+    (Signature.Public_key_hash.t * Signature.Public_key_hash.t) list ->
   int ->
-  (t * Tez.t) list
+  (t * Tez.t * Signature.Public_key_hash.t option) list
 
 val commitment_secret : Blinded_public_key_hash.activation_code
 
diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml
index 6f2588e54c6b..f705a39183d1 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/block.ml
+++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml
@@ -275,8 +275,8 @@ let prepare_main_init_params ?bootstrap_contracts commitments constants
   let open Tezos_protocol_alpha_parameters in
   let bootstrap_accounts =
     List.map
-      (fun (Account.{pk; pkh; _}, amount) ->
-        Default_parameters.make_bootstrap_account (pkh, pk, amount))
+      (fun (Account.{pk; pkh; _}, amount, delegate_to) ->
+        Default_parameters.make_bootstrap_account (pkh, pk, amount, delegate_to))
       initial_accounts
   in
   let parameters =
@@ -392,7 +392,9 @@ let genesis_with_parameters parameters =
     context;
   }
 
-let validate_initial_accounts (initial_accounts : (Account.t * Tez.t) list)
+let validate_initial_accounts
+    (initial_accounts :
+      (Account.t * Tez.t * Signature.Public_key_hash.t option) list)
     tokens_per_roll =
   if initial_accounts = [] then
     Stdlib.failwith "Must have one account with a roll to bake" ;
@@ -400,7 +402,7 @@ let validate_initial_accounts (initial_accounts : (Account.t * Tez.t) list)
   Lwt.catch
     (fun () ->
       List.fold_left_es
-        (fun acc (_, amount) ->
+        (fun acc (_, amount, _) ->
           Environment.wrap_tzresult @@ Tez.( +? ) acc amount >>?= fun acc ->
           if acc >= tokens_per_roll then raise Exit else return acc)
         Tez.zero
@@ -496,7 +498,7 @@ let prepare_initial_context_params ?consensus_threshold ?min_proposal_quorum
   Lwt.catch
     (fun () ->
       List.fold_left_es
-        (fun acc (_, amount) ->
+        (fun acc (_, amount, _) ->
           Environment.wrap_tzresult @@ Tez.( +? ) acc amount >>?= fun acc ->
           if acc >= constants.tokens_per_roll then raise Exit else return acc)
         Tez.zero
@@ -538,7 +540,8 @@ let genesis ?commitments ?consensus_threshold ?min_proposal_quorum
     ?baking_reward_fixed_portion ?origination_size ?blocks_per_cycle
     ?cycles_per_voting_period ?tx_rollup_enable ?tx_rollup_sunset_level
     ?tx_rollup_origination_size ?sc_rollup_enable
-    (initial_accounts : (Account.t * Tez.t) list) =
+    (initial_accounts :
+      (Account.t * Tez.t * Signature.Public_key_hash.t option) list) =
   prepare_initial_context_params
     ?consensus_threshold
     ?min_proposal_quorum
@@ -579,7 +582,8 @@ let genesis ?commitments ?consensus_threshold ?min_proposal_quorum
   }
 
 let alpha_context ?commitments ?min_proposal_quorum
-    (initial_accounts : (Account.t * Tez.t) list) =
+    (initial_accounts :
+      (Account.t * Tez.t * Signature.Public_key_hash.t option) list) =
   prepare_initial_context_params ?min_proposal_quorum initial_accounts
   >>=? fun (constants, shell, _hash) ->
   initial_alpha_context ?commitments constants shell initial_accounts
diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli
index 0c2f2fc4ec41..d19bece55353 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/block.mli
+++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli
@@ -125,7 +125,7 @@ val genesis :
   ?tx_rollup_sunset_level:int32 ->
   ?tx_rollup_origination_size:int ->
   ?sc_rollup_enable:bool ->
-  (Account.t * Tez.tez) list ->
+  (Account.t * Tez.tez * Signature.Public_key_hash.t option) list ->
   block tzresult Lwt.t
 
 val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t
@@ -137,7 +137,7 @@ val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t
 val alpha_context :
   ?commitments:Commitment.t list ->
   ?min_proposal_quorum:int32 ->
-  (Account.t * Tez.tez) list ->
+  (Account.t * Tez.tez * Signature.Public_key_hash.t option) list ->
   Alpha_context.t tzresult Lwt.t
 
 (**
@@ -266,7 +266,7 @@ val prepare_initial_context_params :
   ?tx_rollup_sunset_level:int32 ->
   ?tx_rollup_origination_size:int ->
   ?sc_rollup_enable:bool ->
-  (Account.t * Tez.t) list ->
+  (Account.t * Tez.t * Signature.Public_key_hash.t option) list ->
   ( Constants.Parametric.t * Block_header.shell_header * Block_hash.t,
     tztrace )
   result
diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml
index d4649b4d09a0..cc4b615119c9 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/context.ml
+++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml
@@ -394,16 +394,23 @@ let tup_get : type a r. (a, r) tup -> a list -> r =
   | _ -> assert false
 
 let init_gen tup ?rng_state ?commitments ?(initial_balances = [])
-    ?consensus_threshold ?min_proposal_quorum ?bootstrap_contracts ?level
-    ?cost_per_byte ?liquidity_baking_subsidy ?endorsing_reward_per_slot
-    ?baking_reward_bonus_per_slot ?baking_reward_fixed_portion ?origination_size
-    ?blocks_per_cycle ?cycles_per_voting_period ?tx_rollup_enable
-    ?tx_rollup_sunset_level ?tx_rollup_origination_size ?sc_rollup_enable () =
+    ?consensus_threshold ?min_proposal_quorum ?bootstrap_contracts
+    ?bootstrap_delegations ?level ?cost_per_byte ?liquidity_baking_subsidy
+    ?endorsing_reward_per_slot ?baking_reward_bonus_per_slot
+    ?baking_reward_fixed_portion ?origination_size ?blocks_per_cycle
+    ?cycles_per_voting_period ?tx_rollup_enable ?tx_rollup_sunset_level
+    ?tx_rollup_origination_size ?sc_rollup_enable () =
   let n = tup_n tup in
-  let accounts = Account.generate_accounts ?rng_state ~initial_balances n in
+  let accounts =
+    Account.generate_accounts
+      ?rng_state
+      ~initial_balances
+      ?bootstrap_delegations
+      n
+  in
   let contracts =
     List.map
-      (fun (a, _) -> Alpha_context.Contract.Implicit Account.(a.pkh))
+      (fun (a, _, _) -> Alpha_context.Contract.Implicit Account.(a.pkh))
       accounts
   in
   Block.genesis
@@ -440,15 +447,15 @@ let init_with_constants_gen tup constants =
   let accounts = Account.generate_accounts n in
   let contracts =
     List.map
-      (fun (a, _) -> Alpha_context.Contract.Implicit Account.(a.pkh))
+      (fun (a, _, _) -> Alpha_context.Contract.Implicit Account.(a.pkh))
       accounts
   in
   let open Tezos_protocol_alpha_parameters in
   let bootstrap_accounts =
     List.map
-      (fun (acc, tez) ->
+      (fun (acc, tez, delegate_to) ->
         Default_parameters.make_bootstrap_account
-          (acc.Account.pkh, acc.Account.pk, tez))
+          (acc.Account.pkh, acc.Account.pk, tez, delegate_to))
       accounts
   in
   let parameters =
@@ -470,8 +477,8 @@ let default_raw_context () =
   let open Tezos_protocol_alpha_parameters in
   let bootstrap_accounts =
     List.map
-      (fun (Account.{pk; pkh; _}, amount) ->
-        Default_parameters.make_bootstrap_account (pkh, pk, amount))
+      (fun (Account.{pk; pkh; _}, amount, delegate_to) ->
+        Default_parameters.make_bootstrap_account (pkh, pk, amount, delegate_to))
       initial_accounts
   in
   Block.prepare_initial_context_params initial_accounts
diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli
index 138d32c4a063..984205b4724d 100644
--- a/src/proto_alpha/lib_protocol/test/helpers/context.mli
+++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli
@@ -226,6 +226,8 @@ type 'accounts init :=
   ?consensus_threshold:int ->
   ?min_proposal_quorum:int32 ->
   ?bootstrap_contracts:Parameters.bootstrap_contract list ->
+  ?bootstrap_delegations:
+    (Signature.Public_key_hash.t * Signature.Public_key_hash.t) list ->
   ?level:int32 ->
   ?cost_per_byte:Tez.t ->
   ?liquidity_baking_subsidy:Tez.t ->
diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml
index f10301f8eae7..6a6bd357fc3c 100644
--- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml
+++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml
@@ -342,9 +342,9 @@ let test_committee_sampling () =
     in
     let bootstrap_accounts =
       List.map
-        (fun (acc, tez) ->
+        (fun (acc, tez, delegate_to) ->
           Default_parameters.make_bootstrap_account
-            (acc.Account.pkh, acc.Account.pk, tez))
+            (acc.Account.pkh, acc.Account.pk, tez, delegate_to))
         accounts
     in
     let consensus_committee_size = max_round in
@@ -368,7 +368,7 @@ let test_committee_sampling () =
     >|=? fun bakers ->
     let stats = Stdlib.Hashtbl.create 10 in
     Stdlib.List.iter2
-      (fun (acc, _) bounds ->
+      (fun (acc, _, _) bounds ->
         Stdlib.Hashtbl.add stats acc.Account.pkh (bounds, 0))
       accounts
       bounds ;
diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml
index e9bf056d429b..41299b62d68a 100644
--- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml
+++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml
@@ -284,6 +284,34 @@ let undelegated_originated_bootstrap_contract () =
   | None -> return_unit
   | Some _ -> failwith "Bootstrap contract should be undelegated (%s)" __LOC__
 
+let delegated_implicit_bootstrap_contract () =
+  (* These values are fixed because we use a fixed RNG seed. *)
+  let from_pkh =
+    Signature.Public_key_hash.of_b58check_exn
+      "tz1TDZG4vFoA2xutZMYauUnS4HVucnAGQSpZ"
+  in
+  let to_pkh =
+    Signature.Public_key_hash.of_b58check_exn
+      "tz1MBWU1WkszFfkEER2pgn4ATKXE9ng7x1sR"
+  in
+  let bootstrap_delegations = [(from_pkh, to_pkh)] in
+  let rng_state = Random.State.make [|0|] in
+  Context.init2 ~rng_state ~bootstrap_delegations ()
+  >>=? fun (b, (contract1, _contract2)) ->
+  Block.bake b >>=? fun b ->
+  Context.Contract.delegate_opt (B b) contract1 >>=? fun delegate0 ->
+  (match delegate0 with
+  | Some contract when contract = to_pkh -> return_unit
+  | Some _ | None ->
+      failwith "Bootstrap contract should be delegated (%s)" __LOC__)
+  >>=? fun () ->
+  (* Test delegation amount *)
+  Incremental.begin_construction b >>=? fun i ->
+  let ctxt = Incremental.alpha_ctxt i in
+  Delegate.delegated_balance ctxt to_pkh >>= fun result ->
+  Lwt.return @@ Environment.wrap_tzresult result >>=? fun amount ->
+  Assert.equal_tez ~loc:__LOC__ amount (Tez.of_mutez_exn 4000000000000L)
+
 let tests_bootstrap_contracts =
   [
     Tztest.tztest
@@ -353,6 +381,10 @@ let tests_bootstrap_contracts =
       "originated bootstrap contract can be undelegated"
       `Quick
       undelegated_originated_bootstrap_contract;
+    Tztest.tztest
+      "originated bootstrap contract can be delegated"
+      `Quick
+      delegated_implicit_bootstrap_contract;
   ]
 
 (*****************************************************************************)
diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_sapling.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_sapling.ml
index e87874738316..01dc79cbeaba 100644
--- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_sapling.ml
+++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_sapling.ml
@@ -645,7 +645,7 @@ module Interpreter_tests = struct
     (let pkh = Context.Contract.pkh src1 in
      (* dummy context used only for pack_data *)
      Block.alpha_context
-       [(Account.activator_account, Tez.of_mutez_exn 100_000_000_000L)]
+       [(Account.activator_account, Tez.of_mutez_exn 100_000_000_000L, None)]
      >>=? fun ctx ->
      Script_ir_translator.pack_data ctx Script_typed_ir.key_hash_t pkh >>= wrap)
     >>=? fun (bound_data, _) ->
diff --git a/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml b/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml
index dc8e58f9fdb2..27f5394c700a 100644
--- a/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml
+++ b/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml
@@ -66,7 +66,7 @@ let create_context () =
   let accounts = Account.generate_accounts 1 in
   Block.alpha_context accounts >>=? fun ctxt ->
   match accounts with
-  | [({pkh; _}, _)] -> return (ctxt, pkh)
+  | [({pkh; _}, _, _)] -> return (ctxt, pkh)
   | _ -> (* Exactly one account has been generated. *) assert false
 
 (** Creates a context, a user contract, and a delegate.
diff --git a/src/proto_alpha/lib_protocol/test/integration/test_token.ml b/src/proto_alpha/lib_protocol/test/integration/test_token.ml
index 71b13ab8ccff..d12451168919 100644
--- a/src/proto_alpha/lib_protocol/test/integration/test_token.ml
+++ b/src/proto_alpha/lib_protocol/test/integration/test_token.ml
@@ -44,7 +44,7 @@ let create_context () =
   let accounts = Account.generate_accounts 1 in
   Block.alpha_context accounts >>=? fun ctxt ->
   match accounts with
-  | [({pkh; _}, _)] -> return (ctxt, pkh)
+  | [({pkh; _}, _, _)] -> return (ctxt, pkh)
   | _ -> (* Exactly one account has been generated. *) assert false
 
 let random_amount () =
-- 
GitLab