From f8d8c4d6e923d4d03f91feb396ac158ac3fcac9e Mon Sep 17 00:00:00 2001
From: Jun FURUSE <jun.furuse@dailambda.jp>
Date: Fri, 7 Dec 2018 16:15:48 +0000
Subject: [PATCH] Client: check that proposals are already injected

---
 src/bin_client/test/test_voting.sh            | 76 ++++++++++++-------
 .../client_proto_context_commands.ml          | 18 +++++
 2 files changed, 67 insertions(+), 27 deletions(-)

diff --git a/src/bin_client/test/test_voting.sh b/src/bin_client/test/test_voting.sh
index 1306a965e..fd915458b 100755
--- a/src/bin_client/test/test_voting.sh
+++ b/src/bin_client/test/test_voting.sh
@@ -8,12 +8,13 @@ set -o pipefail
 test_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)")"
 source $test_dir/test_lib.inc.sh "$@"
 
-# Prepare a config with shorter blocks_per_voting_period
-temp=`mktemp`
-sed -e 's/"blocks_per_voting_period" : [0-9]*/"blocks_per_voting_period" : 4/' $parameters_file > $temp
-parameters_file=$temp
+# Prepare a config with a shorter blocks_per_voting_period
+tempdir=`mktemp -d`
+sed -e 's/"blocks_per_voting_period" : [0-9]*/"blocks_per_voting_period" : 4/' $parameters_file > $tempdir/parameters.json
+parameters_file=$tempdir/parameters.json
 echo params=${parameters_file}
 
+# Start a node
 start_node 1
 activate_alpha
 
@@ -26,6 +27,7 @@ echo $res
     || { echo "strange voting_period_position" ; exit 1 ; }
 [ `echo $res | jq .voting_period_remaining` = '3' ] \
     || { echo "strange voting_period_remaining" ; exit 1 ; }
+echo Checking the bug of the empty listing in the first voting period...
 [ `echo $res | jq .listings` = '[]' ] \
     || { echo "empty listings bug was fixed?!" ; exit 1 ; }
 
@@ -40,6 +42,7 @@ res=`$client show votes`
 bake # pos=3
 bake # new period, pos=0
 
+echo 'Checking the current period = proposal with non empty listings'
 res=`$client show votes`
 [ `echo $res | jq .voting_period_position` = '0' ] \
     || { echo "strange voting_period_position" ; exit 1 ; }
@@ -48,14 +51,33 @@ res=`$client show votes`
 [ "`echo $res | jq .listings`" != '[]' ] \
     || { echo "strange listings" ; exit 1 ; }
 
-proto1='ProtoBetaBetaBetaBetaBetaBetaBetaBetaBet11111a5ug96'
-proto2='Proto222222222222222222222222222222222225b7e3dV844j'
-proto3='Proto33333333333333333333333333333333333c6379eVysnU'
+# Prepare 3 different protocol sources
 
-$client submit proposals for bootstrap1 $proto1
-$client submit proposals for bootstrap2 $proto1 $proto2
-$client submit proposals for bootstrap3 $proto2
-$client submit proposals for bootstrap4 $proto3
+echo 'Injecting protocols...'
+
+cp -r demo $tempdir/proto1
+$admin_client inject protocol $tempdir/proto1
+
+cp -r demo $tempdir/proto2
+echo '(* 2 *)' >> $tempdir/proto2/main.ml
+$admin_client inject protocol $tempdir/proto2
+
+cp -r demo $tempdir/proto3
+echo '(* 3 *)' >> $tempdir/proto3/main.ml
+$admin_client inject protocol $tempdir/proto3
+
+proto_str=`$admin_client list protocols | head -3` # assuming new protocols listed first
+echo New protocols: $proto_str
+proto=($proto_str)
+
+# Proposals
+
+echo 'Proposal voting...'
+
+$client submit proposals for bootstrap1 ${proto[0]}
+$client submit proposals for bootstrap2 ${proto[0]} ${proto[1]}
+$client submit proposals for bootstrap3 ${proto[1]}
+$client submit proposals for bootstrap4 ${proto[2]}
 
 bake
 
@@ -65,15 +87,15 @@ res=`$client show votes`
 
 bake # pos=2
 
-echo Breaking the tie
+echo 'Breaking the tie'
 
-$client submit proposals for bootstrap3 $proto1 # To make $proto1 win
+$client submit proposals for bootstrap4 ${proto[1]} # To make ${proto[1]} win
 $client show votes
 
 bake # pos=3
 bake # new period! pos=0
 
-echo Proposal should be done
+echo The phase must be testing_vote...
 res=`$client show votes`
 echo $res
 [ `echo $res | jq .voting_period_position` = '0' ] \
