Example #1
0
void
Peer::recvPeers(StellarMessage const& msg)
{
    for (auto peer : msg.peers())
    {
        stringstream ip;

        ip << (int)peer.ip[0] << "." << (int)peer.ip[1] << "."
           << (int)peer.ip[2] << "." << (int)peer.ip[3];

        if (peer.port == 0 || peer.port > UINT16_MAX)
        {
            CLOG(DEBUG, "Overlay") << "ignoring peer with bad port";
            continue;
        }
        PeerRecord pr{ip.str(), static_cast<unsigned short>(peer.port),
                      mApp.getClock().now(), peer.numFailures, 1};

        if (pr.isPrivateAddress())
        {
            CLOG(DEBUG, "Overlay") << "ignoring flooded private address";
        }
        else
        {
            pr.insertIfNew(mApp.getDatabase());
        }
    }
}
Example #2
0
void
Peer::sendHello()
{
    LOG(DEBUG) << "Peer::sendHello "
               << "@" << mApp.getConfig().PEER_PORT << " to "
               << mRemoteListeningPort;

    StellarMessage msg;
    msg.type(HELLO);
    msg.hello().protocolVersion = mApp.getConfig().PROTOCOL_VERSION;
    msg.hello().versionStr = mApp.getConfig().VERSION_STR;
    msg.hello().listeningPort = mApp.getConfig().PEER_PORT;
    msg.hello().peerID = mApp.getConfig().PEER_PUBLIC_KEY;

    sendMessage(msg);
}
Example #3
0
std::string
msgSummary(StellarMessage const& m)
{
    xdr::detail::Printer p(0);
    xdr::archive(p, m.type(), nullptr);
    return p.buf_.str() + ":" + hexAbbrev(sha256(xdr::xdr_to_msg(m)));
}
Example #4
0
void
Peer::recvGetSCPState(StellarMessage const& msg)
{
    uint32 seq = msg.getSCPLedgerSeq();
    CLOG(TRACE, "Overlay") << "get SCP State " << seq;
    mApp.getHerder().sendSCPStateToPeer(seq, shared_from_this());
}
Example #5
0
void
Peer::recvTransaction(StellarMessage const& msg)
{
    TransactionFramePtr transaction = TransactionFrame::makeTransactionFromWire(
        mApp.getNetworkID(), msg.transaction());
    if (transaction)
    {
        // add it to our current set
        // and make sure it is valid
        auto recvRes = mApp.getHerder().recvTransaction(transaction);

        if (recvRes == Herder::TX_STATUS_PENDING ||
            recvRes == Herder::TX_STATUS_DUPLICATE)
        {
            // record that this peer sent us this transaction
            mApp.getOverlayManager().recvFloodedMsg(msg, shared_from_this());

            if (recvRes == Herder::TX_STATUS_PENDING)
            {
                // if it's a new transaction, broadcast it
                mApp.getOverlayManager().broadcastMessage(msg);
            }
        }
    }
}
Example #6
0
void
Peer::recvGetTxSet(StellarMessage const& msg)
{
    auto self = shared_from_this();
    if (auto txSet = mApp.getHerder().getTxSet(msg.txSetHash()))
    {
        StellarMessage newMsg;
        newMsg.type(TX_SET);
        txSet->toXDR(newMsg.txSet());

        self->sendMessage(newMsg);
    }
    else
    {
        sendDontHave(TX_SET, msg.txSetHash());
    }
}
Example #7
0
void
Peer::recvDontHave(StellarMessage const& msg)
{
    switch (msg.dontHave().type)
    {
    case TX_SET:
        mApp.getHerder().doesntHaveTxSet(msg.dontHave().reqHash,
                                         shared_from_this());
        break;
    case SCP_QUORUMSET:
        mApp.getHerder().doesntHaveSCPQuorumSet(msg.dontHave().reqHash,
                                                shared_from_this());
        break;
    default:
        break;
    }
}
Example #8
0
void
Peer::recvGetTxSet(StellarMessage const& msg)
{
    TxSetFramePtr txSet = mApp.getHerder().fetchTxSet(msg.txSetHash(), false);
    if (txSet)
    {
        StellarMessage newMsg;
        newMsg.type(TX_SET);
        txSet->toXDR(newMsg.txSet());

        sendMessage(newMsg);
    }
    else
    {
        sendDontHave(TX_SET, msg.txSetHash());
    }
}
Example #9
0
void
Peer::recvGetSCPQuorumSet(StellarMessage const& msg)
{
    SCPQuorumSetPtr qSet =
        mApp.getHerder().fetchSCPQuorumSet(msg.qSetHash(), false);
    if (qSet)
    {
        sendSCPQuorumSet(qSet);
    }
    else
    {
        CLOG(TRACE, "Overlay")
            << "No quorum set: " << hexAbbrev(msg.qSetHash());
        sendDontHave(SCP_QUORUMSET, msg.qSetHash());
        // do we want to ask other people for it?
    }
}
Example #10
0
// copy/pasted from sendHello2
// (to be removed when HELLO is not used)
void
Peer::sendHello()
{
    CLOG(DEBUG, "Overlay") << "Peer::sendHello to " << toString();
    StellarMessage msg;
    msg.type(HELLO);
    Hello& elo = msg.hello();
    elo.ledgerVersion = mApp.getConfig().LEDGER_PROTOCOL_VERSION;
    elo.overlayVersion = mApp.getConfig().OVERLAY_PROTOCOL_VERSION;
    elo.versionStr = mApp.getConfig().VERSION_STR;
    elo.networkID = mApp.getNetworkID();
    elo.listeningPort = mApp.getConfig().PEER_PORT;
    elo.peerID = mApp.getConfig().NODE_SEED.getPublicKey();
    elo.cert = this->getAuthCert();
    elo.nonce = mSendNonce;
    sendMessage(msg);
}
Example #11
0
void
Peer::sendPeers()
{
    // send top 50 peers we know about
    vector<PeerRecord> peerList;
    PeerRecord::loadPeerRecords(mApp.getDatabase(), 50, mApp.getClock().now(),
                                peerList);
    StellarMessage newMsg;
    newMsg.type(PEERS);
    newMsg.peers().resize(xdr::size32(peerList.size()));
    for (size_t n = 0; n < peerList.size(); n++)
    {
        if (!peerList[n].isPrivateAddress())
        {
            peerList[n].toXdr(newMsg.peers()[n]);
        }
    }
    sendMessage(newMsg);
}
Example #12
0
void
Peer::sendMessage(StellarMessage const& msg)
{
    CLOG(TRACE, "Overlay") << "("
                           << binToHex(mApp.getConfig().PEER_PUBLIC_KEY)
                                  .substr(0, 6) << ")send: " << msg.type()
                           << " to : " << hexAbbrev(mPeerID);
    xdr::msg_ptr xdrBytes(xdr::xdr_to_msg(msg));
    this->sendMessage(std::move(xdrBytes));
}
Example #13
0
void
Peer::recvSCPMessage(StellarMessage const& msg)
{
    SCPEnvelope envelope = msg.envelope();
    CLOG(TRACE, "Overlay") << "recvSCPMessage qset: "
                           << binToHex(msg.envelope().statement.quorumSetHash)
                                  .substr(0, 6);

    mApp.getOverlayManager().recvFloodedMsg(msg, shared_from_this());

    auto cb = [msg, this](SCP::EnvelopeState state)
    {
        if (state == SCP::EnvelopeState::VALID)
        {
            mApp.getOverlayManager().broadcastMessage(msg);
        }
    };
    mApp.getHerder().recvSCPEnvelope(envelope, cb);
}
Example #14
0
void
Peer::recvPeers(StellarMessage const& msg)
{
    const uint32 NEW_PEER_WINDOW_SECONDS = 10;

    for (auto const& peer : msg.peers())
    {
        if (peer.port == 0 || peer.port > UINT16_MAX)
        {
            CLOG(WARNING, "Overlay") << "ignoring received peer with bad port "
                                     << peer.port;
            continue;
        }
        if (peer.ip.type() == IPv6)
        {
            CLOG(WARNING, "Overlay") << "ignoring received IPv6 address"
                                     << " (not yet supported)";
            continue;
        }
        // randomize when we'll try to connect to this peer next if we don't
        // know it
        auto defaultNextAttempt =
            mApp.getClock().now() +
            std::chrono::seconds(std::rand() % NEW_PEER_WINDOW_SECONDS);

        stringstream ip;
        ip << (int)peer.ip.ipv4()[0] << "." << (int)peer.ip.ipv4()[1] << "."
           << (int)peer.ip.ipv4()[2] << "." << (int)peer.ip.ipv4()[3];
        // don't use peer.numFailures here as we may have better luck
        // (and we don't want to poison our failure count)
        PeerRecord pr{ip.str(), static_cast<unsigned short>(peer.port),
                      defaultNextAttempt, 0};

        if (pr.isPrivateAddress())
        {
            CLOG(WARNING, "Overlay") << "ignoring received private address "
                                     << pr.toString();
        }
        else if (pr.isSelfAddressAndPort(getIP(), mApp.getConfig().PEER_PORT))
        {
            CLOG(WARNING, "Overlay") << "ignoring received self-address "
                                     << pr.toString();
        }
        else if (pr.isLocalhost() &&
                 !mApp.getConfig().ALLOW_LOCALHOST_FOR_TESTING)
        {
            CLOG(WARNING, "Overlay") << "ignoring received localhost";
        }
        else
        {
            pr.insertIfNew(mApp.getDatabase());
        }
    }
}
Example #15
0
void
Peer::sendMessage(StellarMessage const& msg)
{
    CLOG(TRACE, "Overlay") << "("
                           << PubKeyUtils::toShortString(
                                  mApp.getConfig().NODE_SEED.getPublicKey())
                           << ") send: " << msg.type()
                           << " to : " << PubKeyUtils::toShortString(mPeerID);

    AuthenticatedMessage amsg;
    amsg.v0().message = msg;
    if (msg.type() != HELLO)
    {
        amsg.v0().sequence = mSendMacSeq;
        amsg.v0().mac =
            hmacSha256(mSendMacKey, xdr::xdr_to_opaque(mSendMacSeq, msg));
        ++mSendMacSeq;
    }
    xdr::msg_ptr xdrBytes(xdr::xdr_to_msg(amsg));
    this->sendMessage(std::move(xdrBytes));
}
Example #16
0
bool
Peer::recvHello(StellarMessage const& msg)
{
    if (msg.hello().peerID == mApp.getConfig().PEER_PUBLIC_KEY)
    {
        CLOG(DEBUG, "Overlay") << "connecting to self";
        drop();
        return false;
    }

    mRemoteProtocolVersion = msg.hello().protocolVersion;
    mRemoteVersion = msg.hello().versionStr;
    if (msg.hello().listeningPort <= 0 ||
        msg.hello().listeningPort > UINT16_MAX)
    {
        CLOG(DEBUG, "Overlay") << "bad port in recvHello";
        drop();
        return false;
    }
    mRemoteListeningPort =
        static_cast<unsigned short>(msg.hello().listeningPort);
    CLOG(INFO, "Overlay") << "recvHello "
                          << "@" << mApp.getConfig().PEER_PORT
                          << " from: " << mRemoteProtocolVersion << " "
                          << mRemoteVersion << " " << mRemoteListeningPort;
    mState = GOT_HELLO;
    mPeerID = msg.hello().peerID;
    return true;
}
Example #17
0
bool
Peer::recvHello(StellarMessage const& msg)
{
    if (msg.hello().peerID == mApp.getConfig().PEER_PUBLIC_KEY)
    {
        CLOG(DEBUG, "Overlay") << "connecting to self";
        drop();
        return false;
    }

    mRemoteOverlayVersion = msg.hello().overlayVersion;
    mRemoteVersion = msg.hello().versionStr;
    if (msg.hello().listeningPort <= 0 ||
        msg.hello().listeningPort > UINT16_MAX)
    {
        CLOG(DEBUG, "Overlay") << "bad port in recvHello";
        drop();
        return false;
    }
    mRemoteListeningPort =
        static_cast<unsigned short>(msg.hello().listeningPort);
    CLOG(DEBUG, "Overlay") << "recvHello from " << toString();
    mState = GOT_HELLO;
    mPeerID = msg.hello().peerID;
    if (mRole == INITIATOR)
    {
        PeerRecord pr(getIP(), mRemoteListeningPort, mApp.getClock().now(), 0,
                      1);

        pr.insertIfNew(mApp.getDatabase());
    }
    return true;
}
Example #18
0
void
Peer::sendPeers()
{
    // send top 50 peers we know about
    vector<PeerRecord> peerList;
    PeerRecord::loadPeerRecords(mApp.getDatabase(), 50, mApp.getClock().now(),
                                peerList);
    StellarMessage newMsg;
    newMsg.type(PEERS);
    newMsg.peers().reserve(peerList.size());
    for (auto const& pr : peerList)
    {
        if (pr.isPrivateAddress() ||
            pr.isSelfAddressAndPort(getIP(), mRemoteListeningPort))
        {
            continue;
        }
        PeerAddress pa;
        pr.toXdr(pa);
        newMsg.peers().push_back(pa);
    }
    sendMessage(newMsg);
}
void
PendingEnvelopes::envelopeReady(SCPEnvelope const& envelope)
{
    StellarMessage msg;
    msg.type(SCP_MESSAGE);
    msg.envelope() = envelope;
    mApp.getOverlayManager().broadcastMessage(msg);

    mPendingEnvelopes[envelope.statement.slotIndex].push_back(envelope);

    /*
    // if envelope is on the right slot send into SCP
    // TODO.1 : below
    if(checkFutureCommitted(envelope))
    {
        mIsFutureCommitted.insert(envelope.statement.slotIndex);
    }
    */

    mApp.getClock().getIOService().post([this]()
                                        {
                                            mHerder.processSCPQueue();
                                        });
}
Example #20
0
bool
tryRead(XDRInputFileStream& in, StellarMessage& m)
{
    try
    {
        return in.readOne(m);
    }
    catch (xdr::xdr_runtime_error& e)
    {
        LOG(INFO) << "Caught XDR error '" << e.what()
                  << "' on input substituting HELLO";
        m.type(HELLO);
        return true;
    }
}
Example #21
0
void
Peer::recvTransaction(StellarMessage const& msg)
{
    TransactionFramePtr transaction =
        TransactionFrame::makeTransactionFromWire(msg.transaction());
    if (transaction)
    {
        // add it to our current set
        // and make sure it is valid
        if (mApp.getHerder().recvTransaction(transaction))
        {
            mApp.getOverlayManager().recvFloodedMsg(msg, shared_from_this());
            mApp.getOverlayManager().broadcastMessage(msg);
        }
    }
}
Example #22
0
void
Peer::recvPeers(StellarMessage const& msg)
{
    for (auto const& peer : msg.peers())
    {
        if (peer.port == 0 || peer.port > UINT16_MAX)
        {
            CLOG(WARNING, "Overlay") << "ignoring received peer with bad port "
                                     << peer.port;
            continue;
        }
        if (peer.ip.type() == IPv6)
        {
            CLOG(WARNING, "Overlay") << "ignoring received IPv6 address"
                                     << " (not yet supported)";
            continue;
        }
        stringstream ip;
        ip << (int)peer.ip.ipv4()[0] << "." << (int)peer.ip.ipv4()[1] << "."
           << (int)peer.ip.ipv4()[2] << "." << (int)peer.ip.ipv4()[3];
        PeerRecord pr{ip.str(), static_cast<unsigned short>(peer.port),
                      mApp.getClock().now(), peer.numFailures};

        if (pr.isPrivateAddress())
        {
            CLOG(WARNING, "Overlay") << "ignoring received private address "
                                     << pr.toString();
        }
        else if (pr.isSelfAddressAndPort(getIP(), mApp.getConfig().PEER_PORT))
        {
            CLOG(WARNING, "Overlay") << "ignoring received self-address "
                                     << pr.toString();
        }
        else
        {
            pr.insertIfNew(mApp.getDatabase());
        }
    }
}
Example #23
0
void
Peer::recvTxSet(StellarMessage const& msg)
{
    TxSetFrame frame(msg.txSet());
    mApp.getHerder().recvTxSet(frame.getContentsHash(), frame);
}
Example #24
0
void
Peer::recvSCPQuorumSet(StellarMessage const& msg)
{
    SCPQuorumSetPtr qSet = std::make_shared<SCPQuorumSet>(msg.qSet());
    mApp.getHerder().recvSCPQuorumSet(qSet);
}
Example #25
0
void
Peer::recvHello(StellarMessage const& msg)
{
    using xdr::operator==;

    if (mState >= GOT_HELLO)
    {
        CLOG(ERROR, "Overlay")
            << "received unexpected HELLO";
        mDropInRecvHelloUnexpectedMeter.Mark();
        drop();
        return;
    }

    auto& peerAuth = mApp.getOverlayManager().getPeerAuth();
    if (!peerAuth.verifyRemoteAuthCert(msg.hello().peerID, msg.hello().cert))
    {
        CLOG(ERROR, "Overlay") << "failed to verify remote peer auth cert";
        mDropInRecvHelloCertMeter.Mark();
        drop();
        return;
    }

    mRemoteListeningPort =
        static_cast<unsigned short>(msg.hello().listeningPort);
    mRemoteOverlayVersion = msg.hello().overlayVersion;
    mRemoteVersion = msg.hello().versionStr;
    mPeerID = msg.hello().peerID;
    mRecvNonce = msg.hello().nonce;
    mSendMacSeq = 0;
    mRecvMacSeq = 0;
    mSendMacKey = peerAuth.getSendingMacKey(msg.hello().cert.pubkey, mSendNonce,
                                            mRecvNonce, mRole);
    mRecvMacKey = peerAuth.getReceivingMacKey(msg.hello().cert.pubkey,
                                              mSendNonce, mRecvNonce, mRole);

    mState = GOT_HELLO;
    CLOG(DEBUG, "Overlay") << "recvHello from " << toString();

    if (mRole == REMOTE_CALLED_US)
    {
        // Send a HELLO back, even if it's going to be followed
        // immediately by ERROR, because ERROR is an authenticated
        // message type and the caller won't decode it right if
        // still waiting for an unauthenticated HELLO.
        sendHello();
    }

    if (msg.hello().overlayVersion != mApp.getConfig().OVERLAY_PROTOCOL_VERSION)
    {
        CLOG(ERROR, "Overlay")
            << "connection from peer with different overlay protocol version";
        CLOG(DEBUG, "Overlay")
            << "Protocol = " << msg.hello().overlayVersion
            << " expected: " << mApp.getConfig().OVERLAY_PROTOCOL_VERSION;
        mDropInRecvHelloVersionMeter.Mark();
        drop(ERR_CONF, "wrong protocol version");
        return;
    }

    if (msg.hello().peerID == mApp.getConfig().NODE_SEED.getPublicKey())
    {
        CLOG(WARNING, "Overlay") << "connecting to self";
        mDropInRecvHelloSelfMeter.Mark();
        drop(ERR_CONF, "connecting to self");
        return;
    }

    if (msg.hello().networkID != mApp.getNetworkID())
    {
        CLOG(WARNING, "Overlay")
            << "connection from peer with different NetworkID";
        CLOG(DEBUG, "Overlay")
            << "NetworkID = " << hexAbbrev(msg.hello().networkID)
            << " expected: " << hexAbbrev(mApp.getNetworkID());
        mDropInRecvHelloNetMeter.Mark();
        drop(ERR_CONF, "wrong network passphrase");
        return;
    }

    for (auto const& p : mApp.getOverlayManager().getPeers())
    {
        if (&(p->mPeerID) == &mPeerID)
        {
            continue;
        }
        if (p->getPeerID() == mPeerID)
        {
            CLOG(WARNING, "Overlay")
                << "connection from already-connected peerID "
                << PubKeyUtils::toShortString(mPeerID);
            mDropInRecvHelloPeerIDMeter.Mark();
            drop(ERR_CONF, "connecting already-connected peer");
            return;
        }
    }

    if (msg.hello().listeningPort <= 0 ||
        msg.hello().listeningPort > UINT16_MAX)
    {
        CLOG(WARNING, "Overlay") << "bad port in recvHello";
        mDropInRecvHelloPortMeter.Mark();
        drop(ERR_CONF, "bad port number");
        return;
    }

    if (mRole == WE_CALLED_REMOTE)
    {
        sendAuth();
    }
}
Example #26
0
void
Peer::recvTxSet(StellarMessage const& msg)
{
    TxSetFramePtr txSet = std::make_shared<TxSetFrame>(msg.txSet());
    mApp.getHerder().recvTxSet(txSet);
}
Example #27
0
void
Peer::recvMessage(StellarMessage const& stellarMsg)
{
    CLOG(TRACE, "Overlay") << "("
                           << binToHex(mApp.getConfig().PEER_PUBLIC_KEY)
                                  .substr(0, 6)
                           << ")recv: " << stellarMsg.type()
                           << " from:" << hexAbbrev(mPeerID);

    if (mState < GOT_HELLO &&
        ((stellarMsg.type() != HELLO) && (stellarMsg.type() != PEERS)))
    {
        CLOG(WARNING, "Overlay") << "recv: " << stellarMsg.type()
                                 << " before hello";
        drop();
        return;
    }

    switch (stellarMsg.type())
    {
    case ERROR_MSG:
    {
        recvError(stellarMsg);
    }
    break;

    case HELLO:
    {
        this->recvHello(stellarMsg);
    }
    break;

    case DONT_HAVE:
    {
        recvDontHave(stellarMsg);
    }
    break;

    case GET_PEERS:
    {
        recvGetPeers(stellarMsg);
    }
    break;

    case PEERS:
    {
        recvPeers(stellarMsg);
    }
    break;

    case GET_TX_SET:
    {
        recvGetTxSet(stellarMsg);
    }
    break;

    case TX_SET:
    {
        recvTxSet(stellarMsg);
    }
    break;

    case TRANSACTION:
    {
        recvTransaction(stellarMsg);
    }
    break;

    case GET_SCP_QUORUMSET:
    {
        recvGetSCPQuorumSet(stellarMsg);
    }
    break;

    case SCP_QUORUMSET:
    {
        recvSCPQuorumSet(stellarMsg);
    }
    break;

    case SCP_MESSAGE:
    {
        recvSCPMessage(stellarMsg);
    }
    break;
    }
}
Example #28
0
void
fuzz(std::string const& filename, el::Level logLevel,
     std::vector<std::string> const& metrics)
{
    Logging::setFmt("<fuzz>", false);
    Logging::setLogLevel(logLevel, nullptr);
    LOG(INFO) << "Fuzzing stellar-core " << STELLAR_CORE_VERSION;
    LOG(INFO) << "Fuzz input is in " << filename;

    Config cfg1, cfg2;

    cfg1.RUN_STANDALONE = true;
    cfg1.ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING = true;
    cfg1.LOG_FILE_PATH = "fuzz-app-1.log";
    cfg1.TMP_DIR_PATH = "fuzz-tmp-1";
    cfg1.BUCKET_DIR_PATH = "fuzz-buckets-1";

    cfg2.RUN_STANDALONE = true;
    cfg2.ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING = true;
    cfg1.LOG_FILE_PATH = "fuzz-app-2.log";
    cfg2.TMP_DIR_PATH = "fuzz-tmp-2";
    cfg2.BUCKET_DIR_PATH = "fuzz-buckets-2";

    CfgDirGuard g1(cfg1);
    CfgDirGuard g2(cfg2);

restart:
    {
        VirtualClock clock;
        Application::pointer app1 = Application::create(clock, cfg1);
        Application::pointer app2 = Application::create(clock, cfg2);
        LoopbackPeerConnection loop(*app1, *app2);
        while (clock.crank(false) > 0)
            ;

        XDRInputFileStream in;
        in.open(filename);
        StellarMessage msg;
        size_t i = 0;
        while (tryRead(in, msg))
        {
            ++i;
            if (msg.type() != HELLO)
            {
                LOG(INFO) << "Fuzzer injecting message " << i << ": "
                          << msgSummary(msg);
                loop.getAcceptor()->Peer::sendMessage(msg);
            }
            size_t iter = 20;
            while (clock.crank(false) > 0 && iter-- > 0)
                ;
        }
    }

    if (getenv("AFL_PERSISTENT") && persist_cnt++ < PERSIST_MAX)
    {
#ifndef _WIN32
        raise(SIGSTOP);
#endif
        goto restart;
    }
}
Example #29
0
void
Peer::recvDontHave(StellarMessage const& msg)
{
    mApp.getHerder().peerDoesntHave(msg.dontHave().type, msg.dontHave().reqHash,
                                    shared_from_this());
}
Example #30
0
void
Peer::recvSCPQuorumSet(StellarMessage const& msg)
{
    Hash hash = sha256(xdr::xdr_to_opaque(msg.qSet()));
    mApp.getHerder().recvSCPQuorumSet(hash, msg.qSet());
}