anchor.diff:  immutable(_, _New, undefined, _) ->
       true;
   immutable(update, New, Existing, {_Good, Bad}) ->
  -    %% If data type and allow mult and are in New they must match what is in existing
  -    %% or be in Bad
  -    case {proplists:get_value(datatype, New), proplists:get_value(allow_mult, New),
  -          proplists:get_value(datatype, Existing)} of
  -        {undefined, undefined, _Meh} ->
  +    case proplists:get_value(consistent, Existing) of
  +        Consistent when Consistent =:= false orelse
  +                        Consistent =:= undefined ->
  +            %% not an existing consistent type (or bucket) so validate it
  +            %% as a datatype (immutable_dt also covers the case where it was
  +            %% not a datatype, yes i know this is kind of wierd when you read the
  +            %% test, sorry...)
  +            NewDT = proplists:get_value(datatype, New),
  +            NewAM = proplists:get_value(allow_mult, New),
  +            ExistingDT = proplists:get_value(datatype, Existing),
  +            immutable_dt(NewDT, NewAM, ExistingDT, Bad);
  +        true ->
  +            %% existing type (or bucket) is consistent
  +            immutable_consistent(New, Existing, Bad)
  +    end.
  +
  +immutable_consistent(New, Existing, Bad) ->
  +    NewCS = proplists:get_value(consistent, New),
  +    OldN = proplists:get_value(n_val, Existing),
  +    NewN = proplists:get_value(n_val, New),
  +    immutable_consistent(NewCS, OldN, NewN, Bad).
  +
  +%% Consistent properties must remain consistent and
  +%% the n_val must not change. This function assumes the
  +%% existing value for consistent is true.
  +immutable_consistent(undefined, _N, undefined, _Bad) ->
  +    %% consistent and n_val not modified
  +    true;
  +immutable_consistent(true, _N, undefined, _Bad) ->
  +    %% consistent still set to true and n_val not modified
  +    true;
  +immutable_consistent(Consistent, _N, _N, _Bad) when Consistent =:= undefined orelse
  +                                                    Consistent =:= true ->
  +    %% consistent not modified or still set to true and n_val
  +    %% modified but set to same value
  +    true;
  +immutable_consistent(Consistent, _OldN, _NewN, Bad) when Consistent =:= undefined orelse
  +                                                         Consistent =:= true ->
  +    %% consistent not modified or still set to true but n_val modified
  +    has_n_val(Bad);
  +immutable_consistent(_Consistent, OldN, NewN, Bad) when OldN =:= NewN orelse
  +                                                        NewN =:= undefined ->
  +    %% consistent modified but set to invalid value or false, n_val not modified
  +    %% or set to existing value
  +    has_consistent(Bad);
  +immutable_consistent(_Consistent, _OldN, _NewN, Bad) ->
  +    has_consistent(Bad) andalso has_n_val(Bad).
  +
  +
  +%% If data type and allow mult and are in New they must match what is in existing
  +%% or be in Bad
  +immutable_dt(undefined, undefined, _Meh1, _Bad) ->
  +    %% datatype and allow_mult are not being modified, so its valid
  +    true;
  +immutable_dt(undefined, _, undefined, _Bad) ->
  +    %% data type not in new or existing, so its valid
  +    true;
  +immutable_dt(_Datatype, undefined, _Datatype, _Bad) ->
  +    %% data types from new and existing match and allow mult not modified, valid
  +    true;
  +immutable_dt(_Datatype, true, _Datatype, _Bad) ->
  +  %% data type from new and existing match and allow mult still set to true, valid
  +    true;
  +immutable_dt(undefined, true, _Datatype, _Bad) ->
  +    %% data type not modified and allow_mult still set to true, vald
  +    true;
  +immutable_dt(_Datatype, undefined, _Datatype2, Bad) ->
  +    %% data types do not match, allow_mult not modified
  +    has_datatype(Bad);
  +immutable_dt(_Datatype, true, _Datatype2, Bad) ->
  +    %% data types do not match, allow_mult still set to true
  +    has_datatype(Bad);
  +immutable_dt(_Datatype, false, undefined, Bad) ->
  +    %% datatype defined when it wasn't before
  +    has_datatype(Bad);
  +immutable_dt(_Datatype, false, _Datatype, Bad) ->
  +    %% attempt to set allow_mult to false when data type set is invalid, datatype not modified
  +    has_allow_mult(Bad);
  +immutable_dt(undefined, false, _Meh, Bad) ->
  +    %% data type not modified but exists and allow_mult set to false is invalid
  +    has_allow_mult(Bad);
  +immutable_dt(_Datatype, false, _Datatype2, Bad) ->
  +    %% data type changed and allow mult modified to be false, both are invalid
  +    has_allow_mult(Bad) andalso has_datatype(Bad);
  +immutable_dt(undefined, _, _Datatype, Bad) ->
  +    %% datatype not modified but allow_mult is invalid
  +    has_allow_mult(Bad);
  +immutable_dt(_Datatype, _, _Datatype, Bad) ->
  +    %% allow mult is invalid but data types still match
  +    has_allow_mult(Bad);
  +immutable_dt(_, _, _, Bad) ->
  +    %% allow_mult and data type are invalid
  +    has_allow_mult(Bad) andalso has_datatype(Bad).
  +
  +only_create_if_valid({Good, Bad}, New) ->
  +    DT = proplists:get_value(datatype, New),
  +    AM = proplists:get_value(allow_mult, New),
  +    CS = proplists:get_value(consistent, New),
  +    case {DT, AM, CS} of
  +        %% if consistent or datatype properties are not defined then properties should be
  +        %% valid since no other properties generated can be in valid
  +        {undefined, _AllowMult, Consistent} when Consistent =:= false orelse
  +                                                 Consistent =:= undefined ->
               true;
  -        {_Datatype, undefined, _Datatype} ->
  -            true;
  -        {_Datatype, true, _Datatype} ->
  -            true;
  -        {_Datatype, undefined, _Datatype2} ->
  -            has_datatype(Bad);
  -        {_Datatype, true, _Datatype2} ->
  -            has_datatype(Bad);
  -        {_Datatype, false, undefined} ->
  -            has_datatype(Bad);
  -        {_Datatype, false, _Datatype} ->
  -            has_allow_mult(Bad);
  -        {undefined, false, _Meh} ->
  -            has_allow_mult(Bad);
  -        {_Datatype, false, _Datatype2} ->
  -            has_allow_mult(Bad) andalso has_datatype(Bad);
  -        {_Datatype, _, _Datatype} ->
  -            has_allow_mult(Bad);
  -        {_, _, _} ->
  -            has_allow_mult(Bad) andalso has_datatype(Bad)
  -    end.
  -
  -only_create_if_valid({Good, Bad}, New) ->
  -    case {proplists:get_value(datatype, New), proplists:get_value(allow_mult, New)} of
  -        {undefined, _AllowMult} ->
  -            true;
  -        {Datatype, true} ->
  +        %% if datatype is defined, its not a consistent type and allow_mult=true
  +        %% then the datatype must be valid
  +        {Datatype, true, Consistent} when Consistent =:= false orelse
  +                                          Consistent =:= undefined ->
               case lists:member(riak_kv_crdt:to_mod(Datatype), ?V2_TOP_LEVEL_TYPES) of
                   true ->
                       has_datatype(Good) andalso has_allow_mult(Good);
                   false ->
                       has_datatype(Bad) andalso has_allow_mult(Good)
               end;
  -        {Datatype, _} ->
  +        %% if the datatype is defined, the type is not consistent and allow_mult is false
  +        %% then allow_mult should be in the Bad list and the datatype may be depending on if it
  +        %% is valid
  +        {Datatype, _, Consistent} when Consistent =:= false orelse
  +                                       Consistent =:= undefined->
               case lists:member(riak_kv_crdt:to_mod(Datatype), ?V2_TOP_LEVEL_TYPES) of
                   true ->
                       has_allow_mult(Bad) andalso has_datatype(Good);
                   false ->
                       has_datatype(Bad) andalso has_allow_mult(Bad)
  -            end
  +            end;
  +        %% the type is consistent, whether it has a datatype or allow_mult set is irrelevant (for now
  +        %% at least)
  +        {_, _, true} ->
  +            has_consistent(Good);
  +        %% the type was not inconsistent (explicitly or implicitly) but the value is invalid
  +        {_, _, _Consistent} ->
  +            has_consistent(Bad)
       end.
   
   has_datatype(Props) ->
  