@@ -84,20 +106,20 @@ echo $res
     || { echo "strange current_period_kind" ; exit 1 ; }
 [ "`echo $res | jq .listings`" != '[]' ] \
     || { echo "strange listings" ; exit 1 ; }
-[ `echo $res | jq .current_proposal` = '"'$proto1'"' ] \
+[ `echo $res | jq .current_proposal` = '"'${proto[1]}'"' ] \
     || { echo "strange current_proposal" ; exit 1 ; }
  
 echo Ballots 1
-$client submit ballot for bootstrap1 $proto1 yay
-$client submit ballot for bootstrap2 $proto1 yay
-$client submit ballot for bootstrap3 $proto1 yay
-$client submit ballot for bootstrap4 $proto1 yay
+$client submit ballot for bootstrap1 ${proto[1]} yay
+$client submit ballot for bootstrap2 ${proto[1]} yay
+$client submit ballot for bootstrap3 ${proto[1]} yay
+$client submit ballot for bootstrap4 ${proto[1]} yay
  
 bake # pos=1
 
 # They cannot change their mind.
 echo "Ballots 2 (should fail)"
-$client submit ballot for bootstrap1 $proto1 yay \
+$client submit ballot for bootstrap1 ${proto[1]} yay \
     && { echo "submit ballot cannot be called twice" ; exit 1 ; }
 
 bake # pos=2
@@ -117,7 +139,7 @@ res=`$client show votes`
     || { echo "strange current_period_kind" ; exit 1 ; }
 [ "`echo $res | jq .listings`" = '[]' ] \
     || { echo "strange listings" ; exit 1 ; }
-[ `echo $res | jq .current_proposal` = '"'$proto1'"' ] \
+[ `echo $res | jq .current_proposal` = '"'${proto[1]}'"' ] \
     || { echo "strange current_proposal" ; exit 1 ; }
 [ `echo $res | jq .ballot_list` = '[]' ] \
     || { echo "strange ballot_list" ; exit 1 ; }
@@ -137,15 +159,15 @@ res=`$client show votes`
     || { echo "strange current_period_kind" ; exit 1 ; }
 [ "`echo $res | jq .listings`" != '[]' ] \
     || { echo "strange listings" ; exit 1 ; }
-[ `echo $res | jq .current_proposal` = '"'$proto1'"' ] \
+[ `echo $res | jq .current_proposal` = '"'${proto[1]}'"' ] \
     || { echo "strange current_proposal" ; exit 1 ; }
 [ `echo $res | jq .ballot_list` = '[]' ] \
     || { echo "strange ballot_list" ; exit 1 ; }
  
-$client submit ballot for bootstrap1 $proto1 yay
-$client submit ballot for bootstrap2 $proto1 yay
-$client submit ballot for bootstrap3 $proto1 yay
-$client submit ballot for bootstrap4 $proto1 nay # not to promote
+$client submit ballot for bootstrap1 ${proto[1]} yay
+$client submit ballot for bootstrap2 ${proto[1]} yay
+$client submit ballot for bootstrap3 ${proto[1]} yay
+$client submit ballot for bootstrap4 ${proto[1]} nay # not to promote
 
 bake # pos=1
 bake # pos=2
@@ -155,7 +177,7 @@ $client show votes
 
 bake # new period pos=0
  
-echo 'Promotion vote should be done (negatively)'
+echo 'Promotion vote should be over now negatively'
 res=`$client show votes`
 [ `echo $res | jq .voting_period_position` = '0' ] \
     || { echo "strange voting_period_position" ; exit 1 ; }
diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml
index 0a2336b39..74d9abbdf 100644
--- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml
+++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml
@@ -659,6 +659,24 @@ let commands version () =
                                 | Some hash -> return hash)))
       )
       (fun () (_name, source) proposals cctxt ->
+         Shell_services.Protocol.list cctxt >>=? fun known_protos ->
+         let check_proposals proposals =
+           let n = List.length proposals in
+           if n = 0 then generic_error "Empty proposal"
+           else if n > Constants.fixed.max_proposals_per_delegate then
+             generic_error "Too many proposals"
+           else
+             (* Why we do not have Error_monad.iter ? *)
+             let rec iter f = function
+               | [] -> ok ()
+               | p::ps -> f p >>? fun () -> iter f ps
+             in
+             iter (fun p -> 
+                 if List.mem p known_protos then ok ()
+                 else generic_error "Protocol %a is not injected in the node" Protocol_hash.pp p)
+               proposals
+         in
+         Lwt.return (check_proposals proposals) >>=? fun () ->
          Client_proto_context.get_manager
            cctxt ~chain:`Main ~block:cctxt#block
            source >>=? fun (_src_name, src_pkh, _src_pk, src_sk) ->