Show Posts
|
Pages: [1] 2 3 4 5 6 7 »
|
Here's a link to a branch where I tried to use leveldb: https://github.com/trentrussell/qeditas/tree/trdevnfth-leveldbIt actually does compile, at least for me on debian. I got leveldb-1.18 and then compiled it. To compile qeditas I first had to set some directories are set using the configure file: ./configure -leveldb=<fullpathtoleveldbdir> -ocamlinclude=<ocamldir>/lib/ocaml make I have in my notes though that in some situation I got an error like: Error: Error on dynamically loaded library: ./bin/dlldb.so: ./bin/dlldb.so: undefined symbol: _ZN7leveldb2DB4OpenERKNS_7OptionsERKSsPPS0_
Instead of trying to figure this out, I switched to just saving things in files. I assume this is some kind of linking error which would be easy to resolve if I knew more about it.
|
|
|
Due to being busy with other things, I have not directly done any work on Qeditas since December. Nevertheless, I have been exchanging private messages with someone who has been experimenting with his own fork of the code. I must admit I haven't looked closely at his progress, but hope to spend some time reviewing it soon. Perhaps he will want to say more.
OK. I can give a short summary of what I've been doing. In January I tried using a fork of Clams to do the networking and database storage for Qeditas. This worked well enough that I had two or three nodes running a testnet for about a week. There were problems though and I don't think it makes sense to inherit a lot of code and dependencies that aren't needed. So now I'm trying to directly code the networking and database code in ocaml with the rest of Qeditas. One technical point might be worth mentioning: I got rid of "frames" entirely. Now ledger trees (ctrees) are always stored and communicated as "elements" -- essentially 9 levels with hashes summarizing the lowest levels (except leaves). It's like fixing the "frame" to be one that abstracts every nine levels. If all goes well, at some point I should be able to get some kind of testnet running. If so, I'll say more about how others can run a testnet node too. But I don't know if "at some point" will be next month or next year. Even at that point, I wouldn't recommend starting a mainnet until the testnet has run without a problem for a few months and people have had a chance to review the code.
|
|
|
Since it seems like there's still lots of time before Qeditas will launch, I want to propose that the units in the initial distribution slowly decrease over time. Specifically, I'm thinking that the distribution from the snapshot that can be claimed is 100% for roughly the first 5 years, but then halves along with the block reward every 4 years. I wrote code that does this in one of my Qeditas branches: https://github.com/trentrussell/qeditas/blob/trdevnf/src/assets.ml#L92A situation occurred in the Clam community recently where someone found out they had a significant amount of clams from the initial distribution and over a couple of months "dug" them ("digging" is the way clams are claimed) and sold them on the market. Not only did this hurt the price of clams a lot, it also fractured the community. Some insisted that "digging" be stopped to avoid a big digger event happening again. Others insisted that stopping digging would be breaking the promise of the original distribution. To avoid a similar debate in Qeditas, I think it's a good idea to already know that the threat of someone with a massive distribution from the snapshot is temporary. At the same time, everyone should have sufficient time to make their claim. Five years seems like a reasonable amount of time. After that, those with Qeditas currency from the initial distribution can still make their claim, but they will effectively get less. This halving would continue for roughly 200 years until the remaining units from the initial distribution is 0. Another reason this is a good idea is that there's no way to tell the difference between "lost" coins and unclaimed coins. Over time, unclaimed coins (from the initial distribution) disappear, leading to more certainty about the coin supply. Bill wrote me that he has "mixed feelings" about reducing the initial distribution over time like this, but is "open to being persuaded." He suggested I ask for comments on the thread. I'll let him say more about his opinions on the matter if he wants. Thoughts? Is this controversial?
|
|
|
so I just need 0.01 CLAM for example and I'm good to go? or are my chances increased to process a block the larger my stash?
Your chance of staking per unit time is proportional to the size of your stash, yes. If you have 1000 CLAMs you will stake 1 CLAM about once per day on average. If you have 0.01 CLAMs you will stake 1 CLAM about every 100,000 days (or 274 years) on average although you might get lucky and stake on your first day of trying. i only got 99,987 days to go! Funny thing about Poisson Processes: Every day you don't stake, you still have 100,000 days to go.
|
|
|
I have added some code for Qeditas to call qednet for things. Things are looking good so far. One thing, though. I looked at the "frame" used to create the initial distribution ctree (in qeditasinit.ml in the initdistr branch): let fr10 = flevs 8 FAll;; let fr2pk = flevs 8 fr10;; let fr2s = flevs 8 fr10;; let fr0 = FAbbrev(FBin(FBin(FAbbrev(fr2pk),FAbbrev(fr2s)),FAll));;
I wanted to save this frame in the database and potentially share it with peers, but the serialization of it was surprisingly large (over 100K). Looking closer it was clear this could be improved by using sharing. I changed the serialization code (seo_frame and sei_frame) to check if the two children of a binary FBin node are equal and treat this separately from the "real" binary case. This made the serialization of the frame above only 9 bytes(!). Here's the modified serialization code: https://github.com/trentrussell/qeditas/blob/trdev/src/ctre.ml#L706I tried to do things the same was as was described in the Serialization chapter of: http://qeditas.org/qeditastechdoc.pdf
|
|
|
I'm going to be letting a number of really good CLAM domains expire in the near future as well.
Hopefully you'll be more content after you really let go of any connection to Clams. At the moment you're behaving like a "crazy ex." After you really let go, there will be no reason for you to come to this thread at all. If you're having trouble letting go, consider talking to someone in real life about the situation.
|
|
|
Thanks. I was able to extend the C++ code to have a "savedatafromfile" command and used it to save all the initial ctree abbrev files into the leveldb database. It takes up about 330MB total. I can then get them back upon demand: qednetd loaddata qctreeabbrev 0b7f6f55f3b4b05a9a7bd99d01a087d799e01b9c ba55f4b8d10abea5f63679dae37a370ce7c891e4a77a843b8a0ccfeb19badfd2c6afe5aa36141f99dced6423c361b100b95d6ca886b698e1e8732446d0021b7eb5400b1d98d8be38bc9656cc1ba71acd5f01
In principle another node should be able to get the data from a peer: qednet getdata qctreeabbrev 0b7f6f55f3b4b05a9a7bd99d01a087d799e01b9c
But it doesn't get sent for some reason, so it's still work in progress. Edit: I found the problem, so now ctrees can be requested from peers.
|
|
|
By the way, I'm forking the clam code because I need a functioning p2p rumour network for something I'm trying out. I've changed the default ports and magic number, so no one running clams should notice anything. I'm open to the idea of directly integrating with the clam network in some way, but let's wait and see. I'll post something more depending on whether things are successful.
My fork of the clam code is described here: https://bitcointalk.org/index.php?topic=998559.msg13498133#msg13498133In short: I'm trying to use the modified clam network to pass around data for a different network (Qeditas). I do it by representing everything as a dummy clam tx (generally no inputs and no outputs) that has all the actual data in the clamspeech part. Yes, it's a hack. But it might work, and I don't have enough C++ experience to code it cleanly from scratch (like having a new class for each kind of data).
|
|
|
I was working with the code for Clams and thought of how I might be able to modify it to provide the network infrastructure you need for Qeditas. Clam transactions have a "clamspeech" part which can hold arbitrary data. This could be used (or abused?) to have dummy Clam transactions whose main content is a clamspeech part carrying Qeditas data (txs, blocks, ctrees, etc). In addition to giving a way of sharing the data between peers, the dummy txs with the Qeditas data can be stored in the local leveldb tx database. I forked Clams, made some modifications and renamed it "qednet". It's on github with a "trdev" branch that has the actual modifications: https://github.com/trentrussell/qednet/tree/trdevI also put the Qeditas git repo back on github. There's also a "trdev" branch there, but I haven't started modifying anything yet: https://github.com/trentrussell/qeditasI'm thinking Qeditas (ocaml) can start qednet (C++) in a process. Qednet will connect up with peers and share inventory/data (this works already). Qeditas will be notified when there are new Qeditas transactions or Qeditas blocks. Qeditas can then ask qednet (via rpc commands) for the actual data which Qeditas can verify and organize (e.g., finding the "best" current block/ledger). I should probably say that I'm not really a C++ programmer. The parts of the qednet code that didn't directly come from Clams was mostly copy-paste-modify from code in Clams. There is also some strange bug the first time I try to run qednetd. I'd expect it to make the .qednet directory and then advise the user on making a qednet.conf file. Instead the first time I run it it makes the .qednet directory and then dies with a seg fault. The second time I run it it warns that I need to -reindex. I don't actually need to -reindex (there are no blocks). Instead I run it a third time and it prompts me to make a qednet.conf file. After making the qednet.conf, I can run it a fourth time and it starts working. If this bug sounds familiar to anyone let me know. I'm not sure any of this will work well enough to really start Qeditas, but at least it might keep the Qeditas project alive with a test network. PS: To check if the first block is valid, I need the ctree corresponding to the initial ledger. I guess one node needs this and then it can get shared. @Bill: You posted a link to the initial distribution, but it's text files with address hashes and amounts. Do you have the ctree itself available somewhere?
|
|
|
I just saw this comment in the code and was quite amused. https://github.com/nochowderforyou/clams/blob/master/src/main.cpp#L1097 //Sanity Checks, If they happen: "We're All Going To Die"
By the way, I'm forking the clam code because I need a functioning p2p rumour network for something I'm trying out. I've changed the default ports and magic number, so no one running clams should notice anything. I'm open to the idea of directly integrating with the clam network in some way, but let's wait and see. I'll post something more depending on whether things are successful.
|
|
|
After thinking about the idea for using multisig to simulate exchanging crypto and fiat (see the link in my signature for the idea), the best way I can think to do it is in several steps.
1. A party makes an offer, including price, amount, collateral (with a specified txout), an expiration time, boundary information for the window and possible escrows. 2. A counterparty accepts the offer by determining the rest (counterparty collateral and which escrow), writing the full terms in (formal) text, signing the text, and creating a tx with the appropriate 2-of-3 tx with a hash of the contract text in the CLAMspeech. No one signs the tx yet. 3. The party accepts this by adding his/her signature of the contract text. 4. The escrow accepts this by adding his/her signature of the contract text. Only now do the party and counterparty start signing the tx. 5. One signs the tx. 6. Another signs the tx and publishes it.
The contract text would need to specify that it's void if there's not a tx with the contract hash in the clamspeech published by time X.
Unfortunately, I can't believe very many people would prefer trading with a 6 step process over simply trusting a third party exchange. Unless this could be simplified significantly, it's probably not worth implementing.
On the other hand, now that I've started looking into the CLAMour code, I'm imagining other potential uses of CLAMspeech. For example, another proof-of-stake coin could be "merge staked" with clams. Suppose the other coin (which I'll call "othercoin") is also proof-of-stake using its own token. When othercoin stakers make a new block, the block header hash could be published in the CLAMspeech of a coinstake:
othercoin <othercoinnewblockheaderhash>
For the othercoin block to be correct, the timestamp would have to be earlier than the time stamp in the Clams block where its hash was published. Also, the hashes would be required to be published in order.
An advantage of this is that someone couldn't silently make a separate long othercoin fork (since it would be visible in the Clams chain). To be more precise, they couldn't silently stake a separate othercoin history without also silently staking a separate Clams history. It would also rely on timestamps in Clams blocks to prevent attacks by falsely claiming an othercoin time in the future, unless they also attacked Clams this way at the same time.
Would there be any objection to this on the Clams side? It seems like it would give more people a reason to own and stake Clams.
The only downside I can see is that it restricts stakers from making clamour votes. It seems like "othercoin <hash>" might only take up about half the CLAMspeech, so people could still vote for some clamours by having a speech like:
clamour <id1> <id2> othercoin <hash>
PS: I now have two testnet clam nodes running. For testing, I need to be able to stake fairly regularly, so it would help if someone could send massive amounts of testnet clams to n422ULsfpah4GEJciZ1uRYMCLgFdGCpBsP and mxHPD9KUvyvezaVC87b2vFrnHaiFnB44mf. Based on the current staking weight on testnet, it looks like approximately 100,000 clams would let me stake a few times an hour.
|
|
|
Be careful. Just because one of my privkeys signed the first input to a transaction, it doesn't mean I agree with the content of the CLAMspeech. The transaction could be a withdrawal from Just-Dice. When withdrawing from Just-Dice you can specify any CLAMspeech you like. The transaction's inputs will be signed by private keys in the hot wallet, but the owner of those keys doesn't endorse the content of the CLAMspeech.
This is a good point. It's another reason for me to step back and think more carefully about "design" issues. In other words, it's been one of those days of taking two steps back.
I worry that we're going to end up hard-coding many different similar-but-different features into the CLAM client, and wonder if there's some way we could generalize it so we don't have to edit C++ code for the next person to dream up a use for CLAMspeech. (Cue sighs and groans from Creative and Kef...) I've read before that bitcoin restricted OP_RETURN to 40 bytes because this is enough for key value pairs for a distributed hash table. Maybe a feature for storing such key value pairs would be sufficient for many different purposes.
|
|
|
You could get rid of isprefix all together, and just check whether i == vchID.size() after the loop is done. Iff that's true then it's a prefix: unsigned char* keyidarr = (unsigned char*) &keyid; unsigned int i; for (i = 0; i < vchID.size(); i++) if (vchID[i] != keyidarr[i]) break; if (i == vchID.size()) // it's a prefix ...
Edit: I meant to say that I was meaning to help you out with this about 12 hours ago, but when I went to check on my testnet instance it was dead, and crashed every time I tried to restart it, so I spent today tracking down and fixing the bugs that caused that instead. Thanks, that code is an improvement. I'd forgotten about break. I was originally hoping to take advantage of the representation in memory of the vchID "unsigned char vector" to avoid needing to loop at all, but it became clear that the representation isn't what I hoped it was (an array). I'm happy with the response time I've been getting from the Clam team members, so thanks to all of you for that. Now that I have "register pubkey" I started writing support for "register escrow agent", "create contract", "trade contract" and "settle contract" -- but found I have to rethink things again. For example, I had planned to have CLAMspeech declarations like: register escrow agent 73 USD <timeout> <terms> in which the controller of the pubkey registered to 73 indicates his/her willingness to act as an escrow agent under the given terms until the timeout. Obviously this tx should be signed by the corresponding private key. The easiest way to enforce this is to check that the first input to the tx with the CLAMspeech came from the corresponding address. In which case the pubkey is explicitly in the tx already, and so why did it need to be registered in advance? In other words, it's been one of those days of taking two steps back.
|
|
|
I did find a bit of a hackish way to check if a vector of unsigned chars is a "prefix" of a CKeyID: CKeyID keyid = vchPubKey.GetID(); std::vector<unsigned char> vchID = ParseHex(strID); bool isprefix=true; unsigned char* keyidarr = (unsigned char*) &keyid; for (unsigned int i = 0; i < vchID.size() && isprefix; ++i) { if (vchID[i] != keyidarr[i]) isprefix=false; }
This rejects the old register (since it uses the checksum instead of a prefix) and accepts the new one. As a result there's one pubkey registered. I have commands "listrpubkeys" and "getrpubkey": cct listrpubkeys [ { "id" : "73", "pubkey" : "039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5", "txid" : "8690cfc9b0e40b7fb328da478e2523071ac759eea7cac729038b47b8f180948d", "confirmations" : 446 } ]
cct getrpubkey 73 { "pid" : "73", "id" : "73", "pubkey" : "039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5", "txid" : "8690cfc9b0e40b7fb328da478e2523071ac759eea7cac729038b47b8f180948d", "confirmations" : 446 }
The "pid" field given in response to "getrpubkey" shouldn't be there. I'll track it down later. I'm saying "rpubkey" for "registered pubkey" to avoid confusing with ordinary public keys. If someone has a suggestion for how I should've done it, I'd be happy to listen.
|
|
|
I've managed to add registration of ids to a version of clams I'm running on testnet. I've switched to having ids that are N prefix bytes of the underlying 20 byte address instead of using the checksum. In hex this is a 2N char id. An example is in tx 8690cfc9b0e40b7fb328da478e2523071ac759eea7cac729038b47b8f180948d with the clamspeech: register pubkey 73 039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5 Here the given pubkey is from the address mr1yhbGu64c83LtN5GBxPVPBb7XheNi8rH, which in hex is Version Byte: 6f 20 byte address: 732e7e8744a30f55ff7c43b77e473ff462777b43 Checksum: 8b8070fe In principle, possible ids to register would be 73 (as above), 732e, 732e7e, etc. I don't yet have code that correctly actually checks that the given id corresponds to a prefix of the address, so I wanted to ask (technically) how to do this. Here's what I've found: I can use CPubKey(ParseHex(strPubkey)) to convert "039d...f5" into a CPubKey. IsFullyValid will make sure it's a valid pubkey. GetID can be used to obtain the 20 byte address as a CKeyID (which seems to be the same as uint160). On the other hand, I can use ParseHex on the given hex ID in the clamspeech to obtain a vector of unsigned chars. I crossed my fingers and tried to use memcmp as a way checking for a prefix, but it doesn't seem to work. Here's the current code snippet I have in main.cpp: ... CPubKey vchPubKey = CPubKey(ParseHex(strPubkey)); ... CKeyID keyid = vchPubKey.GetID(); std::vector<unsigned char> vchID = ParseHex(strID); if (memcmp(&vchID,&keyid,vchID.size()) != 0) { LogPrintf("invalid pubkey registration attempt %s; id %s is not a prefix of the address: %s\n", strPubkey, strID, tx.strCLAMSpeech.substr(0, MAX_TX_COMMENT_LEN)); } else { pindex->vRpubkey.push_back(*(mapRpubkey[pid] = new CRpubkey(pindex->nHeight, tx.GetHash(), strID, strPubkey))); }
I'm going to try to get on the #clams channel on IRC. If successful, I'll start asking questions there. I don't want to "spam" this thread with posts that aren't of general interest. I could also start a separate thread if people think I should. Edit: I'm now registered at irc.freenode.net with nick TrentRussell and have joined the #clams channel. I've never used irc before, but will try to use it now and try to log the channel when I'm not online.
|
|
|
Enquiring minds want to know if astroturfers get christmas day off... Before anyone jumps to any conclusions, that cuts both ways It's amusing that this was the last post before Christmas. Nothing on Christmas. Then all hell breaks loose.
|
|
|
There exists a natural place where unicorns live. I've said it. Does that mean it is true? Should I write a paper to confirm it? His words were obliterated by others long ago. Maybe it becomes true if you repeat the quote in enough distinct posts. That's how truth works, right?
|
|
|
I'm not sure why you need to use any URL. The register pubkey 8b8070fe 039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5 one seems easiest. But the checksum is only valid for Bitcoin testnet. So unless you specify either "Bitcoin testnet" or "111" (i.e. Bitcoin testnet prefix byte), it would take 112 iterations of sha256d to verify the checksum, assuming the verifier starts at prefix_byte = 0. That's not a heavy burden, but it seems unnecessary.
The URL was only needed in order to give the pubkey in a way that technically would match what CLAMour expects. I won't do this. I'm likely to go with the "register pubkey <checksum> <pubkey>" approach. I'll try to modify my copy of the clam code to have a "getpubkey" command.
|
|
|
I've registered an identity on testnet using CLAMour as follows: The tx c82f27a509bf2c04ffb037f683d8259894f273f8d8f849a8e0545879d5444a2c has CLAMspeech create clamour 1a762d2507760a436061029547245e434fa89da6e9d22cf07d6f8a6140b31f37 http://txti.es/1a762d25The text at the link is "Testnet identity 039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5 (address mr1yhbGu64c83LtN5GBxPVPBb7XheNi8rH)". The "identity" can (in a sense) be looked up using the client: cct getclamour 1a762d25 { "pid" : "1a762d25", "hash" : "1a762d2507760a436061029547245e434fa89da6e9d22cf07d6f8a6140b31f37", "url" : "http://txti.es/1a762d25", "txid" : "c82f27a509bf2c04ffb037f683d8259894f273f8d8f849a8e0545879d5444a2c", "confirmations" : 16 } While this would work, I think it's better to separate it from CLAMour. Also, I think I shouldn't say "identity" when what I really mean is "pubkey". Here's an alternative approach: The tx 6c08736d725217eeaf04dd3e1cc90ee17123f4361b7318fd9f68b02d87823b0b has CLAMspeech register pubkey 8b8070fe 039df70c1c46425ae4d3be53892949e17bebcbe30f419132441faab92677b220f5 Here the hex "8b8070fe" is the 4 byte checksum of the corresponding address: mr1yhbGu64c83LtN5GBxPVPBb7XheNi8rH. A "getpubkey" command (like "getclamour") would be helpful. Thoughts?
|
|
|
... I'm not sure exactly what your goal is, but it sounds like Namecoin could be a viable alternative. CLAMour is one application of the overall ClamSpeech system, created for petitions. So if you want to store identities, I would recommend something along the lines of 'create identity <hash> <url>' as per your example. At one point we explored a potential format for ClamSpeeches that included metadata before the rest of the ClamSpeech - a "category identifier." Ultimately something more plain-language was used. There are no enforced rules on the contents of ClamSpeeches (and I'm confident that there never will be), only on their lengths. So if somebody wants to store identity data in the CLAM chain, it doesn't really matter what anyone else approves of. If you do use the CLAM chain for identity data, there is one thing you should be aware of: The requirement that a petition be declared with 'create clamour <petition_hash> [<url>]' exists because petitions are identified by their first 4 bytes when voting for them (so multiple petitions can be voted for in one stake transaction). Since you probably won't need to refer to multiple identities in one ClamSpeech, you can just omit the 'create identity' step. Thus, you can simply put 'identity <hash> [<url>]' in a ClamSpeech instead of 'create identity <hash> [<url>]'. I mainly need a short unambiguous way to refer to a public key, so using CLAMour for this is probably overkill. I've done some testnet tests and the next post will be about it. (It's already written, but wanted to respend to your post first.)
|
|
|
|