Can a full node provide a bogus block bloomfilter to a Neutrino node?
When a thin client using BIP157/BIP158 (Neutrino) requests the block filter for the latest block, would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content? Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
security block-header thin-clients sybil-attack neutrino
add a comment |
When a thin client using BIP157/BIP158 (Neutrino) requests the block filter for the latest block, would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content? Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
security block-header thin-clients sybil-attack neutrino
add a comment |
When a thin client using BIP157/BIP158 (Neutrino) requests the block filter for the latest block, would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content? Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
security block-header thin-clients sybil-attack neutrino
When a thin client using BIP157/BIP158 (Neutrino) requests the block filter for the latest block, would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content? Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
security block-header thin-clients sybil-attack neutrino
security block-header thin-clients sybil-attack neutrino
asked 12 hours ago
Murch♦Murch
34.9k27114326
34.9k27114326
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
They can lie to you about the filters, yes. However due to the filters being deterministic you can query other nodes for the hashes of their filters to gauge relative correctness. You can also use a watchtower like service to give a trusted set of the filters in some cases.
The original design document includes an extension for committing to these filters as a consensus rule. It is designed and presented as “levels” which can improve the reliability and security of using client side filtering in this manner.
The security model of the oracle bloom filter can be vastly improved
by instead committing a hash of the BFD inside every block as a soft-
fork consensus rule change. After this, every node in the network would
build the filter and validate that the hash in the block is correct,
then make a conscious choice discard it for space savings or cache the
data to disk.
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012636.html
add a comment |
would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Yes. Indeed, the protocol actually specifies that data carrier outputs (OP_RETURN
outputs) are always excluded from the filter.
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content?
The properties of a Golomb-coded set, which is what BIP157/158 uses (not a Bloom filter) are that an honest default filter is guaranteed to match any of the wallet's data that were included in the block chain data used to generate the filter, but that it might also sometimes match wallet data that weren't part of the filter data. For example:
- Alice's wallet has the addresses bc1abcd...wxyz
- If block 123 includes address bc1abcd...wxyz and a node sends Alice an honest filter, it's guaranteed to generate a match for her
- If block 456 doesn't include the address bc1abcd...wxyz, it might still produce a match for Alice's wallet by accident
This creates a very simple situation that as long as the lite client has at least one honest peer---an assumption lite clients (SPV clients) depend on to get the most-PoW chain---Alice is guaranteed to always download blocks with transactions interesting to her wallet because one of the filters Alice downloads will be honest. This is similar in security to BIP37.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate (which I think is about 1-in-20-million). Since Alice is probably downloading blocks from a different node than she used to get her filters (for increased privacy), this can create a weak DoS bandwidth vulnerability against honest nodes, like a DNS amplification attack.
Happily, with BIP157/158 filters having such a low false-positive rate, Alice can detect that Mallory is griefing her pretty quickly by noticing that Mallory's filters are resulting in a much higher false positive rate than expected.
Additionally, BIP157/158 filters are deterministic and a small hash commitment to a particular filter can be distributed using a small cfheaders
message. This makes it very bandwidth efficient for Alice to query a large number of nodes for filters at the same block height. If any of them disagree, Alice can download all the different filters and the corresponding block, check for omissions or high false positive rates, ban deceitful peers, and continue on in relative bliss. This is much better than BIP37 which requires quite a bit of bandwidth (and even more node CPU cycles) to query a large number of peers.
Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
Sort of. A consensus rule change (possible as a soft fork) could require that a block commit to the filter for that block. A miner could still create an invalid block with a fake filter, but since miners can just as easily create invalid blocks with fake transactions, there's no advantage to creating fake filters.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.
– Anonymous
5 hours ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "308"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fbitcoin.stackexchange.com%2fquestions%2f83792%2fcan-a-full-node-provide-a-bogus-block-bloomfilter-to-a-neutrino-node%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
They can lie to you about the filters, yes. However due to the filters being deterministic you can query other nodes for the hashes of their filters to gauge relative correctness. You can also use a watchtower like service to give a trusted set of the filters in some cases.
The original design document includes an extension for committing to these filters as a consensus rule. It is designed and presented as “levels” which can improve the reliability and security of using client side filtering in this manner.
The security model of the oracle bloom filter can be vastly improved
by instead committing a hash of the BFD inside every block as a soft-
fork consensus rule change. After this, every node in the network would
build the filter and validate that the hash in the block is correct,
then make a conscious choice discard it for space savings or cache the
data to disk.
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012636.html
add a comment |
They can lie to you about the filters, yes. However due to the filters being deterministic you can query other nodes for the hashes of their filters to gauge relative correctness. You can also use a watchtower like service to give a trusted set of the filters in some cases.
The original design document includes an extension for committing to these filters as a consensus rule. It is designed and presented as “levels” which can improve the reliability and security of using client side filtering in this manner.
The security model of the oracle bloom filter can be vastly improved
by instead committing a hash of the BFD inside every block as a soft-
fork consensus rule change. After this, every node in the network would
build the filter and validate that the hash in the block is correct,
then make a conscious choice discard it for space savings or cache the
data to disk.
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012636.html
add a comment |
They can lie to you about the filters, yes. However due to the filters being deterministic you can query other nodes for the hashes of their filters to gauge relative correctness. You can also use a watchtower like service to give a trusted set of the filters in some cases.
The original design document includes an extension for committing to these filters as a consensus rule. It is designed and presented as “levels” which can improve the reliability and security of using client side filtering in this manner.
The security model of the oracle bloom filter can be vastly improved
by instead committing a hash of the BFD inside every block as a soft-
fork consensus rule change. After this, every node in the network would
build the filter and validate that the hash in the block is correct,
then make a conscious choice discard it for space savings or cache the
data to disk.
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012636.html
They can lie to you about the filters, yes. However due to the filters being deterministic you can query other nodes for the hashes of their filters to gauge relative correctness. You can also use a watchtower like service to give a trusted set of the filters in some cases.
The original design document includes an extension for committing to these filters as a consensus rule. It is designed and presented as “levels” which can improve the reliability and security of using client side filtering in this manner.
The security model of the oracle bloom filter can be vastly improved
by instead committing a hash of the BFD inside every block as a soft-
fork consensus rule change. After this, every node in the network would
build the filter and validate that the hash in the block is correct,
then make a conscious choice discard it for space savings or cache the
data to disk.
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012636.html
answered 11 hours ago
AnonymousAnonymous
8,63411028
8,63411028
add a comment |
add a comment |
would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Yes. Indeed, the protocol actually specifies that data carrier outputs (OP_RETURN
outputs) are always excluded from the filter.
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content?
The properties of a Golomb-coded set, which is what BIP157/158 uses (not a Bloom filter) are that an honest default filter is guaranteed to match any of the wallet's data that were included in the block chain data used to generate the filter, but that it might also sometimes match wallet data that weren't part of the filter data. For example:
- Alice's wallet has the addresses bc1abcd...wxyz
- If block 123 includes address bc1abcd...wxyz and a node sends Alice an honest filter, it's guaranteed to generate a match for her
- If block 456 doesn't include the address bc1abcd...wxyz, it might still produce a match for Alice's wallet by accident
This creates a very simple situation that as long as the lite client has at least one honest peer---an assumption lite clients (SPV clients) depend on to get the most-PoW chain---Alice is guaranteed to always download blocks with transactions interesting to her wallet because one of the filters Alice downloads will be honest. This is similar in security to BIP37.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate (which I think is about 1-in-20-million). Since Alice is probably downloading blocks from a different node than she used to get her filters (for increased privacy), this can create a weak DoS bandwidth vulnerability against honest nodes, like a DNS amplification attack.
Happily, with BIP157/158 filters having such a low false-positive rate, Alice can detect that Mallory is griefing her pretty quickly by noticing that Mallory's filters are resulting in a much higher false positive rate than expected.
Additionally, BIP157/158 filters are deterministic and a small hash commitment to a particular filter can be distributed using a small cfheaders
message. This makes it very bandwidth efficient for Alice to query a large number of nodes for filters at the same block height. If any of them disagree, Alice can download all the different filters and the corresponding block, check for omissions or high false positive rates, ban deceitful peers, and continue on in relative bliss. This is much better than BIP37 which requires quite a bit of bandwidth (and even more node CPU cycles) to query a large number of peers.
Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
Sort of. A consensus rule change (possible as a soft fork) could require that a block commit to the filter for that block. A miner could still create an invalid block with a fake filter, but since miners can just as easily create invalid blocks with fake transactions, there's no advantage to creating fake filters.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.
– Anonymous
5 hours ago
add a comment |
would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Yes. Indeed, the protocol actually specifies that data carrier outputs (OP_RETURN
outputs) are always excluded from the filter.
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content?
The properties of a Golomb-coded set, which is what BIP157/158 uses (not a Bloom filter) are that an honest default filter is guaranteed to match any of the wallet's data that were included in the block chain data used to generate the filter, but that it might also sometimes match wallet data that weren't part of the filter data. For example:
- Alice's wallet has the addresses bc1abcd...wxyz
- If block 123 includes address bc1abcd...wxyz and a node sends Alice an honest filter, it's guaranteed to generate a match for her
- If block 456 doesn't include the address bc1abcd...wxyz, it might still produce a match for Alice's wallet by accident
This creates a very simple situation that as long as the lite client has at least one honest peer---an assumption lite clients (SPV clients) depend on to get the most-PoW chain---Alice is guaranteed to always download blocks with transactions interesting to her wallet because one of the filters Alice downloads will be honest. This is similar in security to BIP37.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate (which I think is about 1-in-20-million). Since Alice is probably downloading blocks from a different node than she used to get her filters (for increased privacy), this can create a weak DoS bandwidth vulnerability against honest nodes, like a DNS amplification attack.
Happily, with BIP157/158 filters having such a low false-positive rate, Alice can detect that Mallory is griefing her pretty quickly by noticing that Mallory's filters are resulting in a much higher false positive rate than expected.
Additionally, BIP157/158 filters are deterministic and a small hash commitment to a particular filter can be distributed using a small cfheaders
message. This makes it very bandwidth efficient for Alice to query a large number of nodes for filters at the same block height. If any of them disagree, Alice can download all the different filters and the corresponding block, check for omissions or high false positive rates, ban deceitful peers, and continue on in relative bliss. This is much better than BIP37 which requires quite a bit of bandwidth (and even more node CPU cycles) to query a large number of peers.
Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
Sort of. A consensus rule change (possible as a soft fork) could require that a block commit to the filter for that block. A miner could still create an invalid block with a fake filter, but since miners can just as easily create invalid blocks with fake transactions, there's no advantage to creating fake filters.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.
– Anonymous
5 hours ago
add a comment |
would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Yes. Indeed, the protocol actually specifies that data carrier outputs (OP_RETURN
outputs) are always excluded from the filter.
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content?
The properties of a Golomb-coded set, which is what BIP157/158 uses (not a Bloom filter) are that an honest default filter is guaranteed to match any of the wallet's data that were included in the block chain data used to generate the filter, but that it might also sometimes match wallet data that weren't part of the filter data. For example:
- Alice's wallet has the addresses bc1abcd...wxyz
- If block 123 includes address bc1abcd...wxyz and a node sends Alice an honest filter, it's guaranteed to generate a match for her
- If block 456 doesn't include the address bc1abcd...wxyz, it might still produce a match for Alice's wallet by accident
This creates a very simple situation that as long as the lite client has at least one honest peer---an assumption lite clients (SPV clients) depend on to get the most-PoW chain---Alice is guaranteed to always download blocks with transactions interesting to her wallet because one of the filters Alice downloads will be honest. This is similar in security to BIP37.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate (which I think is about 1-in-20-million). Since Alice is probably downloading blocks from a different node than she used to get her filters (for increased privacy), this can create a weak DoS bandwidth vulnerability against honest nodes, like a DNS amplification attack.
Happily, with BIP157/158 filters having such a low false-positive rate, Alice can detect that Mallory is griefing her pretty quickly by noticing that Mallory's filters are resulting in a much higher false positive rate than expected.
Additionally, BIP157/158 filters are deterministic and a small hash commitment to a particular filter can be distributed using a small cfheaders
message. This makes it very bandwidth efficient for Alice to query a large number of nodes for filters at the same block height. If any of them disagree, Alice can download all the different filters and the corresponding block, check for omissions or high false positive rates, ban deceitful peers, and continue on in relative bliss. This is much better than BIP37 which requires quite a bit of bandwidth (and even more node CPU cycles) to query a large number of peers.
Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
Sort of. A consensus rule change (possible as a soft fork) could require that a block commit to the filter for that block. A miner could still create an invalid block with a fake filter, but since miners can just as easily create invalid blocks with fake transactions, there's no advantage to creating fake filters.
would it be possible for the full node serving this request to attack the Neutrino node by providing a fake block filter that omits certain transactions?
Yes. Indeed, the protocol actually specifies that data carrier outputs (OP_RETURN
outputs) are always excluded from the filter.
Do block filters include a mechanism that enables the thin client to verify that it is an accurate representation of the corresponding block's content?
The properties of a Golomb-coded set, which is what BIP157/158 uses (not a Bloom filter) are that an honest default filter is guaranteed to match any of the wallet's data that were included in the block chain data used to generate the filter, but that it might also sometimes match wallet data that weren't part of the filter data. For example:
- Alice's wallet has the addresses bc1abcd...wxyz
- If block 123 includes address bc1abcd...wxyz and a node sends Alice an honest filter, it's guaranteed to generate a match for her
- If block 456 doesn't include the address bc1abcd...wxyz, it might still produce a match for Alice's wallet by accident
This creates a very simple situation that as long as the lite client has at least one honest peer---an assumption lite clients (SPV clients) depend on to get the most-PoW chain---Alice is guaranteed to always download blocks with transactions interesting to her wallet because one of the filters Alice downloads will be honest. This is similar in security to BIP37.
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate (which I think is about 1-in-20-million). Since Alice is probably downloading blocks from a different node than she used to get her filters (for increased privacy), this can create a weak DoS bandwidth vulnerability against honest nodes, like a DNS amplification attack.
Happily, with BIP157/158 filters having such a low false-positive rate, Alice can detect that Mallory is griefing her pretty quickly by noticing that Mallory's filters are resulting in a much higher false positive rate than expected.
Additionally, BIP157/158 filters are deterministic and a small hash commitment to a particular filter can be distributed using a small cfheaders
message. This makes it very bandwidth efficient for Alice to query a large number of nodes for filters at the same block height. If any of them disagree, Alice can download all the different filters and the corresponding block, check for omissions or high false positive rates, ban deceitful peers, and continue on in relative bliss. This is much better than BIP37 which requires quite a bit of bandwidth (and even more node CPU cycles) to query a large number of peers.
Would it be possible to construct the block filters in a fashion that lying by omission becomes impossible when the thin client is aware of the correct latest block's header already?
Sort of. A consensus rule change (possible as a soft fork) could require that a block commit to the filter for that block. A miner could still create an invalid block with a fake filter, but since miners can just as easily create invalid blocks with fake transactions, there's no advantage to creating fake filters.
edited 10 hours ago
answered 10 hours ago
David A. HardingDavid A. Harding
9,27912656
9,27912656
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.
– Anonymous
5 hours ago
add a comment |
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.
– Anonymous
5 hours ago
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.– Anonymous
5 hours ago
Unlike BIP37, BIP157/158 can allow a griefer (Mallory) to stuff a filter full of extraneous data to cause a greater number of matches than indicated by the BIP157/158 false positive rate
I'm not sure this is correct. BIP37 has no restriction on what the node actually returns, it's trivial to short circuit the filtering command to return just everything, and the clients as far as I know have no defense against massive amounts of non-matches. The code I've looked at never even compares the filters to what is returned.– Anonymous
5 hours ago
add a comment |
Thanks for contributing an answer to Bitcoin Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fbitcoin.stackexchange.com%2fquestions%2f83792%2fcan-a-full-node-provide-a-bogus-block-bloomfilter-to-a-neutrino-node%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown