Dev

This page is for Byteball developer use. It is not dumbed down at all for non-techies.

New bot developers

If you know next to nothing about Byteball, then download/install a regular light client like a normal person would, and get familiar with some existing bots in the Bot Store (Chat > Bot Store). The full client may take a few days to sync up. Same thing goes for the headless wallet (see below) - you can start developing faster if you run the bot also in light mode (by setting conf.bLight value to true).

To look into how bots are written, see the Github tutorials at https://github.com/byteball/byteballcore/wiki/Writing-chatbots-for-Byteball.

Getting your hands dirty
What might help most to understand how bots work is to try to get an existing bot working on your machine, such as https://github.com/byteball/email-attestation. If you are able to get that bot running, you can try get any other bot running that can be found on Byteball Github account https://github.com/byteball and after that you are probably ready to start developing your own bot by following the Developer Guides Wiki: https://github.com/byteball/byteballcore/wiki/Byteball-Developer-Guides

Headless wallet
A headless wallet is like a normal wallet, but without user interface, intended for software code interaction with the Byteball DAG.

More about headless wallet:

Sending payments
Look how existing bots send payments:

TESTNET
There are commands in `testnetify.sh` file, which need to be run after `npm install` to edit some values in byteballcore library. It will make the bot to communicate with testnet hub, but important thing is to remember that you need to delete your bots existing databases when you already ran the bot on default MAINNET DAG: https://explorer.byteball.org/. Also, TESTNET wallet at https://byteball.org/testnet.html is also not up-to-date with all the features (single-address wallets & private profile requests) that default MAINNET wallet (https://byteball.org/#download) has, so it might be more complicated to develop some features with that wallet app, but the good thing is that you can ask bytes from faucet and write into TESTNET DAG at https://testnetexplorer.byteball.org without worrying that you mess something up.

Byteball-to-TCP Proxy

With the help of this special chatbot it is possible to develop the actual bot in any programming language. Byteball-to-TCP Proxy (bb2tcp) listens on the Byteball network like a regular chatbot, except that for each paired device it establishes a new TCP connection to a predefined server. Thus, it acts as a proxy between a custom TCP server and the paired Byteball client device.

This software makes it no longer necessary for the Byteball chatbots to be developed in Node.js. Thus, the developer is free to choose whichever programming language they prefer for the bot. What is more, bb2tcp can be configured to send notifications to a custom server upon any pairing attempts. The latter can be used to implement two-factor or passwordless authentication (for example, see Slice&Dice Dungeon ).

To implement passwordless authentication with the help of Byteball, the application should present the user with a customly generated QR code. The payload of that QR code should contain a pairing link such as byteball:A/SCXz5tNuJDLuCO8PXpsfUoL7dCMBGnvSST7z0YPXjd@byteball.org/bb#bki433fsb where the end part (in bold) is randomly generated by the server. When the user scans the given QR code with their Byteball device a pairing attempt with the code bki433fsb is made and the bb2tcp chatbot notifies the application by sending the device address and the provided pairing code to the application server. The application server then knows which Byteball device is attempting to authorize themselves so the respective user session's privileges could be elevated immediately without any input from the user.

The bb2tcp chatbot is developed and maintained by @hyena from the Byteball's official Slack. All questions and ideas for enhancements are welcome.


Byteball address validation in C++

<syntaxhighlight lang="cpp">
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <type_traits>