positive.code:     end;
  coerce_bool(_) ->
      error.
  
  %% @private riak datatype support requires a bucket type of `datatype'
  %% and `allow_mult' set to `true'. These function enforces those
  
negative.code:                        io:format("Bucket ~p~n", [Bucket]),
                         io:format("Existing ~p~n", [Existing]),
                         io:format("New ~p~n", [New]),
                         io:format("Result ~p~n", [Result]),
                         io:format("{has_datatype, valid_datatype, allow_mult, has_consistent, valid_consistent}~n"),
                         io:format("{~p,~p,~p,~p,~p}~n~n",
                                   [has_datatype(New), valid_datatype(New), allow_mult(New), has_consistent(New), valid_consistent(New)])
                     end,
                     collect(with_title("{has_datatype, valid_datatype, allow_mult, has_consistent, valid_consistent}"),
                             {has_datatype(New), valid_datatype(New), allow_mult(New), has_consistent(New), valid_consistent(New)},
                             only_create_if_valid(Result, New)))
              end).
  
  %% As of 2.0pre? validate/4 must merge the new and existing props,
  %% verify that.
  prop_merges() ->
      ?FORALL({Bucket, Existing0, New}, {gen_bucket(update, any),
                                        gen_existing(), gen_new(update)},
              begin
                  %% ensure default buckets are not marked consistent since that is invalid
                  Existing = case default_bucket(Bucket) of
                                 true -> lists:keydelete(consistent, 1, Existing0);
                                 false -> Existing0
                             end,
                  Result={Good, _Bad} = validate(update, Bucket, Existing, New),
  
                  DefaultBucket = default_bucket(Bucket),
                  HasAllowMult = has_allow_mult(New),
                  AllowMult = allow_mult(New),
                  HasDatatype = has_datatype(Existing),
                  NValChanged = n_val_changed(Existing, New),
                  IsConsistent = is_consistent(Existing),
                  NewConsistent = proplists:get_value(consistent, New),
                  Expected = case {DefaultBucket, HasAllowMult, AllowMult, HasDatatype,
                                   NValChanged, IsConsistent, NewConsistent} of
                                 %% default bucket, attempted to change consistent to invalid value
                                 %% allow_mult may be invalid too
                                 {true,_, Mult, _, _, false, notvalid} ->
                                     maybe_bad_mult(Mult, merge(lists:keydelete(consistent, 1, New), Existing));
                                 %% default bucket, attempted to change consistent to true
                                 %% allow_mult may be invalid too
                                 {true, _, Mult, _, _, false, true} ->
                                     maybe_bad_mult(Mult, merge(lists:keydelete(consistent, 1, New), Existing));
                                 %% all valid for default type buckets
                                 {true, _, Mult,  _, _, _, _} when Mult /= error ->
                                     merge(New, Existing);
                                 %% default bucket: allow mult is invalid
                                 {true, true, _, _, _, _, _} ->
                                     maybe_bad_mult(error, merge(New, Existing));
  
                                 %% typed bucket, allow mult changed but not consistent or data type
                                 {false, true, Mult,  false, _, false, _} when Mult /= error ->
                                     %% the n_val is the only valid change we generate in this case. can't change
                                     %% data type or consistent peroperty
                                     NVal = proplists:get_value(n_val, New, proplists:get_value(n_val, Existing)),
                                     merge([proplists:lookup(allow_mult, New), {n_val, NVal}], Existing);
                                 %% typed bucket, allow_mult change is invalid. n_val has changed. not a datatype or
                                 %% consistent
                                 {false, true, error, false, true, false, _} ->
                                     merge([proplists:lookup(n_val, New)], Existing);
                                 %% typed bucket, allow_mult change is invalid and n_val hasn't changed
                                 {false, true, error, false, false, false, _} ->
                                     Existing;
                                 %% typed bucket, strongly-consistent, both n_val and consistent value are invalid changes
                                 {false, _, Mult,_,true,true,false} ->
                                     maybe_bad_mult(Mult,
                                                    merge(lists:keydelete(consistent, 1, lists:keydelete(n_val, 1, New)), Existing));
                                 %% typed bucket, strongly-consistent, both n_val and consistent value are invalid changes
                                 {false, _, Mult,_,true,true,notvalid} ->
                                     maybe_bad_mult(Mult,
                                                    merge(lists:keydelete(consistent, 1, lists:keydelete(n_val, 1, New)), Existing));
                                 %% typed bucket, strongly-consistent, n_val change is invalid
                                 {false, _, Mult,_,true,true,_} ->
                                     maybe_bad_mult(Mult, merge(lists:keydelete(n_val, 1, New), Existing));
                                 %% typed bucket, strongly-consistent, consistent value change is invalid
                                 {false, _, Mult, _, _, true, false} ->
                                     maybe_bad_mult(Mult, merge(lists:keydelete(consistent, 1, New), Existing));
                                 %% typed bucket, strongly-consistent, consistent value change is invalid
                                 {false, _, Mult, _, _, true, notvalid} ->
                                     maybe_bad_mult(Mult, merge(lists:keydelete(consistent, 1, New), Existing));
                                 %% typed bucket, strongly-consistent, all good (except maybe allow_mult)
                                 {false, _, Mult, _, _, true, _} ->
                                     maybe_bad_mult(Mult, merge(New, Existing));
                                 %% typed bucket, strongly-consistent, all good (except maybe allow_mult)
                                 {false, true, _Mult, true,_, _, _} ->
                                     NVal = proplists:get_value(n_val, New, proplists:get_value(n_val, Existing)),
                                     merge([{n_val, NVal}], Existing);
                                 %% typed bucket, bucket not strongly consistent or a data type, all valid
                                 {false,_,_,_,_,false,_} ->
                                     merge(New, Existing)
                             end,
  
                  ?WHENFAIL(
  