Skip to content

Commit

Permalink
Fix Flash failure on CI test
Browse files Browse the repository at this point in the history
The unittests in `agora.test.Flash` fails often on CI because there is
a timing issue. Unittests expect `update_tx`s not to be sent as soon as
a block is externalized when the `allow_publish` is set to `false`. But
the `update_tx` is sent as soon as the `allow_publish` is to set `true`
by calling `setPublishEnable`, which is not to be supposed to be sent.
  • Loading branch information
linked0 authored and hewison-chris committed Feb 16, 2022
1 parent c4fde63 commit 4544d62
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
20 changes: 13 additions & 7 deletions source/agora/flash/Channel.d
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,6 @@ LOuter: while (1)

public void onUpdateTxExternalized (in Transaction tx, in uint utxo_idx, in bool is_last)
{
this.state = ChannelState.StartedUnilateralClose;
this.onChannelNotify(this.own_pk, this.conf.chan_id, this.state,
ErrorCode.None);

this.last_externalized_update_utxo = UTXO.getHash(tx.hashFull(), utxo_idx);
if (is_last)
{
Expand All @@ -753,7 +749,13 @@ LOuter: while (1)
}
else
{
this.publishUpdateTx(this.channel_updates[$ - 1]);
this.taskman.setTimer(100.msecs,
{
this.publishUpdateTx(this.channel_updates[$ - 1]);
this.state = ChannelState.StartedUnilateralClose;
this.onChannelNotify(this.own_pk, this.conf.chan_id, this.state,
ErrorCode.None, this.height);
});
}
}

Expand Down Expand Up @@ -2221,6 +2223,8 @@ LOuter: while (1)

protected Transaction publishUpdateTx (in UpdatePair update)
{
import agora.utils.PrettyPrinter;

auto update_tx = update.update_tx.serializeFull.deserializeFull!Transaction();
assert(update_tx.inputs.length == 1);
assert(update_tx.outputs.length == 1);
Expand Down Expand Up @@ -2264,9 +2268,11 @@ LOuter: while (1)
update_tx.inputs[idx].unlock = genKeyUnlock(fee_sig);

auto result = this.txPublisher(update_tx);
log.info("{}: Publishing update tx {}: {}. Result: {}",
// NOTE: Added the content of the update tx in the log for debugging
// about the failure on the CI build but will be removed after fixing it.
log.info("{}: Publishing update tx {}: {}. Result: {}. Tx: {}",
this.own_pk.flashPrettify, update.seq_id, update_tx.hashFull().flashPrettify,
result);
result, update_tx.prettify);
return update_tx;
}

Expand Down
28 changes: 22 additions & 6 deletions source/agora/test/Flash.d
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ public interface TestFlashListenerAPI : FlashListenerAPI
/// has succeeded / failed, and return true / false for success
ErrorCode waitUntilNotified (Invoice);

/// wait until we get a notification about the given channel state,
/// and return any associated error codes
ErrorCode waitUntilChannelState (Hash, ChannelState, PublicKey node = PublicKey.init);
/// wait until we get a notification about the given channel state
/// with the specified height and return any associated error codes
ErrorCode waitUntilChannelState (Hash, ChannelState, PublicKey node = PublicKey.init,
Height height = Height(0), bool erase_state = true);

/// Print out the contents of the log
public void printLog ();
Expand Down Expand Up @@ -542,16 +543,24 @@ private class FlashListener : TestFlashListenerAPI
}

public ErrorCode waitUntilChannelState (Hash chan_id, ChannelState state,
PublicKey node = PublicKey.init)
PublicKey node = PublicKey.init, Height height = Height(0),
bool erase_state = true)
{
scope (exit) this.channel_state.remove(chan_id);
// There is no case where we check the state with a specified
// height and no public key.
assert(height == Height(0) || node != PublicKey.init);

scope (exit) if (erase_state) this.channel_state.remove(chan_id);
while (1)
{
if (auto chan_states = chan_id in this.channel_state)
{
if (auto chan_state = node in *chan_states)
if ((*chan_state).state >= state)
{
if ((*chan_state).state >= state &&
(*chan_state).height >= height)
return (*chan_state).error;
}
if (node == PublicKey.init)
{
auto states = chan_states.byValue
Expand Down Expand Up @@ -1925,6 +1934,13 @@ unittest
network.clients[0].postTransaction(update_tx);
assert(!network.clients[0].hasTransactionHash(update_tx.hashFull()));

// wait until all the flash nodes skip publishing `update tx` before
// the `setPublishEnable` is called.
network.listener.waitUntilChannelState(chan_id,
ChannelState.StartedUnilateralClose, WK.Keys.A.address, Height(4), false);
network.listener.waitUntilChannelState(chan_id,
ChannelState.StartedUnilateralClose, WK.Keys.C.address, Height(4));

// allow normal node operation again
alice.setPublishEnable(true);
charlie.setPublishEnable(true);
Expand Down

0 comments on commit 4544d62

Please sign in to comment.