anchor.diff:      }),
       ok = ack_outstanding(MessageId, Mod, Round, Root, From),
       {noreply, State};
  +
   handle_cast({graft, MessageId, Mod, Round, Root, From}, State) ->
       ?LOG_DEBUG("received ~p", [{graft, MessageId, Mod, Round, Root, From}]),
       Result = Mod:graft(MessageId),
       ?LOG_DEBUG("graft(~p): ~p", [MessageId, Result]),
       State1 = handle_graft(Result, MessageId, Mod, Round, Root, From, State),
       {noreply, State1};
  -handle_cast({update, Members}, State=#state{all_members=BroadcastMembers,
  -                                            common_eagers=EagerPeers0,
  -                                            common_lazys=LazyPeers}) ->
  +
  +handle_cast({update, Members}, #state{} = State) ->
       ?LOG_DEBUG("received ~p", [{update, Members}]),
  +
  +    #state{
  +        all_members = BroadcastMembers,
  +        common_eagers = EagerPeers0,
  +        common_lazys = LazyPeers
  +    } = State,
  +
       CurrentMembers = ordsets:from_list(Members),
       New = ordsets:subtract(CurrentMembers, BroadcastMembers),
       Removed = ordsets:subtract(BroadcastMembers, CurrentMembers),
  
positive.code: 
  
  -record(state, {
            %% Initially trees rooted at each node are the same.
            %% Portions of that tree belonging to this node are
            %% shared in this set.
            common_eagers :: ordsets:ordset(node()) | undefined,
  
            %% Initially trees rooted at each node share the same lazy links.
            %% Typically this set will contain a single element. However, it may
            %% contain more in large clusters and may be empty for clusters with
            %% less than three nodes.
            common_lazys  :: ordsets:ordset(node()) | undefined,
  
            %% A mapping of sender node (root of each broadcast tree)
            %% to this node's portion of the tree. Elements are
            %% added to this structure as messages rooted at a node
            %% propogate to this node. Nodes that are never the
            %% root of a message will never have a key added to
            %% `eager_sets'
            eager_sets    :: [{node(), ordsets:ordset(node())}] | undefined,
  
            %% A Mapping of sender node (root of each spanning tree)
            %% to this node's set of lazy peers. Elements are added
            %% to this structure as messages rooted at a node
            %% propogate to this node. Nodes that are never the root
            %% of a message will never have a key added to `lazy_sets'
            lazy_sets     :: [{node(), ordsets:ordset(node())}] | undefined,
  
            %% Set of registered modules that may handle messages that
            %% have been broadcast
            mods          :: [module()],
  
            %% List of outstanding exchanges
            exchanges     :: exchanges(),
  
            %% Set of all known members. Used to determine
            %% which members have joined and left during a membership update
            all_members   :: ordsets:ordset(node()) | undefined,
  
            %% Lazy tick period in milliseconds. On every tick all outstanding
            %% lazy pushes are sent out
            lazy_tick_period :: non_neg_integer(),
  
            %% Exchange tick period in milliseconds that may or may not occur
            exchange_tick_period :: non_neg_integer()
  
           }).
  -type state()           :: #state{}.
  
  %%%===================================================================
  %%% API
  %%%===================================================================
  
  %% @doc Starts the broadcast server on this node. The initial membership list is
  %% fetched from the ring. If the node is a singleton then the initial eager and lazy
  %% sets are empty. If there are two nodes, each will be in the others eager set and the
  %% lazy sets will be empty. When number of members is less than 5, each node will initially
  %% have one other node in its eager set and lazy set. If there are more than five nodes
  %% each node will have at most two other nodes in its eager set and one in its lazy set, initally.
  %% In addition, after the broadcast server is started, a callback is registered with ring_events
  %% to generate membership updates as the ring changes.
  -spec start_link() -> {ok, pid()} | ignore | {error, term()}.
  
  start_link() ->
      LazyTickPeriod = partisan_config:get(
          lazy_tick_period, ?DEFAULT_LAZY_TICK_PERIOD),
      ExchangeTickPeriod = partisan_config:get(
          exchange_tick_period, ?DEFAULT_EXCHANGE_TICK_PERIOD),
      Opts = #{
          lazy_tick_period => LazyTickPeriod,
          exchange_tick_period => ExchangeTickPeriod
  
negative.code:     gen_server:cast(?SERVER, {broadcast, MessageId, Payload, Mod}).
  
  
  %% -----------------------------------------------------------------------------
  %% @doc Notifies broadcast server of membership update
  %% @end
  %% -----------------------------------------------------------------------------
  -spec update([node()]) -> ok.
  
  update(LocalState0) ->
      LocalState = partisan_peer_service:decode(LocalState0),
      gen_server:cast(?SERVER, {update, LocalState}).
  
  
  %% -----------------------------------------------------------------------------
  %% @doc Returns the broadcast servers view of full cluster membership.
  %% Wait indefinitely for a response is returned from the process.
  