bool is_byteball_addr(const char *addr) {
    static const unsigned char offsets[] = {
          1,   5,   6,  11,  20,  22,  28,  33,
         36,  41,  49,  58,  65,  74,  77,  79,
         82,  90,  94, 100, 102, 108, 112, 115,
        118, 126, 129, 131, 138, 147, 152, 154
    };
    const size_t offsets_sz = std::extent<decltype(offsets)>::value;
    bool bits[32*5];
    unsigned char data[16];
    unsigned char checksum[4];

    { // Base32 validation and decoding.
        auto b32 = [](char c) -> unsigned char {
            return ( (c >= 65 && c <= 90) ? (unsigned char) (     c - 65) :
                     (c >= 50 && c <= 55) ? (unsigned char) (26 + c - 50) : 255 );
        };

        auto isb32 = [](char c) -> bool {
            return ( (c >= 65 && c <= 90) || (c >= 50 && c <= 55) );
        };

        size_t i = 0;
        char *c = (char *) &(*addr);
        while (isb32(*c) && i < 32) {
            unsigned char value = b32(*c++);
            for (size_t j=0; j<5; ++j) {
                bool bit = (value % 2);
                value /= 2;
                bits[5*i + (4-j)] = bit;
            }
            ++i;
        }
        if (i != 32 || *c) return false;
    }

    { // Separation of the checksum from the clean data.
        auto bits2bytes = [](bool *b, unsigned char *B, size_t sz) -> void {
            for (size_t i=0; i<sz; ++i) {
                unsigned char byte = 0;
                for (size_t j=0; j<8; ++j) {
                    bool bit = b[i*8 + j];
                    byte ^= (unsigned char) ( (-bit ^ byte) & (1 << (7-j)) );
                }
                B[i] = byte;
            }
        };

        bool data_bits[128];
        bool checksum_bits[32];
        size_t start = 0;
        size_t data_bit_i = 0;
        size_t checksum_bit_i = 0;
        for (size_t i=0; i<offsets_sz; ++i) {
            for (size_t j=start; j<offsets[i]; ++j) {
                data_bits[data_bit_i++] = bits[j];
            }
            checksum_bits[checksum_bit_i++] = bits[offsets[i]];
            start = offsets[i]+1;
        }
        memcpy(data_bits+123, bits+155, 5); // Add last fragment.

        bits2bytes(data_bits, data, 16);
        bits2bytes(checksum_bits, checksum, 4);
    }

    { // Validate the checksum (requires the openssl/sha.h header).
        SHA256_CTX context;
        unsigned char md[SHA256_DIGEST_LENGTH];

        SHA256_Init(&context);
        SHA256_Update(&context, (unsigned char*) data, 16);
        SHA256_Final(md, &context);

        if (md[ 5] == checksum[0]
        &&  md[13] == checksum[1]
        &&  md[21] == checksum[2]
        &&  md[29] == checksum[3]) return true;
    }

    return false;
}

int main( int argc, char * argv [] ) {
    int i;

    for (i = 1; i < argc; ++i ) {
        bool valid = is_byteball_addr(argv[i]);
        printf( "%s is %s\n", argv[i], valid ? "VALID." : "INVALID!");
    }

    return 0;
}

</syntaxhighlight>

byteball github repo[1]

Consensus

A Slack #tech conversation 28/29 March 2018.

angrytree [10:25 PM]: posted in #general, want to see if anyone from byteball can clarify - question about double spending - if a user violates the rule that requires all his txns to have partial order, what's to stop him? do we just go back to the non serial case? for example, if i introduced a pair of conflicting double spending txns, would one be accepted eventually as stated in 4.2? or would both be discarded? if it's the former case, what's the point of introducing the partial order requirement then? looks like witness is used to help with resolving double spending anyway. looks to me, the arbitrary rule of requiring partial order of one's own txns could make byteball prone to censorship attack
Punqtured [10:44 PM]: @angrytree Is what you're trying to learn, whether the platform will be prone to censorship from witnesses? If so, you're right. The witnesses should therefore be entities with "real world value" at stake. If they misbehave, they will not only be rejected as witnesses, but also lose reputation and credibility in the real world. Think of companies that can't accept to be linked to dubious behavior. That's probably the best explanation I can give about the witnesses. The network relies on witnesses and therefore, in theory, they could collude and censor the platform. It would require the majority of witnesses to collude, for it to be effective, though. When witnesses gets decentralized (this is an issue as of yet) it would be unlikely that 6 different companies with 6 different interests would agree to have their name and reputation spoiled by colluding. The witnesses are covered in the presentation from slide 28
angrytree [10:58 PM]: thanks @Punqtured for the explanation :slightly_smiling_face: but what i'm trying to learn right now is mostly the scenario without witnesses, as a clean thought experiment for other DAG consensus algos as well. If I'm required to have partial order of all my own txns, and I want to get my txns "confirmed" as fast as possible, then I'm prone not to include other people's txns as that takes time. If everyone does that, then it poses a risk of censorship. That's what I see the downside in requiring partial order of one's own txns, so I want get to the bottom of why it's needed in the first place :slightly_smiling_face:
Punqtured [11:01 PM]: Why would referencing your own txns be faster than referencing any others'? (edited)
angrytree [11:13 PM]: borrowing bitcoin's example, may not be applicable to byteball - the txns verification takes time + i don't want my competitors to know the most up to date information. Here in Byteball, seems like only witnesses earn bytes from verifying txns anyway? So I don't see an incentive for normal users to help each other, other than altruism. but what i'm really interested about is just the dag consensus part - partial ordering and double spending
HHugh [11:22 PM]: From what I understand the fee is split into to categories: header fee and payload fee. Payload fee (about 40% for simple transfers) is equal to the size in bytes of the message; header fee (about 60%) is the balance of the data size. The witnesses collect the payload fee and the header fee goes to whichever user who posts the next child transaction. So a financial incentive exists (however small) to link to childless parent units. Check out pg 17 #13 of the whitepaper for details.
angrytree [11:26 PM]: yeah that's right, thx! ^^ would still love to get some clarification with regard to the partial ordering requirement
HHugh [11:31 PM]: That's beyond me... sorry. Sounds like you're considering forking options?
angrytree [11:33 PM]: yeah looking at the extreme version of this is hashgraph/nano, where everyone has his own chain, but they have their own problems too

