anchor.diff:  
   %% NOTE: This protocol doesn't cover durability nor recovery. It's merely
   %% here for demonstration purposes.
  +%% TODO: Handle abort message at participants.
  +%% TODO: Handle durability at participants.
   
   -module(lampson_2pc).
   
  
positive.code:     %% Store transaction.
      true = ets:insert(?MODULE, {Id, Transaction}),
  
      %% Send prepare message to all participants including ourself.
      lists:foreach(fun(N) ->
          lager:info("~p: sending prepare message to node ~p: ~p", [node(), N, Message]),
  
negative.code: 
  %% @private
  %% Incoming messages.
  handle_info({timeout, Id}, State) ->
      Manager = manager(),
  
      %% Find transaction record.
      case ets:lookup(?MODULE, Id) of 
          [{_Id, #transaction{participants=Participants, from=From, server_ref=ServerRef, message=Message} = Transaction}] ->
              lager:info("Received timeout for transaction id ~p", [Id]),
  
              %% Reply to caller.
              lager:info("Aborting transaction: ~p", [Id]),
              gen_server:reply(From, error),
  
              %% Update local state.
              true = ets:insert(?MODULE, {Id, Transaction#transaction{status=aborting}}),
  
              %% Send notification to abort.
              MyNode = partisan_peer_service_manager:mynode(),
              lists:foreach(fun(N) ->
                  lager:info("~p: sending abort message to node ~p: ~p", [node(), N, Id]),
                  Manager:forward_message(N, ?GOSSIP_CHANNEL, ?MODULE, {abort, MyNode, Id, ServerRef, Message}, [])
              end, membership(Participants));
          [] ->
              lager:error("Notification for timeout message but no transaction found!")
      end,
  
      {noreply, State};
  handle_info({ack, FromNode, Id}, State) ->
      %% Find transaction record.
      case ets:lookup(?MODULE, Id) of 
  