I'm sorry, I don't think I can. Spec needs to be pc = addr3, without the $. Yup - my bad again - actually the code had it right all the time I just wrote the spec. wrong (twice now). It will be fixed to: pc = addr3 in the spec. (which is how it actually had been coded in the prototype originally - guess I code better than I write specifications).
|
|
|
OK, that's easy enough.
Glad you have decided to change it. Its strange the gateway is actually never dealing in NXT. It does have issue and redemption of asset, which is in NXT cents though. Do you know how we will go from NXT cents to more precision later? I guess I could just multiply by a million and it becomes NXTtoshis.
It makes sense to use NXTtoshis and then convert them back to NXTcents for API calls (that way all your numbers will be at the same scale).
|
|
|
for BTC, I could just convert to satoshis and do arithmetic on that couldn't I? All I need are add and subtract, can I just use longs or do I need to use a special library?
You just need to use an int64_t and consider everything to be in "satoshis" if you are only doing basic operations (the class I wrote is to allow for more complicated operations). For NXT amounts also just treat the values as NXT cents (although you may as well also allow for further possible decimal values) and use an int64_t again.
|
|
|
The infinitesimal rears its ugly head. This is why when I am doing comparisons, I usually have a SMALLVAL set to .0000000001 or something like that and adjust the comparisons.
You could use an "epsilon" for comparisons but it is simply too easy for someone to code: if( a == 0 ) or if( a != 0 ) isn't it? Also I just showed (1) of the main problems (arguably probably about the nastiest surprise) but there are *others*. Again - you have been warned - this is not a "dust" issue - it will end up being a "logic issue" and I would bet that at some point you are going to unexpectedly end up with negative balances.
|
|
|
For those interested the output of the little program I posted just before is this: a = 13.060000, b = 0.540000, c = 13.600000 c == 13.60 a + b > 13.60
Now all we how done here is to "add" two numbers together and then compare and *bam* we are in trouble.
|
|
|
I do understand.
Clearly you do not. Please just try just this out: #define test( v1, op, v2 ) if( v1 op v2 ) printf( #v1 " " #op " " #v2 "\n" )
#include <stdio.h> #include <math.h>
int main( ) { volatile double a, b, c; char buf[ 50 ];
a = 13.06; b = 0.54; sprintf( buf, "%lf", a + b ); c = atof( buf );
printf( "a = %lf, b = %lf, c = %lf\n", a, b, c );
test( c, >, 13.60 ); test( c, ==, 13.60 ); test( c, <, 13.60 ); test( a + b, >, 13.60 ); test( a + b, ==, 13.60 ); test( a + b, <, 13.60 );
return 0; }
|
|
|
Just adding.
James - you do understand that 0.1 and 0.01 *cannot be represented in binary floating point* don't you (no matter how many bits you have)? If you care to *read* what I linked for you the problems can (and will) occur even when you are just doing simple operations. Anyway - you have been warned but clearly are not interested in *learning* anything about serious software engineering so I give up and would recommend *no-one* to consider your software as anything other than a prototype.
|
|
|
Actually, that still isn't the subleq branching. SUBLEQ a, b, c means that after you perform a = a - b, if that is <= 0, you goto c, not the address pointed to by c, or advance the code point by c. So you'll want pc = addr3 instead.
Oh - so I changed the code which was actually already correct - doh! Okay so I'll put the code back the way it was and change the spec. to this: SUB_LEQ 0x89 addr1,addr2,addr3 @addr1 -= $addr2, if $addr1 <= 0 then pc = $addr3 (for James)
Please tell me I've got it right this time!
|
|
|
Is double precision floating point really so unreliable?
This is peoples *money* you are dealing with James so I think you should not be so cavalier and actually understand how things work (or pay someone else to do the job *properly*). If you take such shortcuts then your code will just end up as "junk" down the track. I am sure there is some equivalent C code around and the code I wrote there could be reduced (as a lot of functionality it has you wouldn't need).
|
|
|
I just dont want to have to deal with converting everything to int math for now.
This is something better to be done "sooner than later" - I gave you a link to code (check back a couple of posts) that does the job (and has had years of "testing in the field") - feel free to use it.
|
|
|
Would it be possible to use int64_t from the stdint.h library to represent amounts instead of floating point?
Indeed James you should *never* use binary floating point types for *money* please use an int64_t as suggested. If you're interested take a look at https://github.com/ciyam/ciyam/blob/master/src/numeric.cpp (an example of how to do "decimal" using a 64 bit integer as a mantissa).
|
|
|
I missed that. Hopefully I wont have to pay double for all the subleqs.
Strange, I wrote it in the spec as state.pc += $addr3 but didn't actually code it that way in the prototype - anyway I've changed the code (locally for now but will republish soon) to the following: if( state.jumps.count( state.pc + addr3 ) ) state.pc += addr3;
so this ought to be the "subleq" you were expecting James. I think it would be nice to have the possibility to execute the AT at a specific block height (Time) without the need for a incoming transaction to that AT.
Agreed - so I think part of the AT "header" will include an "execute at" block # (or approx. time). Another related idea is that if an AT is currently hibernating then the extra fee required for sending a tx to an AT (to allow it to execute a minimum # of steps) would be instead added to the AT's balance (i.e. so it is paying for those steps to be executed later).
|
|
|
After some consideration I am now thinking that a simple "crowd funding" AT could be a better 3rd use case (I was considering an "auction" but it seems to me the VS could probably handle that with some very minor modifications). The idea would be that this AT would check its balance after n blocks (so it would be a good candidate to use the "sleep until block X") and if it is >= X then it would send all its funds to account Y (being the "project's account") otherwise it would iterate through all the txs it had received and refund the amount back to the sender (minus a small amount to run itself). What do you guys think? Do i get this right, everytime a new transaction comes in, the AT is beeing executed from the beginning, but the memory is at the state where it ended last time?
Pretty much although it actually depends how it had halted - if it had finished running (or reached a "finish" op) then yes it does that but if it hit a "stop" op (or it was halted due to lack of funds) then it continues from that point rather than from the start. From where is execution time purchased from the ATs XNTs or from a fee in the incoming transaction?
The execution time is in accordance with the AT's balance although a fee (possible mandatory) will cover a small amount of execution (so an AM would actually trigger execution).
|
|
|
Do you know what the limits are? What about the txfee?
Upper limit is 20 (as that Javascript website shows) - can read here: https://bitcointalk.org/index.php?topic=215213.0 although there may still be a "relay" limit of 3 in place (so you might try submitting a 4 of 5 "test" tx directly to say blockchain.info). Fee is just in accordance with the total tx size and UTXO "coin age" as per usual.
|
|
|
Well, I was told that if it had more than 3, it would be rejected by a lot of the network as it is not considered standard. Also, for DOGE, it simply fails.
I think your information is "out of date" when it comes to Bitcoin but it could well apply to clones based upon older source code.
|
|
|
This is because bitcoind only supports a max of 3 for multisig and it needs to be one less than 3
^ This is not correct - you might want to have a play with this: https://coinb.in/multisig/
|
|
|
But this way requires the script to be constantly polling for "triggers" (here am_type_subtype), which will require extra cycles (and hence cost) right? (Or would the extra cost be negligible?)
Indeed the normal thing for an AT to do *is* to poll for triggers, as transactions (which *are* its events) are exactly what drives it, so I don't really see that as "wasting cycles". The idea of the hibernation is just to stop it polling completely until a given block height (as I think that could be reasonable for some use cases). There might also be a case for being able to send an AT NXT without letting it execute code (will have to think about this as you wouldn't want the AT to be easily starved). It might also make sense to have an AT "priority" setting (a bit like task priority) so that lower priority ATs might only be run at most every X blocks. Although obviously a lot of careful measuring will need to be performed at the testnet stage the design itself is aimed at being very minimal in "cost" (current use cases would require no more than 1K of memory and would only need to execute 5..10 instructions per "poll".
|
|
|
@Zahlen and @Fry thanks for taking the time to read the spec. and comment. I had thought about "events" but am worried it will complicate the design also I think that the functionality you are wanting can be achieved without too much coding effort. Consider this (taken from the Dormant Funds Transfer use case): :loop get tx at after @timestamp and store in @txid if @txid is zero finish get timestamp for @txid and store in @tx_time get tx type for @txid and store in @tx_info if @tx_info != @am_type_subtype goto skip
So although the basic rule is that for the "event to run" a tx is sent to the AT with enough fees to pay for execution (unless it is in hibernation) the API functions will make it easy enough for the AT to determine what kind of tx has arrived and therefore what to do about it (you could create a bunch of subroutines which are called according to the @am_type_subtype or according to data in an AM, etc.). Understand also that the hibernation idea is simply for an AT to be able to "save wasted cycles" as even if execution is being paid for there is no point in it just checking the block height and stopping. In regards to "subleq" I thought it was doing what I had read but if it isn't then don't worry James - it can easily be fixed up.
|
|
|
Of course one could put a CAPTCHA to prevent robots, but it is inevitable that people with a lot of ressource will cast more than their share of votes; for example by paying (many) people to register multiple accounts and then vote.
You see - keep trying - there is simply *no* way to do it which is perhaps why we need to get over the whole "1 person 1 vote" concept.
|
|
|
|