tonych [12:18 AM]: @angrytree at least one of the two conflicting transactions will be censored. Not by witnesses, by everybody who follows the protocol.

angrytree [12:30 AM]: @tonych censored? what's the rule?

tonych [12:51 AM]: the rule that txns from the same address must be in partial order

angrytree [12:52 AM]: no i mean what's the rule for which txn to censor if I have a pair of conflicting double-spending txn?

tonych [12:53 AM]: the one that is later on the main chain

angrytree [12:55 AM]: hmm you sure? what if they forking off the same parent? even with different parents, how does the clients reach consensus on that? there could be many edge cases. eg. if the attacker send one txn to one set of users; then the other to another set of users

tonych [1:04 AM]: there is an unambiguous way to compare transactions. If their MCIs are equal, we compare the hashes.

Milan Horvath [5:32 AM]: I think it would be great to hire an "auditor" company/team to review the white paper for all these questions to have an independent opinion about the consensus mechanism, and about the double spending prevention!
angrytree [6:01 AM]: @tonych what about if the attacker shuffles the order of the two conflicting txns, and send to two different sets of users? wouldn't one group censors one, then the other censors the other? how would this be mediated?

tonych [12:23 PM]: this is a good question and this a basic requirement for every working consensus algo that it should be protected from partitioning. The answer is that both sets of users must accept both txs. The order of transactions (hence voiding of the tx that appears to be later) is decided only after they become final, i.e. when reordering of these transactions becomes impossible.

angrytree [7:40 PM]: when user X broadcasts a txn to group A, and not to group B, will the group A relay this txn to group B (other than just referencing the hash of it as a parent)? i guess since it's asynchronous system, if X broadcasts a conflicting set of double spends, there's no guarantee they will all be "final" at the same round right?

tonych [12:31 AM]: @angrytree all transactions are relayed to peers, including the doublespends. Of course, we cannot rely on it. what is a "round"?

angrytree [12:33 AM]: thanks! thought that's something normal to do, but don't recall reading in wp. what i meant by "round" was each time the stability point advances - in the context of my last question, there's no guarantee both the double spends get in before the stability point advances right? so some clients may see txn A before the stability point, and that one becomes final, and then the txn B arrives after the stability point. For some other clients, they may have a different view depending on how the conflicting txns are propagated, and get the txn B before the stability point, and txn A after. how does the system deal with this case? also if the double spends order is decided *after* becoming final - that means all the parties will have to do verification again after they are "confirmed"? normally finality == txn sent/received

tonych [1:12 AM]: this case is just impossible. Finality means that the transactions cannot be reordered and all nodes agree about the order of transactions before the stability point. What you describe just contradicts finality. no need to do verification again. When reaching finality, the doublespends are just marked as such

angrytree [2:52 AM]: so basically is the safety guarantee that all honest nodes in the network have a consistent view of the MCI of all txns up to the stability point? I don't remember reading about how partition is dealt with in detail. also is this the right repo for consensus? - https://github.com/byteball/byteballcore
angrytree [3:23 AM]: btw, thanks for your time in the discussion :slightly_smiling_face: really interested in learning about these new consensus algos

tonych [10:16 AM]: yes, up to the stability point (or the earlier of the stability points of different nodes) all nodes have a consistent view of the ledger. yes this repo

Payment channels

Slack post by tonych [2018-04-01 4:22 PM]: Here is how payment channels can be implemented in BB: https://docs.google.com/document/d/19s4LYDfbWDREzVzUwxPuoKANeIGOgPGKV2zI9jTsPSg/edit#

References